From 14bd3bf45d01d48d5798acdef11aeff27684f28d Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Wed, 16 Feb 2022 16:33:46 +0800 Subject: [PATCH] Fix fee (#1891) * change fee calculation * fix fee * update weight * update benchmark * transfer all to treasury * apply review * extract calculate rate and use it in test * set threshold to 2.5 KAR * udpate testcase * cargo run --release --color=never --bin=acala --features=runtime-benchmarks --features=with-karura-runtime -- benchmark --chain=karura-dev --steps=50 --repeat=20 --pallet=module_transaction_payment --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --template=./templates/runtime-weight-template.hbs --output=./runtime/karura/src/weights/ * cargo run --release --color=never --bin=acala --features=runtime-benchmarks --features=with-acala-runtime -- benchmark --chain=acala-latest --steps=50 --repeat=20 --pallet=module_transaction_payment --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --template=./templates/runtime-weight-template.hbs --output=./runtime/acala/src/weights/ Co-authored-by: Acala Benchmarking Bot Co-authored-by: Bryan Chen --- modules/transaction-payment/src/lib.rs | 93 ++++++++- modules/transaction-payment/src/mock.rs | 5 +- modules/transaction-payment/src/tests.rs | 196 ++++++++++++++++-- modules/transaction-payment/src/weights.rs | 11 + .../src/weights/module_transaction_payment.rs | 25 ++- runtime/karura/src/lib.rs | 47 ++++- .../src/weights/module_transaction_payment.rs | 25 ++- .../src/benchmarking/transaction_payment.rs | 25 ++- .../src/weights/module_transaction_payment.rs | 6 + 9 files changed, 383 insertions(+), 50 deletions(-) diff --git a/modules/transaction-payment/src/lib.rs b/modules/transaction-payment/src/lib.rs index cb58a2185d..c0de41908e 100644 --- a/modules/transaction-payment/src/lib.rs +++ b/modules/transaction-payment/src/lib.rs @@ -355,6 +355,8 @@ pub mod module { InvalidBalance, /// Can't find rate by the supply token InvalidRate, + /// Can't find the token info in the charge fee pool + InvalidToken, /// Dex swap pool is not available now DexNotAvailable, /// Charge fee pool is already exist @@ -364,7 +366,7 @@ pub mod module { } #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] + #[pallet::generate_deposit(pub fn deposit_event)] pub enum Event { /// The global fee swap path was updated. GlobalFeeSwapPathUpdated { @@ -386,6 +388,19 @@ pub mod module { pool_size: Balance, swap_threshold: Balance, }, + /// The charge fee pool is swapped + ChargeFeePoolSwapped { + old_exchange_rate: Ratio, + swap_exchange_rate: Ratio, + new_exchange_rate: Ratio, + new_pool_size: Balance, + }, + /// The charge fee pool is disabled + ChargeFeePoolDisabled { + currency_id: CurrencyId, + foreign_amount: Balance, + native_amount: Balance, + }, } /// The next fee multiplier. @@ -607,6 +622,14 @@ pub mod module { T::UpdateOrigin::ensure_origin(origin)?; Self::initialize_pool(currency_id, pool_size, swap_threshold) } + + /// Disable charge fee pool. + #[pallet::weight(::WeightInfo::disable_charge_fee_pool())] + #[transactional] + pub fn disable_charge_fee_pool(origin: OriginFor, currency_id: CurrencyId) -> DispatchResult { + T::UpdateOrigin::ensure_origin(origin)?; + Self::disable_pool(currency_id) + } } } @@ -838,24 +861,31 @@ where // this means the charge fee pool is exhausted for this given token pair. // we normally set the `SwapBalanceThreshold` gt ED to prevent this case. let native_balance = T::Currency::free_balance(&sub_account); - if native_balance < SwapBalanceThreshold::::get(supply_currency_id) { + let threshold_balance = SwapBalanceThreshold::::get(supply_currency_id); + if native_balance < threshold_balance { let trading_path = Self::get_trading_path_by_currency(&sub_account, supply_currency_id); if let Some(trading_path) = trading_path { let supply_balance = T::MultiCurrency::free_balance(supply_currency_id, &sub_account); let supply_amount = supply_balance.saturating_sub(T::MultiCurrency::minimum_balance(supply_currency_id)); - if let Ok((_, swap_native_balance)) = T::DEX::swap_with_specific_path( + if let Ok((supply_amount, swap_native_balance)) = T::DEX::swap_with_specific_path( &sub_account, &trading_path, SwapLimit::ExactSupply(supply_amount, 0), ) { // calculate and update new rate, also update the pool size + let swap_exchange_rate = Ratio::saturating_from_rational(supply_amount, swap_native_balance); let new_pool_size = swap_native_balance.saturating_add(native_balance); - let new_native_balance = rate.saturating_mul_int(new_pool_size); - let next_updated_rate = - Ratio::saturating_from_rational(new_native_balance, PoolSize::::get(supply_currency_id)); - TokenExchangeRate::::insert(supply_currency_id, next_updated_rate); + let new_exchange_rate = Self::calculate_exchange_rate(supply_currency_id, swap_exchange_rate)?; + + TokenExchangeRate::::insert(supply_currency_id, new_exchange_rate); PoolSize::::insert(supply_currency_id, new_pool_size); + Pallet::::deposit_event(Event::::ChargeFeePoolSwapped { + old_exchange_rate: rate, + swap_exchange_rate, + new_exchange_rate, + new_pool_size, + }); } else { debug_assert!(false, "Swap tx fee pool should not fail!"); } @@ -910,8 +940,21 @@ where T::PalletId::get().into_sub_account(id) } - /// Initiate a charge fee swap pool. Usually used in `on_runtime_upgrade` or manual - /// `enable_charge_fee_pool` dispatch call. + /// Calculate the new exchange rate. + /// old_rate * (threshold/poolSize) + swap_exchange_rate * (1-threshold/poolSize) + fn calculate_exchange_rate(currency_id: CurrencyId, swap_exchange_rate: Ratio) -> Result> { + let threshold_balance = SwapBalanceThreshold::::get(currency_id); + let old_threshold_rate = Ratio::saturating_from_rational(threshold_balance, PoolSize::::get(currency_id)); + let new_threshold_rate = Ratio::one().saturating_sub(old_threshold_rate); + + let rate = TokenExchangeRate::::get(currency_id).ok_or(Error::::InvalidRate)?; + let old_parts = rate.saturating_mul(old_threshold_rate); + let new_parts = swap_exchange_rate.saturating_mul(new_threshold_rate); + let new_exchange_rate = old_parts.saturating_add(new_parts); + Ok(new_exchange_rate) + } + + /// Initiate a charge fee pool, transfer token from treasury account to sub account. fn initialize_pool(currency_id: CurrencyId, pool_size: Balance, swap_threshold: Balance) -> DispatchResult { let treasury_account = T::TreasuryAccount::get(); let sub_account = Self::sub_account_id(currency_id); @@ -950,6 +993,7 @@ where SwapBalanceThreshold::::insert(currency_id, swap_threshold); TokenExchangeRate::::insert(currency_id, exchange_rate); PoolSize::::insert(currency_id, pool_size); + Self::deposit_event(Event::ChargeFeePoolEnabled { sub_account, currency_id, @@ -957,7 +1001,38 @@ where pool_size, swap_threshold, }); + Ok(()) + } + /// Disable a charge fee pool, return token from sub account to treasury account. + fn disable_pool(currency_id: CurrencyId) -> DispatchResult { + ensure!( + TokenExchangeRate::::contains_key(currency_id), + Error::::InvalidToken + ); + let treasury_account = T::TreasuryAccount::get(); + let sub_account = Self::sub_account_id(currency_id); + let foreign_amount: Balance = T::MultiCurrency::free_balance(currency_id, &sub_account); + let native_amount: Balance = T::Currency::free_balance(&sub_account); + + T::MultiCurrency::transfer(currency_id, &sub_account, &treasury_account, foreign_amount)?; + T::Currency::transfer( + &sub_account, + &treasury_account, + native_amount, + ExistenceRequirement::AllowDeath, + )?; + + // remove map entry, then `swap_from_pool_or_dex` method will throw error. + TokenExchangeRate::::remove(currency_id); + PoolSize::::remove(currency_id); + SwapBalanceThreshold::::remove(currency_id); + + Self::deposit_event(Event::ChargeFeePoolDisabled { + currency_id, + foreign_amount, + native_amount, + }); Ok(()) } } diff --git a/modules/transaction-payment/src/mock.rs b/modules/transaction-payment/src/mock.rs index e9cfb61d8a..da2efb81cd 100644 --- a/modules/transaction-payment/src/mock.rs +++ b/modules/transaction-payment/src/mock.rs @@ -236,11 +236,12 @@ impl PriceProvider for MockPriceSource { parameter_types! { // DO NOT CHANGE THIS VALUE, AS IT EFFECT THE TESTCASES. pub const FeePoolSize: Balance = 10_000; - pub const SwapThreshold: Balance = 20; + pub const LowerSwapThreshold: Balance = 20; + pub const MiddSwapThreshold: Balance = 5000; + pub const HigerSwapThreshold: Balance = 9500; pub const TransactionPaymentPalletId: PalletId = PalletId(*b"aca/fees"); pub const TreasuryPalletId: PalletId = PalletId(*b"aca/trsy"); pub KaruraTreasuryAccount: AccountId = TreasuryPalletId::get().into_account(); - pub FeePoolExchangeTokens: Vec = vec![AUSD, DOT]; } ord_parameter_types! { pub const ListingOrigin: AccountId = ALICE; diff --git a/modules/transaction-payment/src/tests.rs b/modules/transaction-payment/src/tests.rs index 457670c893..3f0830da17 100644 --- a/modules/transaction-payment/src/tests.rs +++ b/modules/transaction-payment/src/tests.rs @@ -116,14 +116,13 @@ fn do_runtime_upgrade_and_init_balance() { false )); - for asset in crate::mock::FeePoolExchangeTokens::get() { + for asset in vec![AUSD, DOT] { assert_ok!(Pallet::::initialize_pool( asset, FeePoolSize::get(), - crate::mock::SwapThreshold::get() + crate::mock::LowerSwapThreshold::get() )); } - // MockTransactionPaymentUpgrade::on_runtime_upgrade(); vec![AUSD, DOT].iter().for_each(|token| { let ed = (>::minimum_balance(token.clone())).unique_saturated_into(); @@ -135,6 +134,8 @@ fn do_runtime_upgrade_and_init_balance() { // manual set the exchange rate for simplify calculation TokenExchangeRate::::insert(AUSD, Ratio::saturating_from_rational(10, 1)); + let dot_rate = TokenExchangeRate::::get(DOT).unwrap(); + assert_eq!(dot_rate, Ratio::saturating_from_rational(1, 10)); } fn builder_with_upgraded_executed(enable_dex: bool) -> TestExternalities { @@ -1008,7 +1009,7 @@ fn swap_from_pool_with_enough_balance() { } #[test] -fn swap_from_pool_and_dex_update_rate() { +fn swap_from_pool_and_dex_with_higher_threshold() { builder_with_upgraded_executed(true).execute_with(|| { let pool_size = FeePoolSize::get(); let dot_fee_account = Pallet::::sub_account_id(DOT); @@ -1033,32 +1034,143 @@ fn swap_from_pool_and_dex_update_rate() { assert_eq!(fee_dot + dot_ed, Currencies::free_balance(DOT, &dot_fee_account)); assert_eq!(pool_size - balance, Currencies::free_balance(ACA, &dot_fee_account)); + let old_exchange_rate = TokenExchangeRate::::get(DOT).unwrap(); + assert_eq!(old_exchange_rate, Ratio::saturating_from_rational(fee_dot, balance)); + // Set threshold(init-500) gt sub account balance(init-800), trigger swap from dex. - let swap_balance_threshold = (pool_size - 500) as u128; - Pallet::::set_swap_balance_threshold(Origin::signed(ALICE), DOT, swap_balance_threshold).unwrap(); - Pallet::::set_swap_balance_threshold(Origin::signed(ALICE), AUSD, swap_balance_threshold).unwrap(); + Pallet::::set_swap_balance_threshold( + Origin::signed(ALICE), + DOT, + crate::mock::HigerSwapThreshold::get(), + ) + .unwrap(); + Pallet::::set_swap_balance_threshold( + Origin::signed(ALICE), + AUSD, + crate::mock::HigerSwapThreshold::get(), + ) + .unwrap(); // swap 80 DOT out 3074 ACA let trading_path = Pallet::::get_trading_path_by_currency(&ALICE, DOT).unwrap(); let supply_amount = Currencies::free_balance(DOT, &dot_fee_account) - dot_ed; - let (_, swap_native) = + // here just get swap out amount, the swap not happened + let (supply_in_amount, swap_out_native) = module_dex::Pallet::::get_swap_amount(&trading_path, SwapLimit::ExactSupply(supply_amount, 0)) .unwrap(); - assert_eq!(3074, swap_native); - // calculate the new balance of ACA = 3074+(init-800)=3074+9200=12270 - let current_native_balance = - (swap_native + Currencies::free_balance(ACA, &dot_fee_account)).saturated_into::(); - let base_native: u128 = current_native_balance / 10; - assert_eq!(1227, base_native); - // compare to the old balance:10000 and rate:1/10, the new rate is (12270/10000)*(1/10)=0.1227 - let rate = Ratio::saturating_from_rational(base_native, pool_size); - assert_eq!(Ratio::saturating_from_rational(1227, 10000), rate); + assert_eq!(3074, swap_out_native); + assert_eq!(supply_in_amount, supply_amount); + let new_pool_size = + (swap_out_native + Currencies::free_balance(ACA, &dot_fee_account)).saturated_into::(); + + // the swap also has it's own exchange rate by input_amount divide output_amount + let swap_exchange_rate = Ratio::saturating_from_rational(supply_in_amount, swap_out_native); + assert_eq!(swap_exchange_rate, Ratio::saturating_from_rational(80, 3074)); + + // swap_rate=80/3074, threshold=9500, pool_size=10000, threshold_rate=0.95, old_rate=1/10 + // new_rate = 1/10 * 0.95 + 80/3074 * 0.05 = 0.095 + 0.001301236174365 = 0.096301236174365 + let new_exchange_rate_val = + Ratio::saturating_from_rational(9_630_123_6174_365_647 as u128, 1_000_000_000_000_000_000 as u128); // the sub account has 9200 ACA, 80 DOT, use 80 DOT to swap out some ACA let balance2 = 300 as u128; assert_ok!(Pallet::::swap_from_pool_or_dex(&BOB, balance2, DOT)); - assert_eq!(TokenExchangeRate::::get(DOT).unwrap(), rate); - assert_eq!(PoolSize::::get(DOT), current_native_balance); + System::assert_has_event(crate::mock::Event::TransactionPayment( + crate::Event::ChargeFeePoolSwapped { + old_exchange_rate, + swap_exchange_rate, + new_exchange_rate: new_exchange_rate_val, + new_pool_size, + }, + )); + + let new_rate = TokenExchangeRate::::get(DOT).unwrap(); + assert_eq!(new_exchange_rate_val, new_rate); + assert_eq!(PoolSize::::get(DOT), new_pool_size); + }); +} + +#[test] +fn swap_from_pool_and_dex_with_midd_threshold() { + builder_with_upgraded_executed(true).execute_with(|| { + let sub_account: AccountId = ::PalletId::get().into_sub_account(DOT); + let dot_ed = >::minimum_balance(DOT); + let trading_path = Pallet::::get_trading_path_by_currency(&ALICE, DOT).unwrap(); + + // the pool size has 10000 ACA, and set threshold to half of pool size: 5000 ACA + let balance = 3000 as u128; + assert_ok!(Currencies::update_balance( + Origin::root(), + BOB, + DOT, + balance.unique_saturated_into(), + )); + + Pallet::::set_swap_balance_threshold( + Origin::signed(ALICE), + DOT, + crate::mock::MiddSwapThreshold::get(), + ) + .unwrap(); + Pallet::::set_swap_balance_threshold( + Origin::signed(ALICE), + AUSD, + crate::mock::MiddSwapThreshold::get(), + ) + .unwrap(); + + // After tx#1, ACA balance of sub account is large than threshold(5000 ACA) + Pallet::::swap_from_pool_or_dex(&BOB, balance, DOT).unwrap(); + assert_eq!(Currencies::free_balance(ACA, &sub_account), 7000); + assert_eq!(Currencies::free_balance(DOT, &sub_account), 301); + + // After tx#2, ACA balance of sub account is less than threshold(5000 ACA) + Pallet::::swap_from_pool_or_dex(&BOB, balance, DOT).unwrap(); + assert_eq!(Currencies::free_balance(ACA, &sub_account), 4000); + assert_eq!(Currencies::free_balance(DOT, &sub_account), 601); + + let supply_amount = Currencies::free_balance(DOT, &sub_account) - dot_ed; + // Given different DOT, get the swap out ACA + // DOT | ACA | SwapRate + // 001 | 0089 | FixedU128(0.011235955056179775) + // 050 | 2498 | FixedU128(0.020016012810248198) + // 100 | 3333 | FixedU128(0.030003000300030003) + // 200 | 3997 | FixedU128(0.050037528146109582) + // 300 | 4285 | FixedU128(0.070011668611435239) + // 500 | 4544 | FixedU128(0.110035211267605633) + // 600 | 4614 | FixedU128(0.130039011703511053) <- this case hit here + let (supply_in_amount, swap_out_native) = + module_dex::Pallet::::get_swap_amount(&trading_path, SwapLimit::ExactSupply(supply_amount, 0)) + .unwrap(); + assert_eq!(600, supply_in_amount); + assert_eq!(4614, swap_out_native); + // new pool size = swap_out_native + ACA balance of sub account + let new_pool_size = swap_out_native + 4000; + + // When execute tx#3, trigger swap from dex, but this tx still use old rate(1/10) + Pallet::::swap_from_pool_or_dex(&BOB, balance, DOT).unwrap(); + assert_eq!(Currencies::free_balance(ACA, &sub_account), 5614); // 4000+4614-3000=5614 + assert_eq!(Currencies::free_balance(DOT, &sub_account), 301); + + let old_exchange_rate = Ratio::saturating_from_rational(1, 10); + let swap_exchange_rate = Ratio::saturating_from_rational(supply_in_amount, swap_out_native); + // (0.1 + 0.130039011703511053)/2 = 0.230039011703511053/2 = 0.115019505851755526 + let new_exchange_rate_val = + Ratio::saturating_from_rational(115_019_505_851_755_526 as u128, 1_000_000_000_000_000_000 as u128); + + System::assert_has_event(crate::mock::Event::TransactionPayment( + crate::Event::ChargeFeePoolSwapped { + old_exchange_rate, + swap_exchange_rate, + new_exchange_rate: new_exchange_rate_val, + new_pool_size, + }, + )); + + // tx#3 use new exchange rate + Pallet::::swap_from_pool_or_dex(&BOB, balance, DOT).unwrap(); + assert_eq!(Currencies::free_balance(ACA, &sub_account), 2614); + assert_eq!(Currencies::free_balance(DOT, &sub_account), 301 + 3 * 115); }); } @@ -1165,7 +1277,7 @@ fn charge_fee_failed_when_disable_dex() { } #[test] -fn enable_init_pool_works() { +fn charge_fee_pool_operation_works() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Currencies::update_balance( Origin::root(), @@ -1204,8 +1316,10 @@ fn enable_init_pool_works() { assert!(dex_available.is_some()); let treasury_account: AccountId = ::TreasuryAccount::get(); + let sub_account: AccountId = ::PalletId::get().into_sub_account(AUSD); let usd_ed = >::minimum_balance(AUSD); let pool_size = FeePoolSize::get(); + let swap_threshold = crate::mock::MiddSwapThreshold::get(); assert_ok!(Currencies::update_balance( Origin::root(), @@ -1224,20 +1338,56 @@ fn enable_init_pool_works() { Origin::signed(ALICE), AUSD, pool_size, - 35 + swap_threshold )); let rate = TokenExchangeRate::::get(AUSD); assert_eq!(rate, Some(Ratio::saturating_from_rational(2, 10))); + System::assert_has_event(crate::mock::Event::TransactionPayment( + crate::Event::ChargeFeePoolEnabled { + sub_account: sub_account.clone(), + currency_id: AUSD, + exchange_rate: Ratio::saturating_from_rational(2, 10), + pool_size, + swap_threshold, + }, + )); assert_noop!( - Pallet::::enable_charge_fee_pool(Origin::signed(ALICE), AUSD, pool_size, 35), + Pallet::::enable_charge_fee_pool(Origin::signed(ALICE), AUSD, pool_size, swap_threshold), Error::::ChargeFeePoolAlreadyExisted ); assert_noop!( - Pallet::::enable_charge_fee_pool(Origin::signed(ALICE), KSM, pool_size, 35), + Pallet::::enable_charge_fee_pool(Origin::signed(ALICE), KSM, pool_size, swap_threshold), Error::::DexNotAvailable ); + assert_noop!( + Pallet::::disable_charge_fee_pool(Origin::signed(ALICE), KSM), + Error::::InvalidToken + ); + + let ausd_amount1 = >::free_balance(AUSD, &sub_account); + let aca_amount1 = crate::mock::PalletBalances::free_balance(&sub_account); + assert_ok!(Pallet::::disable_charge_fee_pool(Origin::signed(ALICE), AUSD)); + assert_eq!(TokenExchangeRate::::get(AUSD), None); + System::assert_has_event(crate::mock::Event::TransactionPayment( + crate::Event::ChargeFeePoolDisabled { + currency_id: AUSD, + foreign_amount: ausd_amount1, + native_amount: aca_amount1, + }, + )); + let ausd_amount2 = >::free_balance(AUSD, &sub_account); + let aca_amount2 = crate::mock::PalletBalances::free_balance(&sub_account); + assert_eq!(aca_amount2, 0); + assert_eq!(ausd_amount2, 0); + + assert_ok!(Pallet::::enable_charge_fee_pool( + Origin::signed(ALICE), + AUSD, + pool_size, + swap_threshold + )); }); } diff --git a/modules/transaction-payment/src/weights.rs b/modules/transaction-payment/src/weights.rs index 5223475e27..7be373511e 100644 --- a/modules/transaction-payment/src/weights.rs +++ b/modules/transaction-payment/src/weights.rs @@ -51,6 +51,7 @@ pub trait WeightInfo { fn remove_global_fee_swap_path() -> Weight; fn set_swap_balance_threshold() -> Weight; fn enable_charge_fee_pool() -> Weight; + fn disable_charge_fee_pool() -> Weight; fn on_finalize() -> Weight; } @@ -96,6 +97,11 @@ impl WeightInfo for AcalaWeight { .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } + fn disable_charge_fee_pool() -> Weight { + (628_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) + } // Storage: TransactionPayment NextFeeMultiplier (r:1 w:1) // Storage: System BlockWeight (r:1 w:0) fn on_finalize() -> Weight { @@ -132,6 +138,11 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } + fn disable_charge_fee_pool() -> Weight { + (628_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes(7 as Weight)) + } fn on_finalize() -> Weight { (9_119_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) diff --git a/runtime/acala/src/weights/module_transaction_payment.rs b/runtime/acala/src/weights/module_transaction_payment.rs index 1a74d95649..0006ee2f36 100644 --- a/runtime/acala/src/weights/module_transaction_payment.rs +++ b/runtime/acala/src/weights/module_transaction_payment.rs @@ -49,26 +49,26 @@ impl module_transaction_payment::WeightInfo for WeightI // Storage: Balances Reserves (r:1 w:1) // Storage: TransactionPayment AlternativeFeeSwapPath (r:0 w:1) fn set_alternative_fee_swap_path() -> Weight { - (37_857_000 as Weight) + (36_957_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: TransactionPayment GlobalFeeSwapPath (r:1 w:1) fn set_global_fee_swap_path() -> Weight { - (19_967_000 as Weight) + (18_934_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: TransactionPayment GlobalFeeSwapPath (r:1 w:1) fn remove_global_fee_swap_path() -> Weight { - (20_261_000 as Weight) + (19_573_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: TransactionPayment PoolSize (r:1 w:0) // Storage: TransactionPayment SwapBalanceThreshold (r:0 w:1) fn set_swap_balance_threshold() -> Weight { - (20_757_000 as Weight) + (21_136_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -81,14 +81,27 @@ impl module_transaction_payment::WeightInfo for WeightI // Storage: TransactionPayment TokenExchangeRate (r:0 w:1) // Storage: TransactionPayment SwapBalanceThreshold (r:0 w:1) fn enable_charge_fee_pool() -> Weight { - (109_411_000 as Weight) + (107_015_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } + // Storage: TransactionPayment TokenExchangeRate (r:1 w:1) + // Storage: Tokens Accounts (r:2 w:2) + // Storage: System Account (r:2 w:2) + // Storage: EvmAccounts EvmAddresses (r:1 w:0) + // Storage: EVM Accounts (r:1 w:1) + // Storage: TransactionPayment SwapBalanceThreshold (r:0 w:1) + // Storage: TransactionPayment PoolSize (r:0 w:1) + // Storage: EvmAccounts Accounts (r:0 w:1) + fn disable_charge_fee_pool() -> Weight { + (111_708_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) + } // Storage: TransactionPayment NextFeeMultiplier (r:1 w:1) // Storage: System BlockWeight (r:1 w:0) fn on_finalize() -> Weight { - (11_586_000 as Weight) + (11_044_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/karura/src/lib.rs b/runtime/karura/src/lib.rs index a8bcba13ea..f285678152 100644 --- a/runtime/karura/src/lib.rs +++ b/runtime/karura/src/lib.rs @@ -2170,8 +2170,51 @@ pub type SignedPayload = generic::SignedPayload; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPalletsWithSystem, ()>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, + TransactionPaymentMigration, +>; + +parameter_types! { + pub FeePoolSize: Balance = 5 * dollar(KAR); + pub SwapBalanceThreshold: Balance = Ratio::saturating_from_rational(25, 10).saturating_mul_int(dollar(KAR)); +} + +pub struct TransactionPaymentMigration; +impl frame_support::traits::OnRuntimeUpgrade for TransactionPaymentMigration { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + let poo_size = FeePoolSize::get(); + let threshold = SwapBalanceThreshold::get(); + let tokens = vec![KUSD, KSM, LKSM, BNC]; + for token in tokens { + let _ = module_transaction_payment::Pallet::::disable_charge_fee_pool( + Origin::signed(KaruraTreasuryAccount::get()), + token, + ); + let _ = module_transaction_payment::Pallet::::enable_charge_fee_pool( + Origin::signed(KaruraTreasuryAccount::get()), + token, + poo_size, + threshold, + ); + } + ::BlockWeights::get().max_block + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + Ok(()) + } +} #[cfg(feature = "runtime-benchmarks")] #[macro_use] diff --git a/runtime/karura/src/weights/module_transaction_payment.rs b/runtime/karura/src/weights/module_transaction_payment.rs index 82e9aaff1e..8acb8a263a 100644 --- a/runtime/karura/src/weights/module_transaction_payment.rs +++ b/runtime/karura/src/weights/module_transaction_payment.rs @@ -49,26 +49,26 @@ impl module_transaction_payment::WeightInfo for WeightI // Storage: Balances Reserves (r:1 w:1) // Storage: TransactionPayment AlternativeFeeSwapPath (r:0 w:1) fn set_alternative_fee_swap_path() -> Weight { - (36_992_000 as Weight) + (34_312_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: TransactionPayment GlobalFeeSwapPath (r:1 w:1) fn set_global_fee_swap_path() -> Weight { - (21_035_000 as Weight) + (19_420_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: TransactionPayment GlobalFeeSwapPath (r:1 w:1) fn remove_global_fee_swap_path() -> Weight { - (21_384_000 as Weight) + (19_280_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: TransactionPayment PoolSize (r:1 w:0) // Storage: TransactionPayment SwapBalanceThreshold (r:0 w:1) fn set_swap_balance_threshold() -> Weight { - (22_468_000 as Weight) + (20_069_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -81,14 +81,27 @@ impl module_transaction_payment::WeightInfo for WeightI // Storage: TransactionPayment TokenExchangeRate (r:0 w:1) // Storage: TransactionPayment SwapBalanceThreshold (r:0 w:1) fn enable_charge_fee_pool() -> Weight { - (105_452_000 as Weight) + (98_681_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } + // Storage: TransactionPayment TokenExchangeRate (r:1 w:1) + // Storage: Tokens Accounts (r:2 w:2) + // Storage: System Account (r:2 w:2) + // Storage: EvmAccounts EvmAddresses (r:1 w:0) + // Storage: EVM Accounts (r:1 w:1) + // Storage: TransactionPayment SwapBalanceThreshold (r:0 w:1) + // Storage: TransactionPayment PoolSize (r:0 w:1) + // Storage: EvmAccounts Accounts (r:0 w:1) + fn disable_charge_fee_pool() -> Weight { + (105_817_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) + } // Storage: TransactionPayment NextFeeMultiplier (r:1 w:1) // Storage: System BlockWeight (r:1 w:0) fn on_finalize() -> Weight { - (11_867_000 as Weight) + (10_840_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/mandala/src/benchmarking/transaction_payment.rs b/runtime/mandala/src/benchmarking/transaction_payment.rs index c98d6690b1..7f7065ca12 100644 --- a/runtime/mandala/src/benchmarking/transaction_payment.rs +++ b/runtime/mandala/src/benchmarking/transaction_payment.rs @@ -25,10 +25,10 @@ use frame_benchmarking::{account, whitelisted_caller}; use frame_support::traits::OnFinalize; use frame_system::RawOrigin; use module_dex::TradingPairStatus; -use module_support::{DEXManager, SwapLimit}; +use module_support::{DEXManager, Ratio, SwapLimit}; use orml_benchmarking::runtime_benchmarks; use orml_traits::MultiCurrency; -use sp_runtime::traits::{AccountIdConversion, UniqueSaturatedInto}; +use sp_runtime::traits::{AccountIdConversion, One, UniqueSaturatedInto}; use sp_std::prelude::*; @@ -139,6 +139,27 @@ runtime_benchmarks! { }.into()); } + disable_charge_fee_pool { + let treasury_account: AccountId = TreasuryPalletId::get().into_account(); + let sub_account: AccountId = ::PalletId::get().into_sub_account(STABLECOIN); + let native_ed: Balance = >::minimum_balance(NATIVECOIN); + let stable_ed: Balance = >::minimum_balance(STABLECOIN); + let pool_size: Balance = native_ed * 50; + + set_balance(NATIVECOIN, &sub_account, native_ed * 10); + set_balance(STABLECOIN, &sub_account, stable_ed * 10); + + module_transaction_payment::TokenExchangeRate::::insert(STABLECOIN, Ratio::one()); + }: _(RawOrigin::Root, STABLECOIN) + verify { + assert_last_event(module_transaction_payment::Event::ChargeFeePoolDisabled { + currency_id: STABLECOIN, + foreign_amount: stable_ed * 10, + native_amount: native_ed * 10, + }.into()); + assert_eq!(module_transaction_payment::TokenExchangeRate::::get(STABLECOIN), None); + } + on_finalize { }: { TransactionPayment::on_finalize(System::block_number()); diff --git a/runtime/mandala/src/weights/module_transaction_payment.rs b/runtime/mandala/src/weights/module_transaction_payment.rs index ec747d2e37..2ce7fffc29 100644 --- a/runtime/mandala/src/weights/module_transaction_payment.rs +++ b/runtime/mandala/src/weights/module_transaction_payment.rs @@ -76,4 +76,10 @@ impl module_transaction_payment::WeightInfo for WeightI .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + + fn disable_charge_fee_pool() -> Weight { + (12_801_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } }