diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index adce753a9e..99b3f2dda9 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -1459,7 +1459,7 @@ impl cumulus_pallet_aura_ext::Config for Runtime {} // ); // pub struct XcmConfig; -// impl Config for XcmConfig { +// impl xcm_executor::Config for XcmConfig { // type Call = Call; // type XcmSender = XcmHandler; // type AssetTransactor = LocalAssetTransactor; diff --git a/runtime/karura/src/lib.rs b/runtime/karura/src/lib.rs index 6a1711d535..9c0188031f 100644 --- a/runtime/karura/src/lib.rs +++ b/runtime/karura/src/lib.rs @@ -56,7 +56,9 @@ use module_evm::{CallInfo, CreateInfo}; use module_evm_accounts::EvmAddressMapping; use module_evm_manager::EvmCurrencyIdMapping; use module_transaction_payment::{Multiplier, TargetedFeeAdjustment}; -use orml_traits::{create_median_value_data_provider, parameter_type_with_key, DataFeeder, DataProviderExtended}; +use orml_traits::{ + create_median_value_data_provider, parameter_type_with_key, DataFeeder, DataProviderExtended, MultiCurrency, +}; use pallet_transaction_payment::RuntimeDispatchInfo; pub use cumulus_primitives_core::ParaId; @@ -73,7 +75,7 @@ pub use xcm_builder::{ AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedRateOfConcreteFungible, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeRevenue, TakeWeightCredit, }; pub use xcm_executor::{Config, XcmExecutor}; @@ -1340,8 +1342,21 @@ parameter_types! { pub type Barrier = (TakeWeightCredit, AllowTopLevelPaidExecutionFrom>); +pub struct ToTreasury; +impl TakeRevenue for ToTreasury { + fn take_revenue(revenue: MultiAsset) { + if let MultiAsset::ConcreteFungible { id, amount } = revenue { + if let Some(currency_id) = CurrencyIdConvert::convert(id) { + // ensure KaruraTreasuryAccount have ed for all of the cross-chain asset. + // Ignore the result. + let _ = Currencies::deposit(currency_id, &KaruraTreasuryAccount::get(), amount); + } + } + } +} + pub struct XcmConfig; -impl Config for XcmConfig { +impl xcm_executor::Config for XcmConfig { type Call = Call; type XcmSender = XcmRouter; // How to withdraw and deposit an asset. @@ -1354,8 +1369,7 @@ impl Config for XcmConfig { type Barrier = Barrier; type Weigher = FixedWeightBounds; // Only receiving KSM is handled, and all fees must be paid in KSM. - //TODO: make treasury take revenue - type Trader = FixedRateOfConcreteFungible; + type Trader = FixedRateOfConcreteFungible; type ResponseHandler = (); // Don't handle responses for now. } diff --git a/runtime/mandala/src/lib.rs b/runtime/mandala/src/lib.rs index dd155e69c8..258dbfed47 100644 --- a/runtime/mandala/src/lib.rs +++ b/runtime/mandala/src/lib.rs @@ -54,7 +54,9 @@ use module_evm_accounts::EvmAddressMapping; pub use module_evm_manager::EvmCurrencyIdMapping; use module_transaction_payment::{Multiplier, TargetedFeeAdjustment}; use orml_tokens::CurrencyAdapter; -use orml_traits::{create_median_value_data_provider, parameter_type_with_key, DataFeeder, DataProviderExtended}; +use orml_traits::{ + create_median_value_data_provider, parameter_type_with_key, DataFeeder, DataProviderExtended, MultiCurrency, +}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -87,7 +89,7 @@ pub use xcm_builder::{ AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedRateOfConcreteFungible, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeRevenue, TakeWeightCredit, }; pub use xcm_executor::{Config, XcmExecutor}; @@ -1641,8 +1643,21 @@ parameter_types! { pub type Barrier = (TakeWeightCredit, AllowTopLevelPaidExecutionFrom>); +pub struct ToTreasury; +impl TakeRevenue for ToTreasury { + fn take_revenue(revenue: MultiAsset) { + if let MultiAsset::ConcreteFungible { id, amount } = revenue { + if let Some(currency_id) = CurrencyIdConvert::convert(id) { + // ensure KaruraTreasuryAccount have ed for all of the cross-chain asset. + // Ignore the result. + let _ = Currencies::deposit(currency_id, &TreasuryAccount::get(), amount); + } + } + } +} + pub struct XcmConfig; -impl Config for XcmConfig { +impl xcm_executor::Config for XcmConfig { type Call = Call; type XcmSender = XcmRouter; // How to withdraw and deposit an asset. @@ -1655,8 +1670,7 @@ impl Config for XcmConfig { type Barrier = Barrier; type Weigher = FixedWeightBounds; // Only receiving DOT is handled, and all fees must be paid in DOT. - //TODO: make treasury take revenue - type Trader = FixedRateOfConcreteFungible; + type Trader = FixedRateOfConcreteFungible; type ResponseHandler = (); // Don't handle responses for now. } diff --git a/runtime/mandala/tests/integration_test.rs b/runtime/mandala/tests/integration_test.rs index 9c09249738..6da240955c 100644 --- a/runtime/mandala/tests/integration_test.rs +++ b/runtime/mandala/tests/integration_test.rs @@ -18,9 +18,11 @@ #![cfg(test)] +use acala_service::chain_spec::evm_genesis; use codec::Encode; // use cumulus_primitives_core::{DownwardMessageHandler, InboundDownwardMessage, // XcmpMessageHandler}; +use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; use frame_support::{ assert_noop, assert_ok, traits::{schedule::DispatchTime, Currency, GenesisBuild, OnFinalize, OnInitialize, OriginTrait, ValidatorSet}, @@ -30,10 +32,11 @@ use mandala_runtime::{ dollar, get_all_module_accounts, AcalaOracle, AccountId, AuctionManager, Authority, AuthoritysOriginId, Balance, Balances, BlockNumber, Call, CdpEngine, CdpTreasury, CreateClassDeposit, CreateTokenDeposit, Currencies, CurrencyId, CurrencyIdConvert, DataDepositPerByte, Dex, EVMBridge, EmergencyShutdown, EnabledTradingPairs, Event, - EvmAccounts, EvmCurrencyIdMapping, Get, GetNativeCurrencyId, Loans, NativeTokenExistentialDeposit, NftPalletId, - Origin, OriginCaller, ParachainInfo, ParachainSystem, Perbill, Proxy, Runtime, Scheduler, Session, SessionManager, - SevenDays, System, TokenSymbol, TreasuryPalletId, TreasuryReservePalletId, Vesting, ACA, AUSD, DOT, EVM, LDOT, NFT, - RENBTC, + EvmAccounts, EvmCurrencyIdMapping, ExistentialDeposits, Get, GetNativeCurrencyId, Loans, MultiLocation, + NativeTokenExistentialDeposit, NetworkId, NftPalletId, Origin, OriginCaller, ParachainInfo, ParachainSystem, + Perbill, Proxy, Runtime, Scheduler, Session, SessionManager, SevenDays, System, TokenSymbol, Tokens, + TreasuryAccount, TreasuryPalletId, TreasuryReservePalletId, Vesting, XcmConfig, XcmExecutor, ACA, AUSD, DOT, EVM, + LDOT, NFT, RENBTC, }; use module_cdp_engine::LiquidationStrategy; use module_evm_accounts::EvmAddressMapping; @@ -42,11 +45,9 @@ use module_support::{ Price, Rate, Ratio, RiskManager, EVM as EVMTrait, }; use orml_authority::DelayedOrigin; -use orml_traits::{Change, MultiCurrency}; +use orml_traits::{Change, GetByKey, MultiCurrency}; use orml_vesting::VestingSchedule; // use polkadot_parachain::primitives::Sibling; -use acala_service::chain_spec::evm_genesis; -use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; pub use primitives::{evm::EvmAddress, DexShare, TradingPair}; use sp_core::{bytes::from_hex, H160}; use sp_io::hashing::keccak_256; @@ -55,7 +56,16 @@ use sp_runtime::{ DispatchError, DispatchResult, FixedPointNumber, MultiAddress, }; use std::str::FromStr; -use xcm::v0::{Junction::*, MultiAsset, MultiLocation::*}; +use xcm::{ + opaque::v0::prelude::{BuyExecution, DepositAsset}, + v0::{ + ExecuteXcm, + Junction::{self, *}, + MultiAsset, + MultiLocation::*, + Outcome, Xcm, + }, +}; use primitives::currency::*; @@ -1650,6 +1660,68 @@ fn test_session_manager_module() { }); } +#[test] +fn treasury_should_take_xcm_execution_revenue() { + ExtBuilder::default().build().execute_with(|| { + let dot_amount = 1000 * dollar(DOT); + let actual_amount = 9999999760000; + let shallow_weight = 3000000; + let origin = MultiLocation::X1(Junction::Parent); + + // receive relay chain token + let mut msg = Xcm::::ReserveAssetDeposit { + assets: vec![MultiAsset::ConcreteFungible { + id: MultiLocation::X1(Junction::Parent), + amount: dot_amount, + }], + effects: vec![ + BuyExecution { + fees: MultiAsset::All, + weight: 0, + debt: shallow_weight, + halt_on_error: true, + xcm: vec![], + }, + DepositAsset { + assets: vec![MultiAsset::All], + dest: MultiLocation::X1(Junction::AccountId32 { + network: NetworkId::Any, + id: ALICE, + }), + }, + ], + }; + use xcm_executor::traits::WeightBounds; + let debt = ::Weigher::shallow(&mut msg).unwrap_or_default(); + let deep = ::Weigher::deep(&mut msg).unwrap_or_default(); + // println!("debt = {:?}, deep = {:?}", debt, deep); + assert_eq!(debt, shallow_weight); + + assert_eq!(Tokens::free_balance(DOT, &ALICE.into()), 0); + assert_ok!(Currencies::deposit( + DOT, + &TreasuryAccount::get(), + ExistentialDeposits::get(&DOT) + )); + assert_eq!( + Tokens::free_balance(DOT, &TreasuryAccount::get()), + ExistentialDeposits::get(&DOT) + ); + + let weight_limit = debt + deep + 1; + assert_eq!( + XcmExecutor::::execute_xcm(origin, msg, weight_limit), + Outcome::Complete(shallow_weight) + ); + + assert_eq!(Tokens::free_balance(DOT, &ALICE.into()), actual_amount); + assert_eq!( + Tokens::free_balance(DOT, &TreasuryAccount::get()), + ExistentialDeposits::get(&DOT) + dot_amount - actual_amount + ); + }); +} + // #[test] // fn receive_cross_chain_assets() { // ExtBuilder::default().build().execute_with(|| {