Skip to content

Commit

Permalink
Add existence requirement (#1014)
Browse files Browse the repository at this point in the history
* add ExistenceRequirement

* fix

* update xcm-procedural:10.1.0 to work
  • Loading branch information
zjb0807 authored Jan 9, 2025
1 parent 286c731 commit 8285019
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 45 deletions.
1 change: 1 addition & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
tar -zxvf cargo-tarpaulin-x86_64-unknown-linux-musl.tar.gz -C $HOME/.cargo/bin
make Cargo.toml
cargo update
cargo update -p xcm-procedural --precise 10.1.0
cargo tarpaulin --verbose --no-fail-fast --workspace --timeout 300 --out Xml
- name: Upload to codecov.io
uses: codecov/codecov-action@v3
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ jobs:
- name: Install clippy
run: rustup component add clippy
- name: Update
run: cargo update
run: |
cargo update
cargo update -p xcm-procedural --precise 10.1.0
- name: Run clippy
run: cargo clippy -- -D warnings
- name: Check for Wasm
Expand Down
71 changes: 54 additions & 17 deletions currencies/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,13 @@ pub mod module {
) -> DispatchResult {
let from = ensure_signed(origin)?;
let to = T::Lookup::lookup(dest)?;
<Self as MultiCurrency<T::AccountId>>::transfer(currency_id, &from, &to, amount)
<Self as MultiCurrency<T::AccountId>>::transfer(
currency_id,
&from,
&to,
amount,
ExistenceRequirement::AllowDeath,
)
}

/// Transfer some native currency to another account.
Expand All @@ -150,7 +156,7 @@ pub mod module {
) -> DispatchResult {
let from = ensure_signed(origin)?;
let to = T::Lookup::lookup(dest)?;
T::NativeCurrency::transfer(&from, &to, amount)
T::NativeCurrency::transfer(&from, &to, amount, ExistenceRequirement::AllowDeath)
}

/// update amount of account `who` under `currency_id`.
Expand Down Expand Up @@ -220,14 +226,15 @@ impl<T: Config> MultiCurrency<T::AccountId> for Pallet<T> {
from: &T::AccountId,
to: &T::AccountId,
amount: Self::Balance,
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
if amount.is_zero() || from == to {
return Ok(());
}
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::transfer(from, to, amount)
T::NativeCurrency::transfer(from, to, amount, existence_requirement)
} else {
T::MultiCurrency::transfer(currency_id, from, to, amount)
T::MultiCurrency::transfer(currency_id, from, to, amount, existence_requirement)
}
}

Expand All @@ -242,14 +249,19 @@ impl<T: Config> MultiCurrency<T::AccountId> for Pallet<T> {
}
}

fn withdraw(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
fn withdraw(
currency_id: Self::CurrencyId,
who: &T::AccountId,
amount: Self::Balance,
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
if amount.is_zero() {
return Ok(());
}
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::withdraw(who, amount)
T::NativeCurrency::withdraw(who, amount, existence_requirement)
} else {
T::MultiCurrency::withdraw(currency_id, who, amount)
T::MultiCurrency::withdraw(currency_id, who, amount, existence_requirement)
}
}

Expand Down Expand Up @@ -475,16 +487,31 @@ where
<Pallet<T>>::ensure_can_withdraw(GetCurrencyId::get(), who, amount)
}

