diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index b4afe49cf..babc0d4f7 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -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 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dfe572303..2659e4273 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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 diff --git a/currencies/src/lib.rs b/currencies/src/lib.rs index 10a109158..a5f989b6a 100644 --- a/currencies/src/lib.rs +++ b/currencies/src/lib.rs @@ -134,7 +134,13 @@ pub mod module { ) -> DispatchResult { let from = ensure_signed(origin)?; let to = T::Lookup::lookup(dest)?; - >::transfer(currency_id, &from, &to, amount) + >::transfer( + currency_id, + &from, + &to, + amount, + ExistenceRequirement::AllowDeath, + ) } /// Transfer some native currency to another account. @@ -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`. @@ -220,14 +226,15 @@ impl MultiCurrency for Pallet { 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) } } @@ -242,14 +249,19 @@ impl MultiCurrency for Pallet { } } - 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) } } @@ -475,16 +487,31 @@ where >::ensure_can_withdraw(GetCurrencyId::get(), who, amount) } - fn transfer(from: &T::AccountId, to: &T::AccountId, amount: Self::Balance) -> DispatchResult { - as MultiCurrency>::transfer(GetCurrencyId::get(), from, to, amount) + fn transfer( + from: &T::AccountId, + to: &T::AccountId, + amount: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> DispatchResult { + as MultiCurrency>::transfer( + GetCurrencyId::get(), + from, + to, + amount, + existence_requirement, + ) } fn deposit(who: &T::AccountId, amount: Self::Balance) -> DispatchResult { >::deposit(GetCurrencyId::get(), who, amount) } - fn withdraw(who: &T::AccountId, amount: Self::Balance) -> DispatchResult { - >::withdraw(GetCurrencyId::get(), who, amount) + fn withdraw( + who: &T::AccountId, + amount: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> DispatchResult { + >::withdraw(GetCurrencyId::get(), who, amount, existence_requirement) } fn can_slash(who: &T::AccountId, amount: Self::Balance) -> bool { @@ -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 { @@ -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 { @@ -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) } } } @@ -817,7 +849,12 @@ impl TransferAll for Pallet { 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, + ) }) } } diff --git a/currencies/src/tests.rs b/currencies/src/tests.rs index 091b599ce..b6438252a 100644 --- a/currencies/src/tests.rs +++ b/currencies/src/tests.rs @@ -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); @@ -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); }); @@ -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); }); @@ -375,7 +394,11 @@ fn call_event_should_work() { })); assert_ok!(>::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); @@ -397,7 +420,10 @@ fn call_event_should_work() { })); assert_ok!(>::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 { diff --git a/payments/src/lib.rs b/payments/src/lib.rs index bd941b3d9..b97fd5640 100644 --- a/payments/src/lib.rs +++ b/payments/src/lib.rs @@ -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}; @@ -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, )?; } } @@ -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(()) })?; diff --git a/tokens/src/lib.rs b/tokens/src/lib.rs index 314066671..315effc5d 100644 --- a/tokens/src/lib.rs +++ b/tokens/src/lib.rs @@ -1161,9 +1161,10 @@ impl MultiCurrency for Pallet { 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 { @@ -1172,9 +1173,14 @@ impl MultiCurrency for Pallet { 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`. @@ -1269,7 +1275,7 @@ impl MultiCurrencyExtended for Pallet { 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(|_| ()) } } } diff --git a/tokens/src/tests_events.rs b/tokens/src/tests_events.rs index df79ed80f..a81284e8f 100644 --- a/tokens/src/tests_events.rs +++ b/tokens/src/tests_events.rs @@ -20,7 +20,13 @@ fn pallet_multicurrency_deposit_events() { .balances(vec![(ALICE, DOT, 100), (BOB, DOT, 100)]) .build() .execute_with(|| { - assert_ok!(>::transfer(DOT, &ALICE, &BOB, 10)); + assert_ok!(>::transfer( + DOT, + &ALICE, + &BOB, + 10, + ExistenceRequirement::AllowDeath + )); System::assert_last_event(RuntimeEvent::Tokens(crate::Event::Transfer { currency_id: DOT, from: ALICE, @@ -35,7 +41,12 @@ fn pallet_multicurrency_deposit_events() { amount: 10, })); - assert_ok!(>::withdraw(DOT, &ALICE, 10)); + assert_ok!(>::withdraw( + DOT, + &ALICE, + 10, + ExistenceRequirement::AllowDeath + )); System::assert_last_event(RuntimeEvent::Tokens(crate::Event::Withdrawn { currency_id: DOT, who: ALICE, diff --git a/tokens/src/tests_multicurrency.rs b/tokens/src/tests_multicurrency.rs index 0db833786..f1a5684a1 100644 --- a/tokens/src/tests_multicurrency.rs +++ b/tokens/src/tests_multicurrency.rs @@ -28,7 +28,7 @@ fn multicurrency_withdraw_work() { assert!(Accounts::::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::::contains_key(ALICE, DOT)); assert_eq!(Tokens::free_balance(DOT, &ALICE), 0); assert_eq!(Tokens::total_issuance(DOT), 1); @@ -44,7 +44,13 @@ fn multicurrency_transfer_work() { assert!(Accounts::::contains_key(ALICE, DOT)); assert_eq!(Tokens::free_balance(DOT, &ALICE), 100); assert_eq!(Tokens::free_balance(DOT, &BOB), 100); - assert_ok!(>::transfer(DOT, &ALICE, &BOB, 99)); + assert_ok!(>::transfer( + DOT, + &ALICE, + &BOB, + 99, + ExistenceRequirement::AllowDeath + )); assert!(!Accounts::::contains_key(ALICE, DOT)); assert_eq!(Tokens::free_balance(DOT, &ALICE), 0); assert_eq!(Tokens::free_balance(DOT, &BOB), 199); @@ -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)); diff --git a/traits/src/currency.rs b/traits/src/currency.rs index e1772d27c..6ab8ed967 100644 --- a/traits/src/currency.rs +++ b/traits/src/currency.rs @@ -1,5 +1,5 @@ use crate::{arithmetic, Happened}; -use frame_support::traits::tokens::Balance; +use frame_support::traits::{tokens::Balance, ExistenceRequirement}; pub use frame_support::{ traits::{BalanceStatus, DefensiveSaturating, LockIdentifier}, transactional, @@ -56,6 +56,7 @@ pub trait MultiCurrency { from: &AccountId, to: &AccountId, amount: Self::Balance, + existence_requirement: ExistenceRequirement, ) -> DispatchResult; /// Add `amount` to the balance of `who` under `currency_id` and increase @@ -64,7 +65,12 @@ pub trait MultiCurrency { /// Remove `amount` from the balance of `who` under `currency_id` and reduce /// total issuance. - fn withdraw(currency_id: Self::CurrencyId, who: &AccountId, amount: Self::Balance) -> DispatchResult; + fn withdraw( + currency_id: Self::CurrencyId, + who: &AccountId, + amount: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> DispatchResult; /// Same result as `slash(currency_id, who, value)` (but without the /// side-effects) assuming there are no balance changes in the meantime and @@ -381,13 +387,18 @@ pub trait BasicCurrency { // Public mutables /// Transfer some amount from one account to another. - fn transfer(from: &AccountId, to: &AccountId, amount: Self::Balance) -> DispatchResult; + fn transfer( + from: &AccountId, + to: &AccountId, + amount: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> DispatchResult; /// Add `amount` to the balance of `who` and increase total issuance. fn deposit(who: &AccountId, amount: Self::Balance) -> DispatchResult; /// Remove `amount` from the balance of `who` and reduce total issuance. - fn withdraw(who: &AccountId, amount: Self::Balance) -> DispatchResult; + fn withdraw(who: &AccountId, amount: Self::Balance, existence_requirement: ExistenceRequirement) -> DispatchResult; /// Same result as `slash(who, value)` (but without the side-effects) /// assuming there are no balance changes in the meantime and only the diff --git a/xcm-support/src/currency_adapter.rs b/xcm-support/src/currency_adapter.rs index ad78676a7..01c95ef6a 100644 --- a/xcm-support/src/currency_adapter.rs +++ b/xcm-support/src/currency_adapter.rs @@ -1,4 +1,4 @@ -use frame_support::traits::Get; +use frame_support::traits::{ExistenceRequirement, Get}; use parity_scale_codec::FullCodec; use sp_runtime::{ traits::{Convert, MaybeSerializeDeserialize, SaturatedConversion}, @@ -173,7 +173,8 @@ impl< let amount: MultiCurrency::Balance = Match::matches_fungible(asset) .ok_or_else(|| XcmError::from(Error::FailedToMatchFungible))? .saturated_into(); - MultiCurrency::withdraw(currency_id, &who, amount).map_err(|e| XcmError::FailedToTransactAsset(e.into())) + MultiCurrency::withdraw(currency_id, &who, amount, ExistenceRequirement::AllowDeath) + .map_err(|e| XcmError::FailedToTransactAsset(e.into())) })?; Ok(asset.clone().into()) @@ -194,8 +195,14 @@ impl< let amount: MultiCurrency::Balance = Match::matches_fungible(asset) .ok_or_else(|| XcmError::from(Error::FailedToMatchFungible))? .saturated_into(); - MultiCurrency::transfer(currency_id, &from_account, &to_account, amount) - .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?; + MultiCurrency::transfer( + currency_id, + &from_account, + &to_account, + amount, + ExistenceRequirement::AllowDeath, + ) + .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?; Ok(asset.clone().into()) } diff --git a/xtokens/src/mock/teleport_currency_adapter.rs b/xtokens/src/mock/teleport_currency_adapter.rs index 8f44dd75e..8a2a4030c 100644 --- a/xtokens/src/mock/teleport_currency_adapter.rs +++ b/xtokens/src/mock/teleport_currency_adapter.rs @@ -1,3 +1,4 @@ +use frame_support::traits::ExistenceRequirement; use parity_scale_codec::FullCodec; use sp_runtime::traits::{Convert, MaybeSerializeDeserialize, SaturatedConversion}; use sp_std::{ @@ -121,7 +122,8 @@ impl< let amount: MultiCurrency::Balance = Match::matches_fungible(asset) .ok_or_else(|| XcmError::from(Error::FailedToMatchFungible))? .saturated_into(); - MultiCurrency::withdraw(currency_id, &who, amount).map_err(|e| XcmError::FailedToTransactAsset(e.into())) + MultiCurrency::withdraw(currency_id, &who, amount, ExistenceRequirement::AllowDeath) + .map_err(|e| XcmError::FailedToTransactAsset(e.into())) })?; Ok(asset.clone().into())