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 10, 2024
1 parent 51d58f4 commit ae385b1
Show file tree
Hide file tree
Showing 7 changed files with 56 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.

16 changes: 10 additions & 6 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 @@ -79,10 +81,12 @@ fn fee_paid_with_foreign_assets() {
let paid_call_len = paid_call.encode().len();
type TxPaymentExtension = pallet_asset_tx_payment::ChargeAssetTxPayment<PolimecRuntime>;

// Tips are always defined in the native asset, and then converted to the fee asset if the second field is `Some`.
// Here a user wants to tip 10 PLMC in USDT.
let signed_extension =
pallet_asset_tx_payment::ChargeAssetTxPayment::<PolimecRuntime>::from(10 * plmc_unit, Some(usdt_id));
// Tips are always defined in the native asset, and then converted to the fee asset if the second field is `Some`.
// Here a user wants to tip 10 PLMC in USDT.
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 Expand Up @@ -126,7 +130,7 @@ fn fee_paid_with_foreign_assets() {
let post_block_author_plmc_balance = PolimecBalances::balance(&block_author.clone());

assert_eq!(prev_alice_usdt_balance - post_alice_usdt_balance, expected_usd_fee + expected_usd_tip);
assert_eq!(post_alice_plmc_balance, prev_alice_plmc_balance,);
assert_eq!(post_alice_plmc_balance, prev_alice_plmc_balance);
assert_eq!(
post_blockchain_operation_treasury_usdt_balance - prev_blockchain_operation_treasury_usdt_balance,
expected_usd_fee
Expand Down
2 changes: 1 addition & 1 deletion runtimes/polimec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ runtime-benchmarks = [
"frame-system/runtime-benchmarks",
"on-slash-vesting/runtime-benchmarks",
"orml-oracle/runtime-benchmarks",
"pallet-asset-tx-payment/runtime-benchmarks",
"pallet-assets/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-collective/runtime-benchmarks",
Expand Down Expand Up @@ -237,7 +238,6 @@ runtime-benchmarks = [
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
"pallet-asset-tx-payment/runtime-benchmarks"
]

try-runtime = [
Expand Down
2 changes: 1 addition & 1 deletion runtimes/polimec/src/custom_migrations/funding_holds.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::{Balance, Funding, Runtime, RuntimeHoldReason};
use alloc::vec::Vec;
use frame_support::traits::{GetStorageVersion, OnRuntimeUpgrade, VariantCount, VariantCountOf};
use pallet_balances::IdAmount;
use pallet_funding::ProjectId;
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_core::{MaxEncodedLen, RuntimeDebug};
use sp_runtime::BoundedVec;
use sp_std::vec::Vec;

#[derive(Clone, Copy, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub enum OldFundingHoldReason {
Expand Down
41 changes: 28 additions & 13 deletions runtimes/polimec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]

extern crate alloc;
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));

use core::ops::RangeInclusive;
use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
Expand Down Expand Up @@ -50,7 +51,10 @@ use parachains_common::{
AssetIdForTrustBackedAssets as AssetId,
};
use parity_scale_codec::Encode;
use polimec_common::credentials::{Did, EnsureInvestor};
use polimec_common::{
credentials::{Did, EnsureInvestor},
ProvideAssetPrice, USD_UNIT,
};
use polkadot_runtime_common::{BlockHashCount, CurrencyToVote, SlowAdjustingFeeUpdate};
use shared_configuration::proxy;
use sp_api::impl_runtime_apis;
Expand All @@ -61,38 +65,37 @@ use sp_runtime::{
AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert, ConvertBack, ConvertInto,
IdentifyAccount, IdentityLookup, OpaqueKeys, Verify,
},
transaction_validity::{TransactionSource, TransactionValidity},
transaction_validity::{InvalidTransaction, TransactionSource, TransactionValidity},
ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, SaturatedConversion,
};
use sp_std::{cmp::Ordering, prelude::*};
use sp_version::RuntimeVersion;

// XCM Imports
use xcm_config::XcmOriginToTransactDispatchOrigin;
use xcm::v3::{
Junction::{GeneralIndex, PalletInstance, Parachain},
Junctions::{Here, X3},
MultiLocation,
};
use xcm_config::{PriceForSiblingParachainDelivery, XcmOriginToTransactDispatchOrigin};

#[cfg(not(feature = "runtime-benchmarks"))]
use xcm_config::XcmConfig;

pub use pallet_parachain_staking;
// Polimec Shared Imports
pub use pallet_parachain_staking;
pub use shared_configuration::{
assets::*, currency::*, fee::*, funding::*, governance::*, identity::*, proxy::*, staking::*, time::*, weights::*,
};
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
pub use sp_runtime::{MultiAddress, Perbill, Permill};

// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));

#[cfg(feature = "std")]
use sp_version::NativeVersion;

use crate::xcm_config::PriceForSiblingParachainDelivery;
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 +1156,17 @@ impl pallet_dispenser::Config for Runtime {
type WhitelistedPolicy = DispenserWhitelistedPolicy;
}

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
9 changes: 5 additions & 4 deletions 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 All @@ -50,6 +50,7 @@ std = [
"frame-support/std",
"frame-system/std",
"orml-traits/std",
"pallet-asset-tx-payment/std",
"pallet-authorship/std",
"pallet-balances/std",
"pallet-funding/std",
Expand All @@ -64,11 +65,12 @@ std = [
"sp-arithmetic/std",
"sp-runtime/std",
"sp-std/std",
"pallet-asset-tx-payment/std"
"xcm/std",
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-asset-tx-payment/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-funding/runtime-benchmarks",
"pallet-oracle-ocw/runtime-benchmarks",
Expand All @@ -77,11 +79,11 @@ runtime-benchmarks = [
"parachains-common/runtime-benchmarks",
"polimec-common/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"pallet-asset-tx-payment/runtime-benchmarks"
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-asset-tx-payment/try-runtime",
"pallet-authorship/try-runtime",
"pallet-balances/try-runtime",
"pallet-funding/try-runtime",
Expand All @@ -91,6 +93,5 @@ try-runtime = [
"pallet-treasury?/try-runtime",
"polimec-common/try-runtime",
"sp-runtime/try-runtime",
"pallet-asset-tx-payment/try-runtime"
]
development-settings = []
16 changes: 10 additions & 6 deletions runtimes/shared-configuration/src/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ 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},
};
use xcm::v3::MultiLocation;

#[allow(clippy::module_name_repetitions)]
pub struct WeightToFee;
Expand Down Expand Up @@ -171,22 +172,24 @@ type AssetBalanceOf<T> =
/// [`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<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>;
// Note: We stick to `v3::MultiLocation`` because `v4::Location`` doesn't implement `Copy`.
type AssetId = MultiLocation;
type Balance = BalanceOf<Runtime>;
type LiquidityInfo = fungibles::Credit<Runtime::AccountId, Runtime::Fungibles>;

Expand All @@ -202,6 +205,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 ae385b1

Please sign in to comment.