fn transfer(from: &T::AccountId, to: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T> as MultiCurrency<T::AccountId>>::transfer(GetCurrencyId::get(), from, to, amount)
fn transfer(
from: &T::AccountId,
to: &T::AccountId,
amount: Self::Balance,
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
<Pallet<T> as MultiCurrency<T::AccountId>>::transfer(
GetCurrencyId::get(),
from,
to,
amount,
existence_requirement,
)
}

fn deposit(who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T>>::deposit(GetCurrencyId::get(), who, amount)
}

fn withdraw(who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T>>::withdraw(GetCurrencyId::get(), who, amount)
fn withdraw(
who: &T::AccountId,
amount: Self::Balance,
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
<Pallet<T>>::withdraw(GetCurrencyId::get(), who, amount, existence_requirement)
}

fn can_slash(who: &T::AccountId, amount: Self::Balance) -> bool {
Expand Down Expand Up @@ -653,8 +680,13 @@ where
Currency::ensure_can_withdraw(who, amount, WithdrawReasons::all(), new_balance)
}

fn transfer(from: &AccountId, to: &AccountId, amount: Self::Balance) -> DispatchResult {
Currency::transfer(from, to, amount, ExistenceRequirement::AllowDeath)
fn transfer(
from: &AccountId,
to: &AccountId,
amount: Self::Balance,
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
Currency::transfer(from, to, amount, existence_requirement)
}

fn deposit(who: &AccountId, amount: Self::Balance) -> DispatchResult {
Expand All @@ -666,8 +698,8 @@ where
Ok(())
}

fn withdraw(who: &AccountId, amount: Self::Balance) -> DispatchResult {
Currency::withdraw(who, amount, WithdrawReasons::all(), ExistenceRequirement::AllowDeath).map(|_| ())
fn withdraw(who: &AccountId, amount: Self::Balance, existence_requirement: ExistenceRequirement) -> DispatchResult {
Currency::withdraw(who, amount, WithdrawReasons::all(), existence_requirement).map(|_| ())
}

fn can_slash(who: &AccountId, amount: Self::Balance) -> bool {
Expand Down Expand Up @@ -707,7 +739,7 @@ where
if by_amount.is_positive() {
Self::deposit(who, by_balance)
} else {
Self::withdraw(who, by_balance)
Self::withdraw(who, by_balance, ExistenceRequirement::AllowDeath)
}
}
}
Expand Down Expand Up @@ -817,7 +849,12 @@ impl<T: Config> TransferAll<T::AccountId> for Pallet<T> {
T::MultiCurrency::transfer_all(source, dest)?;

// transfer all free to dest
T::NativeCurrency::transfer(source, dest, T::NativeCurrency::free_balance(source))
T::NativeCurrency::transfer(
source,
dest,
T::NativeCurrency::free_balance(source),
ExistenceRequirement::AllowDeath,
)
})
}
}
38 changes: 32 additions & 6 deletions currencies/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,12 @@ fn native_currency_should_work() {
assert_eq!(NativeCurrency::free_balance(&ALICE), 50);
assert_eq!(NativeCurrency::free_balance(&BOB), 150);

assert_ok!(NativeCurrency::transfer(&ALICE, &BOB, 10));
assert_ok!(NativeCurrency::transfer(
&ALICE,
&BOB,
10,
ExistenceRequirement::AllowDeath
));
assert_eq!(NativeCurrency::free_balance(&ALICE), 40);
assert_eq!(NativeCurrency::free_balance(&BOB), 160);

Expand Down Expand Up @@ -251,12 +256,22 @@ fn basic_currency_adapting_pallet_balances_transfer() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
assert_ok!(AdaptedBasicCurrency::transfer(&ALICE, &BOB, 50));
assert_ok!(AdaptedBasicCurrency::transfer(
&ALICE,
&BOB,
50,
ExistenceRequirement::AllowDeath
));
assert_eq!(PalletBalances::total_balance(&ALICE), 50);
assert_eq!(PalletBalances::total_balance(&BOB), 150);

// creation fee
assert_ok!(AdaptedBasicCurrency::transfer(&ALICE, &EVA, 10));
assert_ok!(AdaptedBasicCurrency::transfer(
&ALICE,
&EVA,
10,
ExistenceRequirement::AllowDeath
));
assert_eq!(PalletBalances::total_balance(&ALICE), 40);
assert_eq!(PalletBalances::total_balance(&EVA), 10);
});
Expand Down Expand Up @@ -297,7 +312,11 @@ fn basic_currency_adapting_pallet_balances_withdraw() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
assert_ok!(AdaptedBasicCurrency::withdraw(&ALICE, 100));
assert_ok!(AdaptedBasicCurrency::withdraw(
&ALICE,
100,
ExistenceRequirement::AllowDeath
));
assert_eq!(PalletBalances::total_balance(&ALICE), 0);
assert_eq!(PalletBalances::total_issuance(), 100);
});
Expand Down Expand Up @@ -375,7 +394,11 @@ fn call_event_should_work() {
}));

