Skip to content

Commit

Permalink
Fix xcm execution fee destinations
Browse files Browse the repository at this point in the history
  • Loading branch information
JuaniRios committed Jun 14, 2024
1 parent 24f1285 commit 8c04c69
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 18 deletions.
10 changes: 7 additions & 3 deletions integration-tests/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ pub mod polimec {
use super::*;
use crate::{PolimecNet, PolimecOrigin, PolimecRuntime};
use pallet_funding::AcceptedFundingAsset;
use polimec_runtime::PayMaster;
use polimec_runtime::{PayMaster, TreasuryAccount};
use xcm::v3::Parent;
use xcm_emulator::TestExt;

Expand Down Expand Up @@ -622,7 +622,7 @@ pub mod polimec {

funded_accounts.extend(accounts::init_balances().iter().cloned().map(|k| (k, INITIAL_DEPOSIT)));
funded_accounts.extend(collators::initial_authorities().iter().cloned().map(|(acc, _)| (acc, 20_005 * PLMC)));
funded_accounts.push((get_account_id_from_seed::<sr25519::Public>("TREASURY_STASH"), 20_005 * PLMC));
funded_accounts.push((TreasuryAccount::get(), 20_005 * PLMC));
funded_accounts.push((PayMaster::get(), 20_005 * PLMC));

let genesis_config = polimec_runtime::RuntimeGenesisConfig {
Expand All @@ -640,7 +640,11 @@ pub mod polimec {
(usdt_asset_id, "Local USDT".as_bytes().to_vec(), "USDT".as_bytes().to_vec(), 6),
(usdc_asset_id, "Local USDC".as_bytes().to_vec(), "USDC".as_bytes().to_vec(), 6),
],
accounts: vec![],
accounts: vec![
(dot_asset_id, TreasuryAccount::get(), 0_0_010_000_000u128),
(usdt_asset_id, TreasuryAccount::get(), 0_0_010_000_000u128),
(usdc_asset_id, TreasuryAccount::get(), 0_0_010_000_000u128),
],
},
parachain_info: polimec_runtime::ParachainInfoConfig { parachain_id: PARA_ID.into(), ..Default::default() },
session: polimec_runtime::SessionConfig {
Expand Down
3 changes: 1 addition & 2 deletions integration-tests/src/tests/credentials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ use polimec_common::credentials::{Did, InvestorType};
use polimec_common_test_utils::{get_fake_jwt, get_mock_jwt_with_cid, get_test_jwt};
use polimec_runtime::PLMC;
use sp_runtime::{
bounded_vec,
generic::Era,
traits::SignedExtension,
transaction_validity::{InvalidTransaction::Payment, TransactionValidityError},
AccountId32, BoundedVec, DispatchError,
AccountId32, DispatchError,
};
use tests::defaults::*;

Expand Down
9 changes: 6 additions & 3 deletions integration-tests/src/tests/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,8 @@ fn election_phragmen_works() {
<PolimecRuntime as pallet_elections_phragmen::Config>::MaxCandidates::get() as usize
);

let prev_treasury_balance = Balances::balance(&Treasury::account_id());

for (i, voter) in vec![ALICE, BOB, CHARLIE, DAVE, EVE, FERDIE, ALICE_STASH, BOB_STASH].into_iter().enumerate() {
let voter = PolimecNet::account_id_of(voter);
assert_ok!(Elections::vote(
Expand All @@ -411,10 +413,11 @@ fn election_phragmen_works() {
{
assert_eq!(Balances::total_balance(candidate), ED);
}
let post_treasury_balance = Balances::balance(&Treasury::account_id());
let net_treasury_balance = post_treasury_balance - prev_treasury_balance;
assert_eq!(
Balances::balance(&Treasury::account_id()),
(<PolimecRuntime as pallet_elections_phragmen::Config>::MaxCandidates::get() as u128 - 15) * 1000 * PLMC +
ED
net_treasury_balance,
(<PolimecRuntime as pallet_elections_phragmen::Config>::MaxCandidates::get() as u128 - 15) * 1000 * PLMC
)
});
}
Expand Down
1 change: 1 addition & 0 deletions integration-tests/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ mod governance;
mod oracle;
mod reserve_backed_transfers;
mod vest;
mod xcm_config;
113 changes: 113 additions & 0 deletions integration-tests/src/tests/xcm_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use crate::{PolimecAccountId, PolimecBalances, PolimecCall, PolimecForeignAssets, PolimecNet, PolimecRuntime, ALICE};
use parity_scale_codec::Encode;
use polimec_runtime::{xcm_config::SupportedAssets, TreasuryAccount};
use sp_runtime::traits::MaybeEquivalence;
use xcm::prelude::*;
use xcm_emulator::{Chain, TestExt};
pub fn fake_message_hash<T>(message: &Xcm<T>) -> XcmHash {
message.using_encoded(sp_io::hashing::blake2_256)
}
#[test]
fn execution_fees_go_to_treasury() {
let dot_amount = MultiAsset { id: Concrete(MultiLocation::parent()), fun: Fungible(100_0_000_000_000) };
let usdt_amount = MultiAsset {
id: Concrete(MultiLocation {
parents: 1,
interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)),
}),
fun: Fungible(100_000_000),
};
let usdc_amount = MultiAsset {
id: Concrete(MultiLocation {
parents: 1,
interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1337)),
}),
fun: Fungible(100_000_000),
};

let beneficiary: PolimecAccountId = [0u8; 32].into();

let assert_reserve_asset_fee_goes_to_treasury = |multi_asset: MultiAsset| {
let asset_multilocation =
if let Concrete(asset_multilocation) = multi_asset.id { asset_multilocation } else { unreachable!() };
let asset_id = SupportedAssets::convert(&asset_multilocation).unwrap();
let asset_amount = if let Fungible(amount) = multi_asset.fun { amount } else { unreachable!() };

let xcm = Xcm::<PolimecCall>(vec![
ReserveAssetDeposited(vec![multi_asset.clone()].into()),
ClearOrigin,
BuyExecution { fees: multi_asset, weight_limit: Unlimited },
DepositAsset {
assets: WildMultiAsset::All.into(),
beneficiary: MultiLocation::new(0, X1(AccountId32 { network: None, id: beneficiary.clone().into() })),
},
])
.into();
PolimecNet::execute_with(|| {
let prev_treasury_balance = PolimecForeignAssets::balance(asset_id, TreasuryAccount::get());
let prev_beneficiary_balance = PolimecForeignAssets::balance(asset_id, beneficiary.clone());

let outcome = <PolimecRuntime as pallet_xcm::Config>::XcmExecutor::execute_xcm(
MultiLocation::new(1, X1(Parachain(1000))),
xcm.clone(),
fake_message_hash(&xcm),
Weight::MAX,
);
assert!(outcome.ensure_complete().is_ok());

let post_treasury_balance = PolimecForeignAssets::balance(asset_id, TreasuryAccount::get());
let post_beneficiary_balance = PolimecForeignAssets::balance(asset_id, beneficiary.clone());

let net_treasury_balance = post_treasury_balance - prev_treasury_balance;
let net_beneficiary_balance = post_beneficiary_balance - prev_beneficiary_balance;

let net_total = net_treasury_balance + net_beneficiary_balance;

assert_eq!(net_total, asset_amount);
assert!(net_treasury_balance > 0);
});
};

let assert_plmc_fee_goes_to_treasury = || {
let asset_amount = 100_0_000_000_000;
let multi_asset = MultiAsset { id: Concrete(MultiLocation::here()), fun: Fungible(asset_amount) };

let xcm = Xcm::<PolimecCall>(vec![
WithdrawAsset(vec![multi_asset.clone()].into()),
BuyExecution { fees: multi_asset, weight_limit: Unlimited },
DepositAsset {
assets: WildMultiAsset::All.into(),
beneficiary: MultiLocation::new(0, X1(AccountId32 { network: None, id: beneficiary.clone().into() })),
},
])
.into();
PolimecNet::execute_with(|| {
let prev_treasury_balance = PolimecBalances::free_balance(TreasuryAccount::get());
let prev_beneficiary_balance = PolimecBalances::free_balance(beneficiary.clone());

let outcome = <PolimecRuntime as pallet_xcm::Config>::XcmExecutor::execute_xcm(
MultiLocation::new(0, X1(AccountId32 { network: None, id: PolimecNet::account_id_of(ALICE).into() })),
xcm.clone(),
fake_message_hash(&xcm),
Weight::MAX,
);
assert!(outcome.ensure_complete().is_ok());

let post_treasury_balance = PolimecBalances::free_balance(TreasuryAccount::get());
let post_beneficiary_balance = PolimecBalances::free_balance(beneficiary.clone());

let net_treasury_balance = post_treasury_balance - prev_treasury_balance;
let net_beneficiary_balance = post_beneficiary_balance - prev_beneficiary_balance;

let net_total = net_treasury_balance + net_beneficiary_balance;

assert_eq!(net_total, asset_amount);
assert!(net_treasury_balance > 0);
});
};

assert_reserve_asset_fee_goes_to_treasury(dot_amount);
assert_reserve_asset_fee_goes_to_treasury(usdt_amount);
assert_reserve_asset_fee_goes_to_treasury(usdc_amount);
assert_plmc_fee_goes_to_treasury();
}
12 changes: 10 additions & 2 deletions runtimes/polimec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ use frame_support::{
traits::{
fungible::{Credit, HoldConsideration, Inspect},
tokens::{self, PayFromAccount, UnityAssetBalanceConversion},
AsEnsureOriginWithArg, ConstU32, Contains, EitherOfDiverse, InstanceFilter, LinearStoragePrice, PrivilegeCmp,
TransformOrigin,
AsEnsureOriginWithArg, ConstU32, Contains, Currency, EitherOfDiverse, InstanceFilter, LinearStoragePrice,
PrivilegeCmp, TransformOrigin,
},
weights::{ConstantMultiplier, Weight},
};
use frame_system::{EnsureRoot, EnsureRootWithSuccess, EnsureSigned, EnsureSignedBy};
use pallet_balances::NegativeImbalance;
use pallet_democracy::GetElectorate;
use pallet_funding::DaysToBlocks;

