Skip to content

Commit

Permalink
usdt-fee-pjs-compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
JuaniRios committed Oct 4, 2024
1 parent d099958 commit 7bcdb3c
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 31 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 29 additions & 21 deletions integration-tests/src/tests/otm_edge_cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <PolimecRuntime as pallet_funding::Config>::PriceProvider::get_decimals_aware_price(
AcceptedFundingAsset::USDT.id(),
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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(),
]);

Expand All @@ -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);
});
}

Expand Down Expand Up @@ -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));

});
}
10 changes: 7 additions & 3 deletions integration-tests/src/tests/transaction_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
{
Expand Down Expand Up @@ -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 = <PolimecForeignAssets as fungibles::metadata::Inspect<PolimecAccountId>>::decimals(usdt_id);
let usdt_unit = 10u128.pow(usdt_decimals as u32);
let plmc_decimals = PLMC_DECIMALS;
Expand All @@ -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<PolimecRuntime>;
let signed_extension =
pallet_asset_tx_payment::ChargeAssetTxPayment::<PolimecRuntime>::from(10 * plmc_unit, Some(usdt_id));
let signed_extension = pallet_asset_tx_payment::ChargeAssetTxPayment::<PolimecRuntime>::from(
10 * plmc_unit,
Some(usdt_multilocation),
);

let dispatch_info = paid_call.get_dispatch_info();
let FeeDetails { inclusion_fee, tip } =
Expand Down
15 changes: 15 additions & 0 deletions runtimes/polimec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1153,6 +1154,19 @@ impl pallet_dispenser::Config for Runtime {
type WhitelistedPolicy = DispenserWhitelistedPolicy;
}

use xcm::v3::{Junction::*, Junctions::*, MultiLocation};

pub struct ConvertMultilocationToAssetId;
impl Convert<MultiLocation, AssetId> 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<Balance, AssetId, Balance> for PLMCToFundingAssetBalance {
type Error = InvalidTransaction;
Expand All @@ -1175,6 +1189,7 @@ impl pallet_asset_tx_payment::Config for Runtime {
type Fungibles = ForeignAssets;
type OnChargeAssetTransaction = TxFeeFungiblesAdapter<
PLMCToFundingAssetBalance,
ConvertMultilocationToAssetId,
CreditFungiblesToAccount<AccountId, ForeignAssets, BlockchainOperationTreasury>,
AssetsToBlockAuthor<Runtime, ForeignAssetsInstance>,
>;
Expand Down
2 changes: 1 addition & 1 deletion runtimes/shared-configuration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down
18 changes: 12 additions & 6 deletions runtimes/shared-configuration/src/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
};

Expand Down Expand Up @@ -163,30 +163,35 @@ where
}

type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as OnChargeTransaction<T>>::Balance;
// type NativeBalance = u128;
type AssetIdOf<T> = <<T as pallet_asset_tx_payment::Config>::Fungibles as Inspect<AccountIdOf<T>>>::AssetId;
// type FungibleAssetId = u32;
// type CompatibilityAssetId = xcm::v3::MultiLocation;
type AssetBalanceOf<T> =
<<T as pallet_asset_tx_payment::Config>::Fungibles as Inspect<<T as frame_system::Config>::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<Converter, FeeCreditor, TipCreditor>(
PhantomData<(Converter, FeeCreditor, TipCreditor)>,
pub struct TxFeeFungiblesAdapter<Converter, MultiLocationToAssetId, FeeCreditor, TipCreditor>(
PhantomData<(Converter, MultiLocationToAssetId, FeeCreditor, TipCreditor)>,
);

/// Default implementation for a runtime instantiating this pallet, a balance to asset converter and
/// a credit handler.
impl<Runtime, Converter, FeeCreditor, TipCreditor> OnChargeAssetTransaction<Runtime>
for TxFeeFungiblesAdapter<Converter, FeeCreditor, TipCreditor>
impl<Runtime, MultiLocationToAssetId, Converter, FeeCreditor, TipCreditor> OnChargeAssetTransaction<Runtime>
for TxFeeFungiblesAdapter<Converter, MultiLocationToAssetId, FeeCreditor, TipCreditor>
where
Runtime: pallet_asset_tx_payment::Config,
MultiLocationToAssetId: Convert<xcm::v3::MultiLocation, AssetIdOf<Runtime>>,
Converter: ConversionToAssetBalance<BalanceOf<Runtime>, AssetIdOf<Runtime>, AssetBalanceOf<Runtime>>,
FeeCreditor: HandleCredit<Runtime::AccountId, Runtime::Fungibles>,
TipCreditor: HandleCredit<Runtime::AccountId, Runtime::Fungibles>,
AssetIdOf<Runtime>: FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default + Eq + TypeInfo,
{
type AssetId = AssetIdOf<Runtime>;
type AssetId = xcm::v3::MultiLocation;
type Balance = BalanceOf<Runtime>;
type LiquidityInfo = fungibles::Credit<Runtime::AccountId, Runtime::Fungibles>;

Expand All @@ -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))?
Expand Down

0 comments on commit 7bcdb3c

Please sign in to comment.