assert_ok!(<Currencies as MultiCurrency<AccountId>>::transfer(
X_TOKEN_ID, &ALICE, &BOB, 10
X_TOKEN_ID,
&ALICE,
&BOB,
10,
ExistenceRequirement::AllowDeath
));
assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 40);
assert_eq!(Currencies::free_balance(X_TOKEN_ID, &BOB), 160);
Expand All @@ -397,7 +420,10 @@ fn call_event_should_work() {
}));

assert_ok!(<Currencies as MultiCurrency<AccountId>>::withdraw(
X_TOKEN_ID, &ALICE, 20
X_TOKEN_ID,
&ALICE,
20,
ExistenceRequirement::AllowDeath
));
assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 120);
System::assert_last_event(RuntimeEvent::Tokens(orml_tokens::Event::Withdrawn {
Expand Down
17 changes: 14 additions & 3 deletions payments/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ pub mod pallet {
weights::WeightInfo,
};
use frame_support::{
dispatch::DispatchResultWithPostInfo, fail, pallet_prelude::*, require_transactional,
storage::bounded_btree_map::BoundedBTreeMap, traits::tokens::BalanceStatus,
dispatch::DispatchResultWithPostInfo,
fail,
pallet_prelude::*,
require_transactional,
storage::bounded_btree_map::BoundedBTreeMap,
traits::{tokens::BalanceStatus, ExistenceRequirement},
};
use frame_system::pallet_prelude::*;
use orml_traits::{MultiCurrency, MultiReservableCurrency};
Expand Down Expand Up @@ -634,6 +638,7 @@ pub mod pallet {
from, // fee is paid by payment creator
&fee_recipient, // account of fee recipient
fee_amount, // amount of fee
ExistenceRequirement::AllowDeath,
)?;
}
}
Expand All @@ -648,7 +653,13 @@ pub mod pallet {
let amount_to_recipient = recipient_share.mul_floor(payment.amount);
let amount_to_sender = payment.amount.saturating_sub(amount_to_recipient);
// send share to recipient
T::Asset::transfer(payment.asset, to, from, amount_to_sender)?;
T::Asset::transfer(
payment.asset,
to,
from,
amount_to_sender,
ExistenceRequirement::AllowDeath,
)?;

Ok(())
})?;
Expand Down
14 changes: 10 additions & 4 deletions tokens/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,9 +1161,10 @@ impl<T: Config> MultiCurrency<T::AccountId> for Pallet<T> {
from: &T::AccountId,
to: &T::AccountId,
amount: Self::Balance,
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
// allow death
Self::do_transfer(currency_id, from, to, amount, ExistenceRequirement::AllowDeath)
Self::do_transfer(currency_id, from, to, amount, existence_requirement)
}