Expand Down Expand Up @@ -551,6 +552,12 @@ impl tokens::imbalance::OnUnbalanced<CreditOf<Runtime>> for ToTreasury {
let _ = <Balances as tokens::fungible::Balanced<AccountId>>::resolve(&treasury_account, amount);
}
}
impl tokens::imbalance::OnUnbalanced<NegativeImbalance<Runtime>> for ToTreasury {
fn on_nonzero_unbalanced(amount: NegativeImbalance<Runtime>) {
let treasury_account = Treasury::account_id();
<Balances as Currency<AccountId>>::resolve_creating(&treasury_account, amount);
}
}

parameter_types! {
pub TreasuryAccount: AccountId = Treasury::account_id();
Expand Down Expand Up @@ -1132,6 +1139,7 @@ impl pallet_dispenser::Config for Runtime {
// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime

{
// System support stuff.
System: frame_system = 0,
Expand Down
16 changes: 8 additions & 8 deletions runtimes/polimec/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

use super::{
AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, EnsureRoot, ForeignAssets,
ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Vec, WeightToFee,
XcmpQueue,
ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, ToTreasury,
Treasury, TreasuryAccount, Vec, WeightToFee, XcmpQueue,
};
use core::marker::PhantomData;
use frame_support::{
Expand All @@ -31,7 +31,6 @@ use polimec_xcm_executor::{
XcmExecutor,
};
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::impls::ToAuthor;
use sp_runtime::traits::MaybeEquivalence;
use xcm::latest::prelude::*;
use xcm_builder::{
Expand Down Expand Up @@ -261,7 +260,8 @@ pub type Reserves = AssetHubAssetsAsReserve;
/// ForeignAssetsAdapter is a FungiblesAdapter that allows for transacting foreign assets.
/// Currently we only support DOT, USDT and USDC.
pub type AssetTransactors = (FungibleTransactor, ForeignAssetsAdapter);

pub type TakeRevenueToTreasury =
cumulus_primitives_utility::XcmFeesTo32ByteAccount<AssetTransactors, AccountId, TreasuryAccount>;
pub struct XcmConfig;
impl polimec_xcm_executor::Config for XcmConfig {
type Aliasers = ();
Expand Down Expand Up @@ -290,10 +290,10 @@ impl polimec_xcm_executor::Config for XcmConfig {
type SubscriptionService = PolkadotXcm;
type Trader = (
// TODO: weight to fee has to be carefully considered. For now use default
UsingComponents<WeightToFee, HereLocation, AccountId, Balances, ToAuthor<Runtime>>,
FixedRateOfFungible<UsdtTraderParams, ()>,
FixedRateOfFungible<DotTraderParams, ()>,
FixedRateOfFungible<UsdcTraderParams, ()>,
UsingComponents<WeightToFee, HereLocation, AccountId, Balances, Treasury>,
FixedRateOfFungible<UsdtTraderParams, TakeRevenueToTreasury>,
FixedRateOfFungible<DotTraderParams, TakeRevenueToTreasury>,
FixedRateOfFungible<UsdcTraderParams, TakeRevenueToTreasury>,
);
type UniversalAliases = Nothing;
type UniversalLocation = UniversalLocation;
Expand Down

0 comments on commit 8c04c69

Please sign in to comment.