diff --git a/Cargo.lock b/Cargo.lock index 2f30161a0..12035b11c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4938,7 +4938,7 @@ dependencies = [ [[package]] name = "hydradx-runtime" -version = "255.0.0" +version = "256.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", @@ -8936,7 +8936,7 @@ dependencies = [ [[package]] name = "pallet-route-executor" -version = "2.5.0" +version = "2.5.1" dependencies = [ "frame-benchmarking", "frame-support", @@ -11929,7 +11929,7 @@ dependencies = [ [[package]] name = "runtime-integration-tests" -version = "1.23.1" +version = "1.23.2" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 83ee43671..15b8ee223 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runtime-integration-tests" -version = "1.23.1" +version = "1.23.2" description = "Integration tests" authors = ["GalacticCouncil"] edition = "2021" diff --git a/integration-tests/src/router.rs b/integration-tests/src/router.rs index 943425782..d6eba45cc 100644 --- a/integration-tests/src/router.rs +++ b/integration-tests/src/router.rs @@ -36,8 +36,8 @@ use sp_runtime::{ DispatchError, DispatchResult, FixedU128, Permill, TransactionOutcome, }; +use hydradx_runtime::InsufficientEDinHDX; use orml_traits::MultiCurrency; - pub const LBP_SALE_START: BlockNumber = 10; pub const LBP_SALE_END: BlockNumber = 40; @@ -761,6 +761,7 @@ mod router_different_pools_tests { mod omnipool_router_tests { use super::*; use frame_support::assert_noop; + use hydradx_runtime::{Balances, XYK}; use hydradx_traits::router::PoolType; use hydradx_traits::AssetKind; @@ -973,6 +974,530 @@ mod omnipool_router_tests { }); } + #[test] + fn sell_should_not_charge_ed_when_insufficient_in_middle_of_route() { + TestNet::reset(); + + Hydra::execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let name = b"INSUFF".to_vec(); + let insufficient_asset = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + assert_ok!(Currencies::deposit(ETH, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(DOT, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::update_balance( + hydradx_runtime::RuntimeOrigin::root(), + DAVE.into(), + HDX, + 10000 * UNITS as i128, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + HDX, + 10000 * UNITS, + DOT, + 10000 * UNITS, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + DOT, + 10000 * UNITS, + insufficient_asset, + 10000 * UNITS, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset, + 10000 * UNITS, + ETH, + 10000 * UNITS, + )); + + let trades = vec![ + Trade { + pool: PoolType::XYK, + asset_in: HDX, + asset_out: DOT, + }, + Trade { + pool: PoolType::XYK, + asset_in: DOT, + asset_out: insufficient_asset, + }, + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset, + asset_out: ETH, + }, + ]; + + //Act + assert_balance!(ALICE.into(), HDX, 1000 * UNITS); + + let amount_to_sell = 20 * UNITS; + assert_ok!(Router::sell( + hydradx_runtime::RuntimeOrigin::signed(ALICE.into()), + HDX, + ETH, + amount_to_sell, + 0, + trades + )); + + assert_balance!(ALICE.into(), HDX, 1000 * UNITS - amount_to_sell); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); + } + + #[test] + fn sell_should_work_with_only_insufficient_assets() { + TestNet::reset(); + + Hydra::execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let name = b"INSUF1".to_vec(); + let insufficient_asset1 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + let name = b"INSUF2".to_vec(); + let insufficient_asset2 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + let name = b"INSUF3".to_vec(); + let insufficient_asset3 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + let name = b"INSUF4".to_vec(); + let insufficient_asset4 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + assert_ok!(Currencies::deposit(insufficient_asset1, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset2, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset3, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset4, &DAVE.into(), 100000 * UNITS,)); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset1, + 10000 * UNITS, + insufficient_asset2, + 10000 * UNITS, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset2, + 10000 * UNITS, + insufficient_asset3, + 10000 * UNITS, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset3, + 10000 * UNITS, + insufficient_asset4, + 10000 * UNITS, + )); + + let trades = vec![ + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset1, + asset_out: insufficient_asset2, + }, + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset2, + asset_out: insufficient_asset3, + }, + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset3, + asset_out: insufficient_asset4, + }, + ]; + + assert_ok!(Currencies::deposit(insufficient_asset1, &ALICE.into(), 1500 * UNITS,)); + + let ed = InsufficientEDinHDX::get(); + assert_balance!(ALICE.into(), HDX, 1000 * UNITS - ed); + + let amount_to_sell = 20 * UNITS; + assert_ok!(Router::sell( + hydradx_runtime::RuntimeOrigin::signed(ALICE.into()), + insufficient_asset1, + insufficient_asset4, + amount_to_sell, + 0, + trades + )); + + assert_balance!(ALICE.into(), HDX, 1000 * UNITS - 2 * ed); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); + } + + #[test] + fn ed_should_be_refunded_when_all_insufficient_assets_sold() { + TestNet::reset(); + + Hydra::execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let name = b"INSUF1".to_vec(); + let insufficient_asset1 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + let name = b"INSUF2".to_vec(); + let insufficient_asset2 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + assert_ok!(Currencies::deposit(insufficient_asset1, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset2, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(ETH, &DAVE.into(), 100000 * UNITS,)); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset1, + 10000 * UNITS, + insufficient_asset2, + 10000 * UNITS, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset2, + 10000 * UNITS, + ETH, + 10000 * UNITS, + )); + + let trades = vec![ + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset1, + asset_out: insufficient_asset2, + }, + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset2, + asset_out: ETH, + }, + ]; + + let alice_balance_before_trade = Balances::free_balance(AccountId::from(ALICE)); + + let insufficient_asset1_balance = 100 * UNITS; + assert_ok!(Currencies::deposit( + insufficient_asset1, + &ALICE.into(), + insufficient_asset1_balance, + )); + + let extra_ed_charge = UNITS / 10; + + let amount_to_sell = insufficient_asset1_balance; + assert_ok!(Router::sell( + hydradx_runtime::RuntimeOrigin::signed(ALICE.into()), + insufficient_asset1, + ETH, + amount_to_sell, + 0, + trades + )); + let alice_balance_after_trade = Balances::free_balance(AccountId::from(ALICE)); + + //ED should be refunded to alice as she sold all her asset, minus the 10% extra + assert_eq!(alice_balance_before_trade, alice_balance_after_trade + extra_ed_charge); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); + } + + #[test] + fn ed_charging_should_not_be_disabled_when_only_one_trade_with_insufficient_assets() { + TestNet::reset(); + + Hydra::execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let name = b"INSUF1".to_vec(); + let insufficient_asset_1 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + let name = b"INSUF12".to_vec(); + let insufficient_asset_2 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + assert_ok!(Currencies::deposit(insufficient_asset_1, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset_2, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::update_balance( + hydradx_runtime::RuntimeOrigin::root(), + DAVE.into(), + HDX, + 100000 * UNITS as i128, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset_1, + 100000 * UNITS, + insufficient_asset_2, + 100000 * UNITS, + )); + + let trades = vec![Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset_1, + asset_out: insufficient_asset_2, + }]; + + //Act + let amount_to_sell = 10 * UNITS; + assert_ok!(Currencies::deposit(insufficient_asset_1, &ALICE.into(), amount_to_sell,)); + let ed = InsufficientEDinHDX::get(); + let extra_ed_charge = UNITS / 10; + assert_balance!(ALICE.into(), HDX, 1000 * UNITS - ed); + + let amount_to_sell = amount_to_sell; + assert_ok!(Router::sell( + hydradx_runtime::RuntimeOrigin::signed(ALICE.into()), + insufficient_asset_1, + insufficient_asset_2, + amount_to_sell, + 0, + trades + ),); + + //ED for insufficient_asset_1 is refunded, but ED for insufficient_asset_2 is charged plus extra 10% + assert_balance!(ALICE.into(), HDX, 1000 * UNITS - 1 * ed - extra_ed_charge); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); + } + + #[test] + fn buy_should_work_with_only_insufficient_assets() { + TestNet::reset(); + + Hydra::execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let name = b"INSUF1".to_vec(); + let insufficient_asset1 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + let name = b"INSUF2".to_vec(); + let insufficient_asset2 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + let name = b"INSUF3".to_vec(); + let insufficient_asset3 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + let name = b"INSUF4".to_vec(); + let insufficient_asset4 = AssetRegistry::register_insufficient_asset( + None, + Some(name.try_into().unwrap()), + AssetKind::External, + Some(1_000), + None, + None, + None, + None, + ) + .unwrap(); + + assert_ok!(Currencies::deposit(insufficient_asset1, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset2, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset3, &DAVE.into(), 100000 * UNITS,)); + assert_ok!(Currencies::deposit(insufficient_asset4, &DAVE.into(), 100000 * UNITS,)); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset1, + 10000 * UNITS, + insufficient_asset2, + 10000 * UNITS, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset2, + 10000 * UNITS, + insufficient_asset3, + 10000 * UNITS, + )); + + assert_ok!(XYK::create_pool( + RuntimeOrigin::signed(DAVE.into()), + insufficient_asset3, + 10000 * UNITS, + insufficient_asset4, + 10000 * UNITS, + )); + + let trades = vec![ + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset1, + asset_out: insufficient_asset2, + }, + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset2, + asset_out: insufficient_asset3, + }, + Trade { + pool: PoolType::XYK, + asset_in: insufficient_asset3, + asset_out: insufficient_asset4, + }, + ]; + + assert_ok!(Currencies::deposit(insufficient_asset1, &ALICE.into(), 1500 * UNITS,)); + + let ed = InsufficientEDinHDX::get(); + assert_balance!(ALICE.into(), HDX, 1000 * UNITS - ed); + + let amount_to_buy = 20 * UNITS; + assert_ok!(Router::buy( + hydradx_runtime::RuntimeOrigin::signed(ALICE.into()), + insufficient_asset1, + insufficient_asset4, + amount_to_buy, + u128::MAX, + trades + )); + + assert_balance!(ALICE.into(), HDX, 1000 * UNITS - 2 * ed); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); + } + #[test] fn sell_should_pass_when_ed_refund_after_selling_all_shitcoin() { TestNet::reset(); diff --git a/pallets/route-executor/Cargo.toml b/pallets/route-executor/Cargo.toml index 5457d35c0..839ef0e51 100644 --- a/pallets/route-executor/Cargo.toml +++ b/pallets/route-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-route-executor' -version = '2.5.0' +version = '2.5.1' description = 'A pallet to execute a route containing a sequence of trades' authors = ['GalacticCouncil'] edition = '2021' diff --git a/pallets/route-executor/src/lib.rs b/pallets/route-executor/src/lib.rs index b393bf8b6..cf078c736 100644 --- a/pallets/route-executor/src/lib.rs +++ b/pallets/route-executor/src/lib.rs @@ -47,6 +47,8 @@ use sp_std::{vec, vec::Vec}; mod tests; pub mod weights; +mod types; + pub use weights::WeightInfo; // Re-export pallet items so that they can be accessed from the crate namespace. @@ -166,6 +168,11 @@ pub mod pallet { NotAllowed, } + ///Flag to indicate when to skip ED handling + #[pallet::storage] + #[pallet::getter(fn last_trade_position)] + pub type SkipEd = StorageValue<_, types::SkipEd, OptionQuery>; + /// Storing routes for asset pairs #[pallet::storage] #[pallet::getter(fn route)] @@ -223,7 +230,10 @@ pub mod pallet { Error::::TradingLimitReached ); - for (trade_amount, trade) in trade_amounts.iter().zip(route) { + let route_length = route.len(); + for (trade_index, (trade_amount, trade)) in trade_amounts.iter().zip(route.clone()).enumerate() { + Self::disable_ed_handling_for_insufficient_assets(route_length, trade_index, trade); + let user_balance_of_asset_in_before_trade = T::Currency::reducible_balance(trade.asset_in, &who, Preservation::Expendable, Fortitude::Polite); @@ -246,6 +256,8 @@ pub mod pallet { )?; } + SkipEd::::kill(); + Self::ensure_that_user_received_asset_out_at_most( who, asset_in, @@ -305,7 +317,9 @@ pub mod pallet { let first_trade = trade_amounts.last().ok_or(Error::::RouteCalculationFailed)?; ensure!(first_trade.amount_in <= max_amount_in, Error::::TradingLimitReached); - for (trade_amount, trade) in trade_amounts.iter().rev().zip(route) { + let route_length = route.len(); + for (trade_index, (trade_amount, trade)) in trade_amounts.iter().rev().zip(route).enumerate() { + Self::disable_ed_handling_for_insufficient_assets(route_length, trade_index, trade); let user_balance_of_asset_out_before_trade = T::Currency::reducible_balance(trade.asset_out, &who, Preservation::Preserve, Fortitude::Polite); let execution_result = T::AMM::execute_buy( @@ -328,6 +342,8 @@ pub mod pallet { )?; } + SkipEd::::kill(); + Self::ensure_that_user_spent_asset_in_at_least( who, asset_in, @@ -568,6 +584,41 @@ impl Pallet { Ok(route) } + pub fn disable_ed_handling_for_insufficient_assets( + route_length: usize, + trade_index: usize, + trade: Trade, + ) { + if route_length > 1 + && (!T::InspectRegistry::is_sufficient(trade.asset_in) + || !T::InspectRegistry::is_sufficient(trade.asset_out)) + { + //We optimize to set the state for middle trades only once at the first middle trade, then we change no state till the last trade + match trade_index { + 0 => SkipEd::::put(types::SkipEd::Lock), + trade_index if trade_index.saturating_add(1) == route_length => SkipEd::::put(types::SkipEd::Unlock), + 1 => SkipEd::::put(types::SkipEd::LockAndUnlock), + _ => (), + } + } + } + + pub fn skip_ed_lock() -> bool { + if let Ok(v) = SkipEd::::try_get() { + return matches!(v, types::SkipEd::Lock | types::SkipEd::LockAndUnlock); + } + + false + } + + pub fn skip_ed_unlock() -> bool { + if let Ok(v) = SkipEd::::try_get() { + return matches!(v, types::SkipEd::Unlock | types::SkipEd::LockAndUnlock); + } + + false + } + fn validate_route(route: &[Trade]) -> Result<(T::Balance, T::Balance), DispatchError> { let reference_amount_in = Self::calculate_reference_amount_in(route)?; let route_validation = Self::validate_sell(route.to_vec(), reference_amount_in); diff --git a/pallets/route-executor/src/types.rs b/pallets/route-executor/src/types.rs new file mode 100644 index 000000000..f77809c12 --- /dev/null +++ b/pallets/route-executor/src/types.rs @@ -0,0 +1,9 @@ +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::pallet_prelude::TypeInfo; + +#[derive(Debug, Encode, Decode, Copy, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub enum SkipEd { + Lock, + LockAndUnlock, + Unlock, +} diff --git a/pallets/route-executor/src/weights.rs b/pallets/route-executor/src/weights.rs index 018fd4a51..653099c85 100644 --- a/pallets/route-executor/src/weights.rs +++ b/pallets/route-executor/src/weights.rs @@ -19,7 +19,7 @@ //! Autogenerated weights for `pallet_route_executor` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-06-20, STEPS: `10`, REPEAT: `30`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-07-23, STEPS: `10`, REPEAT: `30`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` @@ -48,6 +48,7 @@ use core::marker::PhantomData; /// Weight functions needed for `pallet_route_executor`. pub trait WeightInfo { + fn skip_ed_handling_for_trade_with_insufficient_assets() -> Weight; fn calculate_and_execute_sell_in_lbp(c: u32, ) -> Weight; fn calculate_and_execute_buy_in_lbp(c: u32, b: u32, ) -> Weight; fn set_route_for_xyk() -> Weight; @@ -59,7 +60,21 @@ pub trait WeightInfo { } /// Weights for `pallet_route_executor` using the HydraDX node and recommended hardware. -impl WeightInfo for () { +pub struct HydraWeight(PhantomData); +impl WeightInfo for HydraWeight { + /// Storage: `AssetRegistry::Assets` (r:1 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:0 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + fn skip_ed_handling_for_trade_with_insufficient_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `944` + // Estimated: `3590` + // Minimum execution time: 13_700_000 picoseconds. + Weight::from_parts(13_874_000, 3590) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } /// Storage: `LBP::PoolData` (r:1 w:0) /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) /// Storage: `Tokens::Accounts` (r:5 w:5) @@ -70,6 +85,8 @@ impl WeightInfo for () { /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) /// Storage: `Tokens::Locks` (r:1 w:1) /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:2 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) @@ -77,14 +94,14 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 1]`. fn calculate_and_execute_sell_in_lbp(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `3535` + // Measured: `3743` // Estimated: `13905` - // Minimum execution time: 354_159_000 picoseconds. - Weight::from_parts(358_572_573, 13905) - // Standard Error: 306_143 - .saturating_add(Weight::from_parts(70_834_738, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(16_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + // Minimum execution time: 352_057_000 picoseconds. + Weight::from_parts(358_601_823, 13905) + // Standard Error: 319_985 + .saturating_add(Weight::from_parts(70_948_801, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(17_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `LBP::PoolData` (r:1 w:0) /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) @@ -96,6 +113,8 @@ impl WeightInfo for () { /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) /// Storage: `Tokens::Locks` (r:1 w:1) /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:2 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) @@ -104,29 +123,200 @@ impl WeightInfo for () { /// The range of component `b` is `[0, 1]`. fn calculate_and_execute_buy_in_lbp(c: u32, b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1637 + b * (1923 ±0)` - // Estimated: `6156 + b * (7749 ±228_644_766_292_339_040)` - // Minimum execution time: 94_614_000 picoseconds. - Weight::from_parts(96_046_000, 6156) - // Standard Error: 876_130 - .saturating_add(Weight::from_parts(3_658_596, 0).saturating_mul(c.into())) - // Standard Error: 1_923_356 - .saturating_add(Weight::from_parts(272_645_114, 0).saturating_mul(b.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().reads((13_u64).saturating_mul(b.into()))) - .saturating_add(RocksDbWeight::get().writes((7_u64).saturating_mul(b.into()))) + // Measured: `1637 + b * (2131 ±0)` + // Estimated: `6156 + b * (7749 ±245_709_589_663_843_264)` + // Minimum execution time: 94_752_000 picoseconds. + Weight::from_parts(96_589_000, 6156) + // Standard Error: 840_786 + .saturating_add(Weight::from_parts(3_341_044, 0).saturating_mul(c.into())) + // Standard Error: 1_845_765 + .saturating_add(Weight::from_parts(271_881_978, 0).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().reads((14_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().writes((8_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 7749).saturating_mul(b.into())) } + /// Storage: `EmaOracle::Oracles` (r:2 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `Router::Routes` (r:1 w:1) + /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:7 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:15 w:0) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::Assets` (r:6 w:0) /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `XYK::ShareToken` (r:6 w:0) + /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:7 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:5 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AccountCurrencyMap` (r:1 w:0) + /// Proof: `MultiTransactionPayment::AccountCurrencyMap` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MultiTransactionPayment::AcceptedCurrencies` (r:5 w:0) + /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `EmaOracle::Accumulator` (r:1 w:0) + /// Proof: `EmaOracle::Accumulator` (`max_values`: Some(1), `max_size`: Some(5921), added: 6416, mode: `MaxEncodedLen`) + /// Storage: `Tokens::TotalIssuance` (r:1 w:0) + /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_route_for_xyk() -> Weight { + // Proof Size summary in bytes: + // Measured: `7004` + // Estimated: `39735` + // Minimum execution time: 1_946_884_000 picoseconds. + Weight::from_parts(1_957_705_000, 39735) + .saturating_add(T::DbWeight::get().reads(58_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Router::Routes` (r:0 w:1) + /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) + fn force_insert_route() -> Weight { + // Proof Size summary in bytes: + // Measured: `1012` + // Estimated: `0` + // Minimum execution time: 25_748_000 picoseconds. + Weight::from_parts(26_215_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Router::Routes` (r:1 w:0) + /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) + fn get_route() -> Weight { + // Proof Size summary in bytes: + // Measured: `800` + // Estimated: `3555` + // Minimum execution time: 7_522_000 picoseconds. + Weight::from_parts(7_689_000, 3555) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `EmaOracle::Oracles` (r:2 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + fn get_oracle_price_for_xyk() -> Weight { + // Proof Size summary in bytes: + // Measured: `1452` + // Estimated: `6294` + // Minimum execution time: 26_571_000 picoseconds. + Weight::from_parts(27_038_000, 6294) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `EmaOracle::Oracles` (r:4 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + fn get_oracle_price_for_omnipool() -> Weight { + // Proof Size summary in bytes: + // Measured: `1814` + // Estimated: `11598` + // Minimum execution time: 40_728_000 picoseconds. + Weight::from_parts(41_338_000, 11598) + .saturating_add(T::DbWeight::get().reads(4_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:0) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:2 w:0) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + fn calculate_spot_price_with_fee_in_lbp() -> Weight { + // Proof Size summary in bytes: + // Measured: `1674` + // Estimated: `6156` + // Minimum execution time: 35_793_000 picoseconds. + Weight::from_parts(36_285_000, 6156) + .saturating_add(T::DbWeight::get().reads(4_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `AssetRegistry::Assets` (r:1 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:0 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + fn skip_ed_handling_for_trade_with_insufficient_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `944` + // Estimated: `3590` + // Minimum execution time: 13_700_000 picoseconds. + Weight::from_parts(13_874_000, 3590) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:5 w:5) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:1) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// The range of component `c` is `[0, 1]`. + fn calculate_and_execute_sell_in_lbp(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `3743` + // Estimated: `13905` + // Minimum execution time: 352_057_000 picoseconds. + Weight::from_parts(358_601_823, 13905) + // Standard Error: 319_985 + .saturating_add(Weight::from_parts(70_948_801, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(17_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + /// Storage: `LBP::PoolData` (r:1 w:0) + /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Accounts` (r:5 w:5) + /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:2 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Tokens::Locks` (r:1 w:1) + /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Duster::AccountBlacklist` (r:2 w:0) + /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) + /// Proof: `AssetRegistry::BannedAssets` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) + /// The range of component `c` is `[1, 2]`. + /// The range of component `b` is `[0, 1]`. + fn calculate_and_execute_buy_in_lbp(c: u32, b: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1637 + b * (2131 ±0)` + // Estimated: `6156 + b * (7749 ±245_709_589_663_843_264)` + // Minimum execution time: 94_752_000 picoseconds. + Weight::from_parts(96_589_000, 6156) + // Standard Error: 840_786 + .saturating_add(Weight::from_parts(3_341_044, 0).saturating_mul(c.into())) + // Standard Error: 1_845_765 + .saturating_add(Weight::from_parts(271_881_978, 0).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().reads((14_u64).saturating_mul(b.into()))) + .saturating_add(RocksDbWeight::get().writes((8_u64).saturating_mul(b.into()))) + .saturating_add(Weight::from_parts(0, 7749).saturating_mul(b.into())) + } + /// Storage: `EmaOracle::Oracles` (r:2 w:0) + /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) /// Storage: `Router::Routes` (r:1 w:1) /// Proof: `Router::Routes` (`max_values`: None, `max_size`: Some(90), added: 2565, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:7 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Tokens::Accounts` (r:15 w:0) /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `AssetRegistry::Assets` (r:6 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) /// Storage: `XYK::ShareToken` (r:6 w:0) /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:7 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:5 w:0) @@ -141,11 +331,11 @@ impl WeightInfo for () { /// Proof: `Tokens::TotalIssuance` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) fn set_route_for_xyk() -> Weight { // Proof Size summary in bytes: - // Measured: `6426` + // Measured: `7004` // Estimated: `39735` - // Minimum execution time: 1_917_993_000 picoseconds. - Weight::from_parts(1_930_602_000, 39735) - .saturating_add(RocksDbWeight::get().reads(55_u64)) + // Minimum execution time: 1_946_884_000 picoseconds. + Weight::from_parts(1_957_705_000, 39735) + .saturating_add(RocksDbWeight::get().reads(58_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Router::Routes` (r:0 w:1) @@ -154,8 +344,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1012` // Estimated: `0` - // Minimum execution time: 25_174_000 picoseconds. - Weight::from_parts(25_689_000, 0) + // Minimum execution time: 25_748_000 picoseconds. + Weight::from_parts(26_215_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Router::Routes` (r:1 w:0) @@ -164,19 +354,18 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `800` // Estimated: `3555` - // Minimum execution time: 7_562_000 picoseconds. - Weight::from_parts(7_748_000, 3555) + // Minimum execution time: 7_522_000 picoseconds. + Weight::from_parts(7_689_000, 3555) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: `EmaOracle::Oracles` (r:2 w:0) /// Proof: `EmaOracle::Oracles` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn get_oracle_price_for_xyk() -> Weight { // Proof Size summary in bytes: // Measured: `1452` // Estimated: `6294` - // Minimum execution time: 21_820_000 picoseconds. - Weight::from_parts(22_320_000, 6294) + // Minimum execution time: 26_571_000 picoseconds. + Weight::from_parts(27_038_000, 6294) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `EmaOracle::Oracles` (r:4 w:0) @@ -185,11 +374,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1814` // Estimated: `11598` - // Minimum execution time: 35_720_000 picoseconds. - Weight::from_parts(36_110_000, 11598) + // Minimum execution time: 40_728_000 picoseconds. + Weight::from_parts(41_338_000, 11598) .saturating_add(RocksDbWeight::get().reads(4_u64)) } - /// Storage: `LBP::PoolData` (r:1 w:0) /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) /// Storage: `Tokens::Locks` (r:1 w:0) @@ -200,8 +388,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1674` // Estimated: `6156` - // Minimum execution time: 36_086_000 picoseconds. - Weight::from_parts(36_646_000, 6156) + // Minimum execution time: 35_793_000 picoseconds. + Weight::from_parts(36_285_000, 6156) .saturating_add(RocksDbWeight::get().reads(4_u64)) } } diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index 60e6e1458..285bfed06 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-runtime" -version = "255.0.0" +version = "256.0.0" authors = ["GalacticCouncil"] edition = "2021" license = "Apache 2.0" diff --git a/runtime/hydradx/src/assets.rs b/runtime/hydradx/src/assets.rs index 3d555f48f..1aa98f746 100644 --- a/runtime/hydradx/src/assets.rs +++ b/runtime/hydradx/src/assets.rs @@ -221,6 +221,10 @@ impl SufficiencyCheck { impl OnTransfer for SufficiencyCheck { fn on_transfer(asset: AssetId, from: &AccountId, to: &AccountId, _amount: Balance) -> DispatchResult { + if pallet_route_executor::Pallet::::skip_ed_lock() { + return Ok(()); + } + //NOTE: `to` is paying ED if `from` is whitelisted. //This can happen if pallet's account transfers insufficient tokens to another account. if ::DustRemovalWhitelist::contains(from) { @@ -240,6 +244,10 @@ impl OnDeposit for SufficiencyCheck { pub struct OnKilledTokenAccount; impl Happened<(AccountId, AssetId)> for OnKilledTokenAccount { fn happened((who, asset): &(AccountId, AssetId)) { + if pallet_route_executor::Pallet::::skip_ed_unlock() { + return; + } + if AssetRegistry::is_sufficient(*asset) || frame_system::Pallet::::account(who).sufficients.is_zero() { return; } @@ -872,6 +880,10 @@ impl RouterWeightInfo { weights::pallet_route_executor::HydraWeight::::calculate_spot_price_with_fee_in_lbp().proof_size(), ) } + + pub fn skip_ed_handling_overweight() -> Weight { + weights::pallet_route_executor::HydraWeight::::skip_ed_handling_for_trade_with_insufficient_assets() + } } impl AmmTradeWeights> for RouterWeightInfo { @@ -912,6 +924,14 @@ impl AmmTradeWeights> for RouterWeightInfo { weight.saturating_accrue(amm_weight); } + //We add the overweight for skipping ED handling if route has multiple trades and we have any insufficient asset + if route.len() > 1 + && route.iter().any(|trade| { + !AssetRegistry::is_sufficient(trade.asset_in) || !AssetRegistry::is_sufficient(trade.asset_out) + }) { + weight.saturating_accrue(Self::skip_ed_handling_overweight()); + } + weight } @@ -952,6 +972,14 @@ impl AmmTradeWeights> for RouterWeightInfo { weight.saturating_accrue(amm_weight); } + //We add the overweight for skipping ED handling if we have any insufficient asset + if route.len() > 1 + && route.iter().any(|trade| { + !AssetRegistry::is_sufficient(trade.asset_in) || !AssetRegistry::is_sufficient(trade.asset_out) + }) { + weight.saturating_accrue(Self::skip_ed_handling_overweight()); + } + weight } diff --git a/runtime/hydradx/src/benchmarking/route_executor.rs b/runtime/hydradx/src/benchmarking/route_executor.rs index d7cca10a9..e9ced2afd 100644 --- a/runtime/hydradx/src/benchmarking/route_executor.rs +++ b/runtime/hydradx/src/benchmarking/route_executor.rs @@ -155,7 +155,28 @@ fn create_xyk_pool(asset_a: u32, asset_b: u32) { runtime_benchmarks! { {Runtime, pallet_route_executor} - // Calculates the weight of LBP trade. Used in the calculation to determine the weight of the overhead. + // Calculates the weight all the logic of ED handling of insufficient assets + skip_ed_handling_for_trade_with_insufficient_assets{ + let asset_1 = register_external_asset(b"FCA".to_vec()).map_err(|_| BenchmarkError::Stop("Failed to register asset"))?; + let asset_2 = register_external_asset(b"FCB".to_vec()).map_err(|_| BenchmarkError::Stop("Failed to register asset"))?; + + let trade = Trade { + pool: PoolType::LBP, + asset_in: asset_1, + asset_out: asset_2 + }; + + }: { + //We assume the worst case, so we change the state 4 times(1 add, 2 modify, 1 kill) + Router::disable_ed_handling_for_insufficient_assets(3, 0, trade); + Router::disable_ed_handling_for_insufficient_assets(3, 1, trade); + Router::disable_ed_handling_for_insufficient_assets(3, 2, trade); + } + verify { + + } + + calculate_and_execute_sell_in_lbp { let c in 0..1; // if c == 1, calculate_sell_trade_amounts is executed diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index e80d28be2..8e5c13482 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -113,7 +113,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hydradx"), impl_name: create_runtime_str!("hydradx"), authoring_version: 1, - spec_version: 255, + spec_version: 256, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/runtime/hydradx/src/weights/orml_tokens.rs b/runtime/hydradx/src/weights/orml_tokens.rs index 2c98146ec..33817844b 100644 --- a/runtime/hydradx/src/weights/orml_tokens.rs +++ b/runtime/hydradx/src/weights/orml_tokens.rs @@ -19,29 +19,24 @@ //! Autogenerated weights for `orml_tokens` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-05-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-07-23, STEPS: `10`, REPEAT: `30`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/release/hydradx +// target/release/hydradx // benchmark // pallet +// --chain=dev +// --steps=10 +// --repeat=30 // --wasm-execution=compiled -// --pallet -// * -// --extrinsic -// * -// --heap-pages -// 4096 -// --steps -// 50 -// --repeat -// 20 +// --heap-pages=4096 // --template=scripts/pallet-weight-template.hbs -// --output -// weights/ +// --pallet=orml-tokens +// --output=orml.rs +// --extrinsic=* #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,6 +52,8 @@ pub struct WeightInfo(PhantomData); /// Weights for `orml_tokens` using the HydraDX node and recommended hardware. pub struct HydraWeight(PhantomData); impl orml_tokens::WeightInfo for HydraWeight { + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:1 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) @@ -81,17 +78,19 @@ impl orml_tokens::WeightInfo for HydraWeight { /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `3205` + // Measured: `3409` // Estimated: `11322` - // Minimum execution time: 232_476_000 picoseconds. - Weight::from_parts(233_663_000, 11322) - .saturating_add(T::DbWeight::get().reads(21_u64)) + // Minimum execution time: 237_730_000 picoseconds. + Weight::from_parts(239_119_000, 11322) + .saturating_add(T::DbWeight::get().reads(22_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } /// Storage: `Tokens::Accounts` (r:4 w:4) /// Proof: `Tokens::Accounts` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:1 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) @@ -112,13 +111,15 @@ impl orml_tokens::WeightInfo for HydraWeight { /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn transfer_all() -> Weight { // Proof Size summary in bytes: - // Measured: `3257` + // Measured: `3461` // Estimated: `11322` - // Minimum execution time: 236_104_000 picoseconds. - Weight::from_parts(237_656_000, 11322) - .saturating_add(T::DbWeight::get().reads(21_u64)) + // Minimum execution time: 241_359_000 picoseconds. + Weight::from_parts(242_887_000, 11322) + .saturating_add(T::DbWeight::get().reads(22_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:1 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) @@ -143,13 +144,15 @@ impl orml_tokens::WeightInfo for HydraWeight { /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn transfer_keep_alive() -> Weight { // Proof Size summary in bytes: - // Measured: `3255` + // Measured: `3459` // Estimated: `11322` - // Minimum execution time: 161_927_000 picoseconds. - Weight::from_parts(163_592_000, 11322) - .saturating_add(T::DbWeight::get().reads(21_u64)) + // Minimum execution time: 166_510_000 picoseconds. + Weight::from_parts(167_910_000, 11322) + .saturating_add(T::DbWeight::get().reads(22_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:1 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) @@ -174,11 +177,11 @@ impl orml_tokens::WeightInfo for HydraWeight { /// Proof: `AssetRegistry::ExistentialDepositCounter` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn force_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `3257` + // Measured: `3461` // Estimated: `11322` - // Minimum execution time: 232_442_000 picoseconds. - Weight::from_parts(233_954_000, 11322) - .saturating_add(T::DbWeight::get().reads(21_u64)) + // Minimum execution time: 238_730_000 picoseconds. + Weight::from_parts(240_390_000, 11322) + .saturating_add(T::DbWeight::get().reads(22_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } /// Storage: `Tokens::Accounts` (r:1 w:1) @@ -195,10 +198,10 @@ impl orml_tokens::WeightInfo for HydraWeight { /// Proof: `MultiTransactionPayment::AcceptedCurrencies` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) fn set_balance() -> Weight { // Proof Size summary in bytes: - // Measured: `2213` + // Measured: `2209` // Estimated: `3593` - // Minimum execution time: 53_851_000 picoseconds. - Weight::from_parts(54_455_000, 3593) + // Minimum execution time: 55_376_000 picoseconds. + Weight::from_parts(56_132_000, 3593) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } diff --git a/runtime/hydradx/src/weights/pallet_route_executor.rs b/runtime/hydradx/src/weights/pallet_route_executor.rs index c24ae0a0a..0d8ff8b0d 100644 --- a/runtime/hydradx/src/weights/pallet_route_executor.rs +++ b/runtime/hydradx/src/weights/pallet_route_executor.rs @@ -19,7 +19,7 @@ //! Autogenerated weights for `pallet_route_executor` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-07-23, STEPS: `10`, REPEAT: `30`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-07-25, STEPS: `10`, REPEAT: `30`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` @@ -52,6 +52,19 @@ pub struct WeightInfo(PhantomData); /// Weights for `pallet_route_executor` using the HydraDX node and recommended hardware. pub struct HydraWeight(PhantomData); impl pallet_route_executor::WeightInfo for HydraWeight { + /// Storage: `AssetRegistry::Assets` (r:1 w:0) + /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:0 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + fn skip_ed_handling_for_trade_with_insufficient_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `944` + // Estimated: `3590` + // Minimum execution time: 13_700_000 picoseconds. + Weight::from_parts(13_874_000, 3590) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } /// Storage: `LBP::PoolData` (r:1 w:0) /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) /// Storage: `Tokens::Accounts` (r:5 w:5) @@ -62,6 +75,8 @@ impl pallet_route_executor::WeightInfo for HydraWeight< /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) /// Storage: `Tokens::Locks` (r:1 w:1) /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:2 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) @@ -69,14 +84,14 @@ impl pallet_route_executor::WeightInfo for HydraWeight< /// The range of component `c` is `[0, 1]`. fn calculate_and_execute_sell_in_lbp(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `3535` + // Measured: `3743` // Estimated: `13905` - // Minimum execution time: 347_049_000 picoseconds. - Weight::from_parts(350_762_308, 13905) - // Standard Error: 214_404 - .saturating_add(Weight::from_parts(69_087_003, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(16_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + // Minimum execution time: 352_057_000 picoseconds. + Weight::from_parts(358_601_823, 13905) + // Standard Error: 319_985 + .saturating_add(Weight::from_parts(70_948_801, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(17_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `LBP::PoolData` (r:1 w:0) /// Proof: `LBP::PoolData` (`max_values`: None, `max_size`: Some(163), added: 2638, mode: `MaxEncodedLen`) @@ -88,6 +103,8 @@ impl pallet_route_executor::WeightInfo for HydraWeight< /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) /// Storage: `Tokens::Locks` (r:1 w:1) /// Proof: `Tokens::Locks` (`max_values`: None, `max_size`: Some(1261), added: 3736, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:1) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:2 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:2 w:0) @@ -96,17 +113,17 @@ impl pallet_route_executor::WeightInfo for HydraWeight< /// The range of component `b` is `[0, 1]`. fn calculate_and_execute_buy_in_lbp(c: u32, b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1637 + b * (1923 ±0)` - // Estimated: `6156 + b * (7749 ±228_644_766_292_339_040)` - // Minimum execution time: 94_096_000 picoseconds. - Weight::from_parts(95_234_000, 6156) - // Standard Error: 881_744 - .saturating_add(Weight::from_parts(3_499_280, 0).saturating_mul(c.into())) - // Standard Error: 1_935_679 - .saturating_add(Weight::from_parts(266_101_120, 0).saturating_mul(b.into())) + // Measured: `1637 + b * (2131 ±0)` + // Estimated: `6156 + b * (7749 ±245_709_589_663_843_264)` + // Minimum execution time: 94_752_000 picoseconds. + Weight::from_parts(96_589_000, 6156) + // Standard Error: 840_786 + .saturating_add(Weight::from_parts(3_341_044, 0).saturating_mul(c.into())) + // Standard Error: 1_845_765 + .saturating_add(Weight::from_parts(271_881_978, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().reads((13_u64).saturating_mul(b.into()))) - .saturating_add(T::DbWeight::get().writes((7_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().reads((14_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().writes((8_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 7749).saturating_mul(b.into())) } /// Storage: `EmaOracle::Oracles` (r:2 w:0) @@ -121,6 +138,8 @@ impl pallet_route_executor::WeightInfo for HydraWeight< /// Proof: `AssetRegistry::Assets` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) /// Storage: `XYK::ShareToken` (r:6 w:0) /// Proof: `XYK::ShareToken` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Router::SkipEd` (r:1 w:0) + /// Proof: `Router::SkipEd` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:7 w:0) /// Proof: `Duster::AccountBlacklist` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `AssetRegistry::BannedAssets` (r:5 w:0) @@ -137,9 +156,9 @@ impl pallet_route_executor::WeightInfo for HydraWeight< // Proof Size summary in bytes: // Measured: `7004` // Estimated: `39735` - // Minimum execution time: 1_880_149_000 picoseconds. - Weight::from_parts(1_889_973_000, 39735) - .saturating_add(T::DbWeight::get().reads(57_u64)) + // Minimum execution time: 1_946_884_000 picoseconds. + Weight::from_parts(1_957_705_000, 39735) + .saturating_add(T::DbWeight::get().reads(58_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Router::Routes` (r:0 w:1) @@ -148,8 +167,8 @@ impl pallet_route_executor::WeightInfo for HydraWeight< // Proof Size summary in bytes: // Measured: `1012` // Estimated: `0` - // Minimum execution time: 25_566_000 picoseconds. - Weight::from_parts(26_013_000, 0) + // Minimum execution time: 25_748_000 picoseconds. + Weight::from_parts(26_215_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Router::Routes` (r:1 w:0) @@ -158,8 +177,8 @@ impl pallet_route_executor::WeightInfo for HydraWeight< // Proof Size summary in bytes: // Measured: `800` // Estimated: `3555` - // Minimum execution time: 7_753_000 picoseconds. - Weight::from_parts(7_998_000, 3555) + // Minimum execution time: 7_522_000 picoseconds. + Weight::from_parts(7_689_000, 3555) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `EmaOracle::Oracles` (r:2 w:0) @@ -168,8 +187,8 @@ impl pallet_route_executor::WeightInfo for HydraWeight< // Proof Size summary in bytes: // Measured: `1452` // Estimated: `6294` - // Minimum execution time: 26_531_000 picoseconds. - Weight::from_parts(27_010_000, 6294) + // Minimum execution time: 26_571_000 picoseconds. + Weight::from_parts(27_038_000, 6294) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `EmaOracle::Oracles` (r:4 w:0) @@ -178,8 +197,8 @@ impl pallet_route_executor::WeightInfo for HydraWeight< // Proof Size summary in bytes: // Measured: `1814` // Estimated: `11598` - // Minimum execution time: 40_726_000 picoseconds. - Weight::from_parts(41_280_000, 11598) + // Minimum execution time: 40_728_000 picoseconds. + Weight::from_parts(41_338_000, 11598) .saturating_add(T::DbWeight::get().reads(4_u64)) } /// Storage: `LBP::PoolData` (r:1 w:0) @@ -192,8 +211,8 @@ impl pallet_route_executor::WeightInfo for HydraWeight< // Proof Size summary in bytes: // Measured: `1674` // Estimated: `6156` - // Minimum execution time: 35_350_000 picoseconds. - Weight::from_parts(35_956_000, 6156) + // Minimum execution time: 35_793_000 picoseconds. + Weight::from_parts(36_285_000, 6156) .saturating_add(T::DbWeight::get().reads(4_u64)) } } \ No newline at end of file