fn deposit(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
Expand All @@ -1172,9 +1173,14 @@ impl<T: Config> MultiCurrency<T::AccountId> for Pallet<T> {
Ok(())
}

fn withdraw(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
fn withdraw(
currency_id: Self::CurrencyId,
who: &T::AccountId,
amount: Self::Balance,
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
// allow death
Self::do_withdraw(currency_id, who, amount, ExistenceRequirement::AllowDeath, true)
Self::do_withdraw(currency_id, who, amount, existence_requirement, true)
}

// Check if `value` amount of free balance can be slashed from `who`.
Expand Down Expand Up @@ -1269,7 +1275,7 @@ impl<T: Config> MultiCurrencyExtended<T::AccountId> for Pallet<T> {
if by_amount.is_positive() {
Self::deposit(currency_id, who, by_balance)
} else {
Self::withdraw(currency_id, who, by_balance).map(|_| ())
Self::withdraw(currency_id, who, by_balance, ExistenceRequirement::AllowDeath).map(|_| ())
}
}
}
Expand Down
15 changes: 13 additions & 2 deletions tokens/src/tests_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ fn pallet_multicurrency_deposit_events() {
.balances(vec![(ALICE, DOT, 100), (BOB, DOT, 100)])
.build()
.execute_with(|| {
assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(DOT, &ALICE, &BOB, 10));
assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(
DOT,
&ALICE,
&BOB,
10,
ExistenceRequirement::AllowDeath
));
System::assert_last_event(RuntimeEvent::Tokens(crate::Event::Transfer {
currency_id: DOT,
from: ALICE,
Expand All @@ -35,7 +41,12 @@ fn pallet_multicurrency_deposit_events() {
amount: 10,
}));

assert_ok!(<Tokens as MultiCurrency<AccountId>>::withdraw(DOT, &ALICE, 10));
assert_ok!(<Tokens as MultiCurrency<AccountId>>::withdraw(
DOT,
&ALICE,
10,
ExistenceRequirement::AllowDeath
));
System::assert_last_event(RuntimeEvent::Tokens(crate::Event::Withdrawn {
currency_id: DOT,
who: ALICE,
Expand Down
12 changes: 9 additions & 3 deletions tokens/src/tests_multicurrency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn multicurrency_withdraw_work() {
assert!(Accounts::<Runtime>::contains_key(ALICE, DOT));
assert_eq!(Tokens::free_balance(DOT, &ALICE), 100);
assert_eq!(Tokens::total_issuance(DOT), 100);
assert_ok!(Tokens::withdraw(DOT, &ALICE, 99));
assert_ok!(Tokens::withdraw(DOT, &ALICE, 99, ExistenceRequirement::AllowDeath));
assert!(!Accounts::<Runtime>::contains_key(ALICE, DOT));
assert_eq!(Tokens::free_balance(DOT, &ALICE), 0);
assert_eq!(Tokens::total_issuance(DOT), 1);
Expand All @@ -44,7 +44,13 @@ fn multicurrency_transfer_work() {
assert!(Accounts::<Runtime>::contains_key(ALICE, DOT));
assert_eq!(Tokens::free_balance(DOT, &ALICE), 100);
assert_eq!(Tokens::free_balance(DOT, &BOB), 100);
assert_ok!(<Tokens as MultiCurrency<_>>::transfer(DOT, &ALICE, &BOB, 99));
assert_ok!(<Tokens as MultiCurrency<_>>::transfer(
DOT,
&ALICE,
&BOB,
99,
ExistenceRequirement::AllowDeath
));
assert!(!Accounts::<Runtime>::contains_key(ALICE, DOT));
assert_eq!(Tokens::free_balance(DOT, &ALICE), 0);
assert_eq!(Tokens::free_balance(DOT, &BOB), 199);
Expand Down Expand Up @@ -379,7 +385,7 @@ fn no_op_if_amount_is_zero() {
assert_ok!(Tokens::transfer(Some(ALICE).into(), BOB, DOT, 0));
assert_ok!(Tokens::transfer(Some(ALICE).into(), ALICE, DOT, 0));
assert_ok!(Tokens::deposit(DOT, &ALICE, 0));
assert_ok!(Tokens::withdraw(DOT, &ALICE, 0));
assert_ok!(Tokens::withdraw(DOT, &ALICE, 0, ExistenceRequirement::AllowDeath));
assert_eq!(Tokens::slash(DOT, &ALICE, 0), 0);
assert_eq!(Tokens::slash(DOT, &ALICE, 1), 1);
assert_ok!(Tokens::update_balance(DOT, &ALICE, 0));
Expand Down
Loading

0 comments on commit 8285019

Please sign in to comment.