From 7bcdb3cb0c95953a8ee6bac8eb7463d8e0913c27 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Rios Date: Fri, 4 Oct 2024 11:13:27 +0200 Subject: [PATCH] usdt-fee-pjs-compatibility --- Cargo.lock | 1 + integration-tests/src/tests/otm_edge_cases.rs | 50 +++++++++++-------- .../src/tests/transaction_payment.rs | 10 ++-- runtimes/polimec/src/lib.rs | 15 ++++++ runtimes/shared-configuration/Cargo.toml | 2 +- runtimes/shared-configuration/src/fee.rs | 18 ++++--- 6 files changed, 65 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a15f7a2b8..f7ef0fc63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13216,6 +13216,7 @@ dependencies = [ "sp-arithmetic", "sp-runtime", "sp-std", + "staging-xcm", ] [[package]] diff --git a/integration-tests/src/tests/otm_edge_cases.rs b/integration-tests/src/tests/otm_edge_cases.rs index 1778f4fad..9b5e3564c 100644 --- a/integration-tests/src/tests/otm_edge_cases.rs +++ b/integration-tests/src/tests/otm_edge_cases.rs @@ -31,11 +31,8 @@ fn cannot_have_otm_fee_below_min_amount() { PolimecNet::execute_with(|| { let mut project_metadata = default_project_metadata(issuer.clone()); - project_metadata.participation_currencies = bounded_vec![ - AcceptedFundingAsset::USDT, - AcceptedFundingAsset::USDC, - AcceptedFundingAsset::DOT, - ]; + project_metadata.participation_currencies = + bounded_vec![AcceptedFundingAsset::USDT, AcceptedFundingAsset::USDC, AcceptedFundingAsset::DOT,]; let usdt_price = ::PriceProvider::get_decimals_aware_price( AcceptedFundingAsset::USDT.id(), @@ -70,19 +67,19 @@ fn cannot_have_otm_fee_below_min_amount() { let min_usd_otm_fee = Perbill::from_rational(15u32, 100u32) * min_usd_contribution; let mut min_usdt_contribution = usdt_price.reciprocal().unwrap().saturating_mul_int(min_usd_contribution); - while usdt_price.saturating_mul_int(min_usdt_contribution) < min_usd_contribution { - min_usdt_contribution += 1; - } + while usdt_price.saturating_mul_int(min_usdt_contribution) < min_usd_contribution { + min_usdt_contribution += 1; + } let mut min_usdc_contribution = usdc_price.reciprocal().unwrap().saturating_mul_int(min_usd_contribution); - while usdc_price.saturating_mul_int(min_usdc_contribution) < min_usd_contribution { - min_usdc_contribution += 1; - } + while usdc_price.saturating_mul_int(min_usdc_contribution) < min_usd_contribution { + min_usdc_contribution += 1; + } let mut min_dot_contribution = dot_price.reciprocal().unwrap().saturating_mul_int(min_usd_contribution); - while dot_price.saturating_mul_int(min_dot_contribution) < min_usd_contribution { - min_dot_contribution += 1; - } + while dot_price.saturating_mul_int(min_dot_contribution) < min_usd_contribution { + min_dot_contribution += 1; + } let min_usdt_contribution_otm_fee = usdt_price.reciprocal().unwrap().saturating_mul_int(min_usd_otm_fee); let min_usdc_contribution_otm_fee = usdc_price.reciprocal().unwrap().saturating_mul_int(min_usd_otm_fee); @@ -112,11 +109,23 @@ fn cannot_have_otm_fee_below_min_amount() { inst.mint_plmc_to(vec![(bobert.clone(), plmc_ed).into()]); inst.mint_funding_asset_to(vec![ - (bobert.clone(), min_usdt_contribution + min_usdt_contribution_otm_fee + 10_000, AcceptedFundingAsset::USDT.id()) + ( + bobert.clone(), + min_usdt_contribution + min_usdt_contribution_otm_fee + 10_000, + AcceptedFundingAsset::USDT.id(), + ) .into(), - (bobert.clone(), min_usdc_contribution + min_usdc_contribution_otm_fee + 10_000, AcceptedFundingAsset::USDC.id()) + ( + bobert.clone(), + min_usdc_contribution + min_usdc_contribution_otm_fee + 10_000, + AcceptedFundingAsset::USDC.id(), + ) .into(), - (bobert.clone(), min_dot_contribution + min_dot_contribution_otm_fee + 10_000, AcceptedFundingAsset::DOT.id()) + ( + bobert.clone(), + min_dot_contribution + min_dot_contribution_otm_fee + 10_000, + AcceptedFundingAsset::DOT.id(), + ) .into(), ]); @@ -130,9 +139,9 @@ fn cannot_have_otm_fee_below_min_amount() { asset )); }; - contribute_is_ok_with(AcceptedFundingAsset::USDT, ct_for_min_usdt_contribution); - contribute_is_ok_with(AcceptedFundingAsset::USDC, ct_for_min_usdc_contribution); - contribute_is_ok_with(AcceptedFundingAsset::DOT, ct_for_min_dot_contribution); + contribute_is_ok_with(AcceptedFundingAsset::USDT, ct_for_min_usdt_contribution); + contribute_is_ok_with(AcceptedFundingAsset::USDC, ct_for_min_usdc_contribution); + contribute_is_ok_with(AcceptedFundingAsset::DOT, ct_for_min_dot_contribution); }); } @@ -185,6 +194,5 @@ fn after_otm_fee_user_goes_under_ed() { // Somehow still exists because sufficients = 1 assert!(PolimecSystem::account_exists(&bobert)); dbg!(PolimecSystem::account(&bobert)); - }); } diff --git a/integration-tests/src/tests/transaction_payment.rs b/integration-tests/src/tests/transaction_payment.rs index 6b0df250d..3f37684a5 100644 --- a/integration-tests/src/tests/transaction_payment.rs +++ b/integration-tests/src/tests/transaction_payment.rs @@ -21,7 +21,7 @@ use sp_runtime::{ use xcm_emulator::TestExt; generate_accounts!(ALICE, AUTHOR); use frame_support::traits::fungible::Inspect; - +use xcm::v3::{Junction::*, Junctions::*, MultiLocation}; // Setup code inspired by pallet-authorship tests fn seal_header(mut header: Header, aura_index: u64) -> Header { { @@ -60,6 +60,8 @@ fn fee_paid_with_foreign_assets() { assert_eq!(polimec_runtime::Authorship::author(), Some(block_author.clone())); let usdt_id = AcceptedFundingAsset::USDT.id(); + let usdt_multilocation = + MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) }; let usdt_decimals = >::decimals(usdt_id); let usdt_unit = 10u128.pow(usdt_decimals as u32); let plmc_decimals = PLMC_DECIMALS; @@ -78,8 +80,10 @@ fn fee_paid_with_foreign_assets() { let paid_call = PolimecCall::System(frame_system::Call::remark { remark: vec![69, 69] }); type TxPaymentExtension = pallet_asset_tx_payment::ChargeAssetTxPayment; - let signed_extension = - pallet_asset_tx_payment::ChargeAssetTxPayment::::from(10 * plmc_unit, Some(usdt_id)); + let signed_extension = pallet_asset_tx_payment::ChargeAssetTxPayment::::from( + 10 * plmc_unit, + Some(usdt_multilocation), + ); let dispatch_info = paid_call.get_dispatch_info(); let FeeDetails { inclusion_fee, tip } = diff --git a/runtimes/polimec/src/lib.rs b/runtimes/polimec/src/lib.rs index 428b98c82..7bdcf4246 100644 --- a/runtimes/polimec/src/lib.rs +++ b/runtimes/polimec/src/lib.rs @@ -93,6 +93,7 @@ use polimec_common::{ProvideAssetPrice, USD_UNIT}; use sp_runtime::transaction_validity::InvalidTransaction; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; + #[cfg(feature = "runtime-benchmarks")] mod benchmark_helpers; mod custom_migrations; @@ -1153,6 +1154,19 @@ impl pallet_dispenser::Config for Runtime { type WhitelistedPolicy = DispenserWhitelistedPolicy; } +use xcm::v3::{Junction::*, Junctions::*, MultiLocation}; + +pub struct ConvertMultilocationToAssetId; +impl Convert for ConvertMultilocationToAssetId { + fn convert(location: MultiLocation) -> AssetId { + match location { + MultiLocation { parents: 1, interior: Here } => 10, + MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1337)) } => 1337, + MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) } => 1984, + _ => 0, + } + } +} pub struct PLMCToFundingAssetBalance; impl ConversionToAssetBalance for PLMCToFundingAssetBalance { type Error = InvalidTransaction; @@ -1175,6 +1189,7 @@ impl pallet_asset_tx_payment::Config for Runtime { type Fungibles = ForeignAssets; type OnChargeAssetTransaction = TxFeeFungiblesAdapter< PLMCToFundingAssetBalance, + ConvertMultilocationToAssetId, CreditFungiblesToAccount, AssetsToBlockAuthor, >; diff --git a/runtimes/shared-configuration/Cargo.toml b/runtimes/shared-configuration/Cargo.toml index 17ffa3dcc..3d4e8680e 100644 --- a/runtimes/shared-configuration/Cargo.toml +++ b/runtimes/shared-configuration/Cargo.toml @@ -41,7 +41,7 @@ pallet-parachain-staking.workspace = true pallet-oracle-ocw.workspace = true pallet-treasury = {workspace = true, optional = true} pallet-asset-tx-payment.workspace = true - +xcm.workspace = true [features] default = [ "std" ] fast-mode = [] diff --git a/runtimes/shared-configuration/src/fee.rs b/runtimes/shared-configuration/src/fee.rs index 74c530cf3..170dfe6a5 100644 --- a/runtimes/shared-configuration/src/fee.rs +++ b/runtimes/shared-configuration/src/fee.rs @@ -43,7 +43,7 @@ use scale_info::{prelude::vec, TypeInfo}; use smallvec::smallvec; use sp_arithmetic::Perbill; use sp_runtime::{ - traits::{DispatchInfoOf, Get, One, PostDispatchInfoOf, Zero}, + traits::{Convert, DispatchInfoOf, Get, One, PostDispatchInfoOf, Zero}, transaction_validity::{InvalidTransaction, TransactionValidityError}, }; @@ -163,30 +163,35 @@ where } type BalanceOf = <::OnChargeTransaction as OnChargeTransaction>::Balance; +// type NativeBalance = u128; type AssetIdOf = <::Fungibles as Inspect>>::AssetId; +// type FungibleAssetId = u32; +// type CompatibilityAssetId = xcm::v3::MultiLocation; type AssetBalanceOf = <::Fungibles as Inspect<::AccountId>>::Balance; +// type AssetBalance = u128; /// Implements the asset transaction for a balance to asset converter (implementing /// [`ConversionToAssetBalance`]) and 2 credit handlers (implementing [`HandleCredit`]). /// /// First handler does the fee, second the tip. -pub struct TxFeeFungiblesAdapter( - PhantomData<(Converter, FeeCreditor, TipCreditor)>, +pub struct TxFeeFungiblesAdapter( + PhantomData<(Converter, MultiLocationToAssetId, FeeCreditor, TipCreditor)>, ); /// Default implementation for a runtime instantiating this pallet, a balance to asset converter and /// a credit handler. -impl OnChargeAssetTransaction - for TxFeeFungiblesAdapter +impl OnChargeAssetTransaction + for TxFeeFungiblesAdapter where Runtime: pallet_asset_tx_payment::Config, + MultiLocationToAssetId: Convert>, Converter: ConversionToAssetBalance, AssetIdOf, AssetBalanceOf>, FeeCreditor: HandleCredit, TipCreditor: HandleCredit, AssetIdOf: FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default + Eq + TypeInfo, { - type AssetId = AssetIdOf; + type AssetId = xcm::v3::MultiLocation; type Balance = BalanceOf; type LiquidityInfo = fungibles::Credit; @@ -202,6 +207,7 @@ where // We don't know the precision of the underlying asset. Because the converted fee could be // less than one (e.g. 0.5) but gets rounded down by integer division we introduce a minimum // fee. + let asset_id = MultiLocationToAssetId::convert(asset_id); let min_converted_fee = if fee.is_zero() { Zero::zero() } else { One::one() }; let converted_fee = Converter::to_asset_balance(fee, asset_id) .map_err(|_| TransactionValidityError::from(InvalidTransaction::Payment))?