diff --git a/libs/traits/src/benchmarking.rs b/libs/traits/src/benchmarking.rs index cffc831b2b..dcd2420c75 100644 --- a/libs/traits/src/benchmarking.rs +++ b/libs/traits/src/benchmarking.rs @@ -58,3 +58,56 @@ pub trait OrderBookBenchmarkHelper { /// Fulfills the given swap order from the trader account fn bench_fill_order_full(trader: Self::AccountId, order_id: Self::OrderIdNonce); } + +/// A representation of information helpful when doing a foreign investment +/// benchmark setup. +pub struct BenchForeignInvestmentSetupInfo { + /// The substrate investor address + pub investor: AccountId, + /// The investment id + pub investment_id: InvestmentId, + /// The pool currency which eventually will be invested + pub pool_currency: CurrencyId, + /// The foreign currency which shall be invested and thus swapped into pool + /// currency beforehand + pub foreign_currency: CurrencyId, + /// Bidirectionally funded to fulfill token swap orders + pub funded_trader: AccountId, +} + +/// Benchmark utility for updating/collecting foreign investments and +/// redemptions. + +pub trait ForeignInvestmentBenchmarkHelper { + type AccountId; + type Balance; + type CurrencyId; + type InvestmentId; + + /// Perform necessary setup to enable an investor to invest with or redeem + /// into a foreign currency. + /// + /// Returns + /// * The substrate investor address + /// * The investment id + /// * The pool currency id + /// * The foreign currency id + /// * A trading account which can bidirectionally fulfill swap orders for + /// the (foreign, pool) currency pair + fn bench_prepare_foreign_investments_setup( + ) -> BenchForeignInvestmentSetupInfo; + + /// Perform necessary setup to prepare for the worst benchmark case by + /// calling just a single subsequent function. + /// + /// NOTE: For the time being, the worst case should be collecting a + /// redemption when there is an active invest swap from foreign to pool. The + /// redemption collection will initiate a swap from pool to foreign such + /// that there is a swap merge conflict to be resolved. + fn bench_prep_foreign_investments_worst_case( + investor: Self::AccountId, + investment_id: Self::InvestmentId, + foreign_currency: Self::CurrencyId, + pool_currency: Self::CurrencyId, + ); +} diff --git a/pallets/foreign-investments/src/impls/benchmark_utils.rs b/pallets/foreign-investments/src/impls/benchmark_utils.rs new file mode 100644 index 0000000000..9de3beebb5 --- /dev/null +++ b/pallets/foreign-investments/src/impls/benchmark_utils.rs @@ -0,0 +1,159 @@ +// Copyright 2023 Centrifuge Foundation (centrifuge.io). +// This file is part of Centrifuge Chain project. + +// Centrifuge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version (see http://www.gnu.org/licenses). + +// Centrifuge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +use cfg_traits::{ + benchmarking::{ + BenchForeignInvestmentSetupInfo, ForeignInvestmentBenchmarkHelper, + InvestmentIdBenchmarkHelper, OrderBookBenchmarkHelper, PoolBenchmarkHelper, + }, + investments::{ForeignInvestment, OrderManager}, +}; +use cfg_types::{ + fixed_point::Ratio, + orders::{FulfillmentWithPrice, TotalOrder}, + tokens::CurrencyId, +}; +use frame_benchmarking::Zero; +use frame_support::assert_ok; +use sp_runtime::{DispatchError, FixedPointNumber, Perquintill}; + +use crate::{Config, Pallet}; + +pub const CURRENCY_POOL: CurrencyId = CurrencyId::ForeignAsset(1); +pub const CURRENCY_FOREIGN: CurrencyId = CurrencyId::ForeignAsset(2); +pub const DECIMALS_POOL: u32 = 12; +pub const DECIMALS_FOREIGN: u32 = 6; +pub const INVEST_AMOUNT_POOL_DENOMINATED: u128 = 1_000_000_000_000; +pub const INVEST_AMOUNT_FOREIGN_DENOMINATED: u128 = INVEST_AMOUNT_POOL_DENOMINATED / 1_000_000; + +impl ForeignInvestmentBenchmarkHelper for Pallet +where + T::Balance: From, + T::CurrencyId: From, + T::PoolInspect: PoolBenchmarkHelper + + InvestmentIdBenchmarkHelper, + T::TokenSwaps: OrderBookBenchmarkHelper< + AccountId = T::AccountId, + Balance = T::Balance, + CurrencyId = T::CurrencyId, + OrderIdNonce = T::TokenSwapOrderId, + >, + T::Investment: OrderManager< + Error = DispatchError, + InvestmentId = T::InvestmentId, + Orders = TotalOrder, + Fulfillment = FulfillmentWithPrice, + >, + T::BalanceRatio: From, +{ + type AccountId = T::AccountId; + type Balance = T::Balance; + type CurrencyId = T::CurrencyId; + type InvestmentId = T::InvestmentId; + + fn bench_prepare_foreign_investments_setup( + ) -> BenchForeignInvestmentSetupInfo { + let pool_id = Default::default(); + let pool_admin: T::AccountId = frame_benchmarking::account("pool_admin", 0, 0); + ::bench_create_pool(pool_id, &pool_admin); + + // Add bidirectional trading pair and fund both accounts + let (investor, funded_trader) = + ::bench_setup_trading_pair( + CURRENCY_POOL.into(), + CURRENCY_FOREIGN.into(), + INVEST_AMOUNT_POOL_DENOMINATED.into(), + INVEST_AMOUNT_FOREIGN_DENOMINATED.into(), + DECIMALS_POOL.into(), + DECIMALS_FOREIGN.into(), + ); + ::bench_setup_trading_pair( + CURRENCY_FOREIGN.into(), + CURRENCY_POOL.into(), + INVEST_AMOUNT_FOREIGN_DENOMINATED.into(), + INVEST_AMOUNT_POOL_DENOMINATED.into(), + DECIMALS_FOREIGN.into(), + DECIMALS_POOL.into(), + ); + + // Grant investor permissions + ::bench_investor_setup( + pool_id, + investor.clone(), + T::Balance::zero(), + ); + let investment_id = + ::bench_default_investment_id(pool_id); + + BenchForeignInvestmentSetupInfo { + investor, + investment_id, + pool_currency: CURRENCY_POOL.into(), + foreign_currency: CURRENCY_FOREIGN.into(), + funded_trader, + } + } + + fn bench_prep_foreign_investments_worst_case( + investor: Self::AccountId, + investment_id: Self::InvestmentId, + pool_currency: Self::CurrencyId, + foreign_currency: Self::CurrencyId, + ) { + log::debug!( + "Preparing worst case foreign investment benchmark setup with pool currency {:?} and foreign currency: {:?}", + pool_currency, + foreign_currency + ); + + // Create `InvestState::ActiveSwapIntoPoolCurrency` and prepare redemption for + // collection by redeeming + assert_ok!(Pallet::::increase_foreign_investment( + &investor, + investment_id, + INVEST_AMOUNT_FOREIGN_DENOMINATED.into(), + foreign_currency, + pool_currency, + )); + assert_eq!( + crate::InvestmentPaymentCurrency::::get(&investor, investment_id).unwrap(), + foreign_currency + ); + + log::debug!("Increasing foreign redemption"); + assert_ok!(Pallet::::increase_foreign_redemption( + &investor, + investment_id, + INVEST_AMOUNT_FOREIGN_DENOMINATED.into(), + foreign_currency, + )); + assert_eq!( + crate::RedemptionPayoutCurrency::::get(&investor, investment_id).unwrap(), + foreign_currency + ); + + // Process redemption such that collecting will trigger worst case + let fulfillment: FulfillmentWithPrice = FulfillmentWithPrice { + of_amount: Perquintill::from_percent(50), + price: Ratio::checked_from_rational(1, 4).unwrap().into(), + }; + assert_ok!(::process_redeem_orders( + investment_id + )); + assert_ok!(::redeem_fulfillment( + investment_id, + fulfillment + )); + log::debug!("Worst case benchmark foreign investment setup done!"); + } +} diff --git a/pallets/foreign-investments/src/impls/mod.rs b/pallets/foreign-investments/src/impls/mod.rs index 8ff180b510..abd1794124 100644 --- a/pallets/foreign-investments/src/impls/mod.rs +++ b/pallets/foreign-investments/src/impls/mod.rs @@ -33,6 +33,8 @@ use crate::{ RedemptionPayoutCurrency, RedemptionState, SwapOf, TokenSwapOrderIds, }; +#[cfg(feature = "runtime-benchmarks")] +mod benchmark_utils; mod invest; mod redeem; @@ -795,7 +797,7 @@ impl Pallet { swap_order_id, swap.amount, // The max accepted sell rate is independent of the asset type for now - T::DefaultTokenSellRate::get(), + T::DefaultTokenSellRatio::get(), // The minimum fulfillment must be everything swap.amount, )?; @@ -824,7 +826,7 @@ impl Pallet { swap.currency_out, swap.amount, // The max accepted sell rate is independent of the asset type for now - T::DefaultTokenSellRate::get(), + T::DefaultTokenSellRatio::get(), // The minimum fulfillment must be everything swap.amount, )?; diff --git a/pallets/foreign-investments/src/lib.rs b/pallets/foreign-investments/src/lib.rs index 34907f4790..ccba92f841 100644 --- a/pallets/foreign-investments/src/lib.rs +++ b/pallets/foreign-investments/src/lib.rs @@ -152,7 +152,7 @@ pub mod pallet { /// Type for price ratio for cost of incoming currency relative to /// outgoing - type Rate: Parameter + type BalanceRatio: Parameter + Member + sp_runtime::FixedPointNumber + sp_runtime::traits::EnsureMul @@ -171,7 +171,7 @@ pub mod pallet { /// more sophisticated swap price discovery. For now, this should be set /// to one. #[pallet::constant] - type DefaultTokenSellRate: Get; + type DefaultTokenSellRatio: Get; /// The token swap order identifying type type TokenSwapOrderId: Parameter @@ -190,7 +190,7 @@ pub mod pallet { Balance = Self::Balance, OrderId = Self::TokenSwapOrderId, OrderDetails = Swap, - SellRatio = Self::Rate, + SellRatio = Self::BalanceRatio, >; /// The hook type which acts upon a finalized investment decrement. diff --git a/pallets/liquidity-pools-gateway/src/lib.rs b/pallets/liquidity-pools-gateway/src/lib.rs index 2c1a99a418..1d877ca911 100644 --- a/pallets/liquidity-pools-gateway/src/lib.rs +++ b/pallets/liquidity-pools-gateway/src/lib.rs @@ -322,7 +322,7 @@ pub mod pallet { } /// Process an incoming message. - #[pallet::weight(0)] + #[pallet::weight(T::WeightInfo::process_msg())] #[pallet::call_index(5)] pub fn process_msg( origin: OriginFor, diff --git a/pallets/liquidity-pools/src/benchmarking.rs b/pallets/liquidity-pools/src/benchmarking.rs new file mode 100644 index 0000000000..4d76797de9 --- /dev/null +++ b/pallets/liquidity-pools/src/benchmarking.rs @@ -0,0 +1,68 @@ +// Copyright 2021 Centrifuge Foundation (centrifuge.io). +// This file is part of Centrifuge Chain project. + +// Centrifuge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version (see http://www.gnu.org/licenses). + +// Centrifuge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +use cfg_traits::{ + benchmarking::{BenchForeignInvestmentSetupInfo, ForeignInvestmentBenchmarkHelper}, + investments::{ForeignInvestment, TrancheCurrency}, +}; +use frame_benchmarking::v2::*; + +use super::*; +use crate::Pallet; + +#[benchmarks( + where + T::ForeignInvestment: ForeignInvestmentBenchmarkHelper, + T::Balance: From, + T::AccountId: From<[u8; 32]> + Into<[u8; 32]>, +)] +mod benchmarks { + use super::*; + + #[benchmark] + fn inbound_collect_redeem() { + let BenchForeignInvestmentSetupInfo { investor, investment_id, pool_currency, foreign_currency, .. } = ::bench_prepare_foreign_investments_setup(); + + // Fund investor with foreign currency and tranche tokens + T::Tokens::mint_into( + investment_id.clone().into(), + &investor, + (u128::max_value() / 10).into(), + )?; + T::Tokens::mint_into(foreign_currency, &investor, (u128::max_value() / 10).into())?; + + // Increase investment and redemption + ::bench_prep_foreign_investments_worst_case(investor.clone(), investment_id.clone(), pool_currency, foreign_currency); + + let investor_pointer = investor.clone(); + let redeeming_amount = + T::ForeignInvestment::redemption(&investor_pointer, investment_id.clone())?; + let pool_id = investment_id.of_pool(); + let tranche_id = investment_id.of_tranche(); + let foreign_currency_index = Pallet::::try_get_general_index(foreign_currency)?.into(); + + #[block] + { + Pallet::::handle_collect_redemption( + pool_id, + tranche_id, + investor, + foreign_currency_index, + )?; + } + + assert!( + T::ForeignInvestment::redemption(&investor_pointer, investment_id)? < redeeming_amount + ); + } +} diff --git a/pallets/liquidity-pools/src/defensive_weights.rs b/pallets/liquidity-pools/src/defensive_weights.rs new file mode 100644 index 0000000000..0f8f0acdbc --- /dev/null +++ b/pallets/liquidity-pools/src/defensive_weights.rs @@ -0,0 +1,95 @@ +// Copyright 2023 Centrifuge Foundation (centrifuge.io). +// This file is part of Centrifuge chain project. + +// Centrifuge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version (see http://www.gnu.org/licenses). + +// Centrifuge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +use frame_support::weights::{constants::RocksDbWeight, Weight}; + +pub trait WeightInfo { + fn add_pool() -> Weight; + fn add_tranche() -> Weight; + fn update_token_price() -> Weight; + fn update_member() -> Weight; + fn transfer() -> Weight; + fn set_domain_router() -> Weight; +} + +// NOTE: We use temporary weights here. `execute_epoch` is by far our heaviest +// extrinsic. N denotes the number of tranches. 4 is quite heavy and +// should be enough. +const N: u64 = 4; + +impl WeightInfo for () { + fn set_domain_router() -> Weight { + // TODO: BENCHMARK AND USE REAL WEIGHTS + Weight::from_parts(78_019_565, 19974) + .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) + .saturating_add(RocksDbWeight::get().writes(8)) + .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) + .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) + } + + fn add_pool() -> Weight { + // TODO: BENCHMARK AND USE REAL WEIGHTS + Weight::from_parts(78_019_565, 19974) + .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) + .saturating_add(RocksDbWeight::get().writes(8)) + .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) + .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) + } + + fn add_tranche() -> Weight { + // TODO: BENCHMARK AND USE REAL WEIGHTS + Weight::from_parts(78_019_565, 19974) + .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) + .saturating_add(RocksDbWeight::get().writes(8)) + .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) + .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) + } + + fn update_token_price() -> Weight { + // TODO: BENCHMARK AND USE REAL WEIGHTS + Weight::from_parts(78_019_565, 19974) + .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) + .saturating_add(RocksDbWeight::get().writes(8)) + .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) + .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) + } + + fn update_member() -> Weight { + // TODO: BENCHMARK AND USE REAL WEIGHTS + Weight::from_parts(78_019_565, 19974) + .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) + .saturating_add(RocksDbWeight::get().writes(8)) + .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) + .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) + } + + fn transfer() -> Weight { + // TODO: BENCHMARK AND USE REAL WEIGHTS + Weight::from_parts(78_019_565, 19974) + .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) + .saturating_add(RocksDbWeight::get().writes(8)) + .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) + .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) + } +} diff --git a/pallets/liquidity-pools/src/lib.rs b/pallets/liquidity-pools/src/lib.rs index 5c07b3f0ef..3bc48ca3c6 100644 --- a/pallets/liquidity-pools/src/lib.rs +++ b/pallets/liquidity-pools/src/lib.rs @@ -69,7 +69,9 @@ use xcm::{ VersionedMultiLocation, }; -pub mod weights; +// NOTE: Should be replaced with generated weights in the future. For now, let's +// be defensive. +pub mod defensive_weights; mod message; pub use message::*; @@ -80,6 +82,8 @@ pub use routers::*; mod contract; pub use contract::*; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; pub mod hooks; mod inbound; @@ -127,7 +131,7 @@ pub mod pallet { use xcm::latest::MultiLocation; use super::*; - use crate::weights::WeightInfo; + use crate::defensive_weights::WeightInfo; #[pallet::pallet] #[pallet::generate_store(pub (super) trait Store)] diff --git a/pallets/liquidity-pools/src/weights.rs b/pallets/liquidity-pools/src/weights.rs index 2d5b4c30ae..83940ff968 100644 --- a/pallets/liquidity-pools/src/weights.rs +++ b/pallets/liquidity-pools/src/weights.rs @@ -1,4 +1,5 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). + +// Copyright 2023 Centrifuge Foundation (centrifuge.io). // This file is part of Centrifuge chain project. // Centrifuge is free software: you can redistribute it and/or modify @@ -10,86 +11,81 @@ // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -use frame_support::weights::{constants::RocksDbWeight, Weight}; - -pub trait WeightInfo { - fn add_pool() -> Weight; - fn add_tranche() -> Weight; - fn update_token_price() -> Weight; - fn update_member() -> Weight; - fn transfer() -> Weight; - fn set_domain_router() -> Weight; -} - -// NOTE: We use temporary weights here. `execute_epoch` is by far our heaviest -// extrinsic. N denotes the number of tranches. 4 is quite heavy and -// should be enough. -const N: u64 = 4; - -impl WeightInfo for () { - fn set_domain_router() -> Weight { - // TODO: BENCHMARK AND USE REAL WEIGHTS - Weight::from_parts(78_019_565, 19974) - .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) - .saturating_add(RocksDbWeight::get().writes(8)) - .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) - .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) - } - fn add_pool() -> Weight { - // TODO: BENCHMARK AND USE REAL WEIGHTS - Weight::from_parts(78_019_565, 19974) - .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) - .saturating_add(RocksDbWeight::get().writes(8)) - .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) - .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) - } +//! Autogenerated weights for `pallet_liquidity_pools` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-09-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `Apple Macbook Pro M1 Max`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("development-local"), DB CACHE: 1024 - fn add_tranche() -> Weight { - // TODO: BENCHMARK AND USE REAL WEIGHTS - Weight::from_parts(78_019_565, 19974) - .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) - .saturating_add(RocksDbWeight::get().writes(8)) - .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) - .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) - } +// Executed Command: +// target/release/centrifuge-chain +// benchmark +// pallet +// --chain=development-local +// --steps=50 +// --repeat=20 +// --pallet=pallet_liquidity_pools +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 - fn update_token_price() -> Weight { - // TODO: BENCHMARK AND USE REAL WEIGHTS - Weight::from_parts(78_019_565, 19974) - .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) - .saturating_add(RocksDbWeight::get().writes(8)) - .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) - .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) - } +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] - fn update_member() -> Weight { - // TODO: BENCHMARK AND USE REAL WEIGHTS - Weight::from_parts(78_019_565, 19974) - .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) - .saturating_add(RocksDbWeight::get().writes(8)) - .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) - .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) - } +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; - fn transfer() -> Weight { - // TODO: BENCHMARK AND USE REAL WEIGHTS - Weight::from_parts(78_019_565, 19974) - .saturating_add(Weight::from_ref_time(38_884_782).saturating_mul(N)) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(N))) - .saturating_add(RocksDbWeight::get().writes(8)) - .saturating_add(RocksDbWeight::get().writes((6_u64).saturating_mul(N))) - .saturating_add(Weight::from_proof_size(17774).saturating_mul(N)) +/// Weight functions for `pallet_liquidity_pools`. +pub struct WeightInfo(PhantomData); +impl pallet_liquidity_pools::WeightInfo for WeightInfo { + /// Storage: PoolSystem Pool (r:1 w:0) + /// Proof: PoolSystem Pool (max_values: None, max_size: Some(813), added: 3288, mode: MaxEncodedLen) + /// Storage: OrmlAssetRegistry Metadata (r:2 w:0) + /// Proof Skipped: OrmlAssetRegistry Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: OrderBook TradingPair (r:1 w:0) + /// Proof: OrderBook TradingPair (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: ForeignInvestments RedemptionPayoutCurrency (r:1 w:0) + /// Proof: ForeignInvestments RedemptionPayoutCurrency (max_values: None, max_size: Some(113), added: 2588, mode: MaxEncodedLen) + /// Storage: Investments RedeemOrders (r:1 w:1) + /// Proof: Investments RedeemOrders (max_values: None, max_size: Some(112), added: 2587, mode: MaxEncodedLen) + /// Storage: Investments RedeemOrderId (r:1 w:0) + /// Proof: Investments RedeemOrderId (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Investments ClearedRedeemOrders (r:1 w:0) + /// Proof: Investments ClearedRedeemOrders (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: OrmlTokens Accounts (r:3 w:3) + /// Proof: OrmlTokens Accounts (max_values: None, max_size: Some(129), added: 2604, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ForeignInvestments RedemptionState (r:1 w:1) + /// Proof: ForeignInvestments RedemptionState (max_values: None, max_size: Some(187), added: 2662, mode: MaxEncodedLen) + /// Storage: ForeignInvestments CollectedRedemption (r:1 w:1) + /// Proof: ForeignInvestments CollectedRedemption (max_values: None, max_size: Some(120), added: 2595, mode: MaxEncodedLen) + /// Storage: ForeignInvestments TokenSwapOrderIds (r:1 w:1) + /// Proof: ForeignInvestments TokenSwapOrderIds (max_values: None, max_size: Some(96), added: 2571, mode: MaxEncodedLen) + /// Storage: ForeignInvestments InvestmentState (r:1 w:1) + /// Proof: ForeignInvestments InvestmentState (max_values: None, max_size: Some(187), added: 2662, mode: MaxEncodedLen) + /// Storage: OrderBook Orders (r:1 w:2) + /// Proof: OrderBook Orders (max_values: None, max_size: Some(186), added: 2661, mode: MaxEncodedLen) + /// Storage: OrderBook AssetPairOrders (r:2 w:2) + /// Proof: OrderBook AssetPairOrders (max_values: None, max_size: Some(8068), added: 10543, mode: MaxEncodedLen) + /// Storage: OrderBook OrderIdNonceStore (r:1 w:1) + /// Proof: OrderBook OrderIdNonceStore (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: ForeignInvestments ForeignInvestmentInfo (r:0 w:2) + /// Proof: ForeignInvestments ForeignInvestmentInfo (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: OrderBook UserOrders (r:0 w:2) + /// Proof: OrderBook UserOrders (max_values: None, max_size: Some(226), added: 2701, mode: MaxEncodedLen) + fn inbound_collect_redeem() -> Weight { + // Proof Size summary in bytes: + // Measured: `5737` + // Estimated: `71940` + // Minimum execution time: 231_000 nanoseconds. + Weight::from_parts(236_000_000, 71940) + .saturating_add(T::DbWeight::get().reads(20)) + .saturating_add(T::DbWeight::get().writes(17)) } } diff --git a/pallets/pool-system/src/impls.rs b/pallets/pool-system/src/impls.rs index 25587d8fa0..ac03e93089 100644 --- a/pallets/pool-system/src/impls.rs +++ b/pallets/pool-system/src/impls.rs @@ -472,6 +472,7 @@ mod benchmarks_utils { fn bench_create_pool(pool_id: T::PoolId, admin: &T::AccountId) { const FUNDS: u32 = u32::max_value(); + const POOL_ACCOUNT_BALANCE: u128 = u64::max_value() as u128; if T::AssetRegistry::metadata(&POOL_CURRENCY).is_none() { frame_support::assert_ok!(T::AssetRegistry::register_asset( @@ -521,6 +522,14 @@ mod benchmarks_utils { FUNDS.into(), )); + // Fund pool account + let pool_account = PoolLocator { pool_id }.into_account_truncating(); + frame_support::assert_ok!(T::Tokens::mint_into( + POOL_CURRENCY, + &pool_account, + POOL_ACCOUNT_BALANCE.into() + )); + // Investment in pool let investor = account::("investor_benchmark_pool", 0, 0); Self::bench_investor_setup(pool_id, investor.clone(), FUNDS.into()); diff --git a/runtime/altair/src/lib.rs b/runtime/altair/src/lib.rs index 7734f2ed3c..49f6c8cbfc 100644 --- a/runtime/altair/src/lib.rs +++ b/runtime/altair/src/lib.rs @@ -1389,11 +1389,12 @@ impl pallet_xcm_transactor::Config for Runtime { } parameter_types! { - pub DefaultTokenSellRate: Ratio = Ratio::one(); + pub DefaultTokenSellRatio: Ratio = Ratio::one(); } impl pallet_foreign_investments::Config for Runtime { type Balance = Balance; + type BalanceRatio = Ratio; type CollectedForeignInvestmentHook = pallet_liquidity_pools::hooks::CollectedForeignInvestmentHook; type CollectedForeignRedemptionHook = @@ -1403,12 +1404,11 @@ impl pallet_foreign_investments::Config for Runtime { type CurrencyId = CurrencyId; type DecreasedForeignInvestOrderHook = pallet_liquidity_pools::hooks::DecreasedForeignInvestOrderHook; - type DefaultTokenSellRate = DefaultTokenSellRate; + type DefaultTokenSellRatio = DefaultTokenSellRatio; type Investment = Investments; type InvestmentId = TrancheCurrency; type PoolId = PoolId; type PoolInspect = PoolSystem; - type Rate = Ratio; type RuntimeEvent = RuntimeEvent; type TokenSwapOrderId = u64; type TokenSwaps = OrderBook; diff --git a/runtime/centrifuge/src/lib.rs b/runtime/centrifuge/src/lib.rs index 287b203baf..32b95ace8c 100644 --- a/runtime/centrifuge/src/lib.rs +++ b/runtime/centrifuge/src/lib.rs @@ -429,11 +429,12 @@ impl orml_asset_registry::Config for Runtime { } parameter_types! { - pub DefaultTokenSellRate: Ratio = Ratio::one(); + pub DefaultTokenSellRatio: Ratio = Ratio::one(); } impl pallet_foreign_investments::Config for Runtime { type Balance = Balance; + type BalanceRatio = Ratio; type CollectedForeignInvestmentHook = pallet_liquidity_pools::hooks::CollectedForeignInvestmentHook; type CollectedForeignRedemptionHook = @@ -443,12 +444,11 @@ impl pallet_foreign_investments::Config for Runtime { type CurrencyId = CurrencyId; type DecreasedForeignInvestOrderHook = pallet_liquidity_pools::hooks::DecreasedForeignInvestOrderHook; - type DefaultTokenSellRate = DefaultTokenSellRate; + type DefaultTokenSellRatio = DefaultTokenSellRatio; type Investment = Investments; type InvestmentId = TrancheCurrency; type PoolId = PoolId; type PoolInspect = PoolSystem; - type Rate = Ratio; type RuntimeEvent = RuntimeEvent; type TokenSwapOrderId = u64; type TokenSwaps = OrderBook; diff --git a/runtime/development/src/lib.rs b/runtime/development/src/lib.rs index a4054cf4e7..8ca13335d9 100644 --- a/runtime/development/src/lib.rs +++ b/runtime/development/src/lib.rs @@ -1545,11 +1545,12 @@ impl orml_asset_registry::Config for Runtime { } parameter_types! { - pub DefaultTokenSellRate: Ratio = Ratio::one(); + pub DefaultTokenSellRatio: Ratio = Ratio::one(); } impl pallet_foreign_investments::Config for Runtime { type Balance = Balance; + type BalanceRatio = Ratio; type CollectedForeignInvestmentHook = pallet_liquidity_pools::hooks::CollectedForeignInvestmentHook; type CollectedForeignRedemptionHook = @@ -1559,12 +1560,11 @@ impl pallet_foreign_investments::Config for Runtime { type CurrencyId = CurrencyId; type DecreasedForeignInvestOrderHook = pallet_liquidity_pools::hooks::DecreasedForeignInvestOrderHook; - type DefaultTokenSellRate = DefaultTokenSellRate; + type DefaultTokenSellRatio = DefaultTokenSellRatio; type Investment = Investments; type InvestmentId = TrancheCurrency; type PoolId = PoolId; type PoolInspect = PoolSystem; - type Rate = Ratio; type RuntimeEvent = RuntimeEvent; type TokenSwapOrderId = u64; type TokenSwaps = OrderBook; @@ -2560,6 +2560,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, cumulus_pallet_xcmp_queue, XcmpQueue); add_benchmark!(params, batches, pallet_transfer_allowlist, TransferAllowList); add_benchmark!(params, batches, pallet_order_book, OrderBook); + add_benchmark!(params, batches, pallet_liquidity_pools, LiquidityPools); add_benchmark!(params, batches, pallet_nft_sales, NftSales); add_benchmark!(params, batches, pallet_investments, Investments); @@ -2615,6 +2616,7 @@ impl_runtime_apis! { list_benchmark!(list, extra, cumulus_pallet_xcmp_queue, XcmpQueue); list_benchmark!(list, extra, pallet_transfer_allowlist, TransferAllowList); list_benchmark!(list, extra, pallet_order_book, OrderBook); + list_benchmark!(list, extra, pallet_liquidity_pools, LiquidityPools); list_benchmark!(list, extra, pallet_nft_sales, NftSales); list_benchmark!(list, extra, pallet_investments, Investments); diff --git a/runtime/integration-tests/src/liquidity_pools/pallet/development/tests/liquidity_pools/foreign_investments.rs b/runtime/integration-tests/src/liquidity_pools/pallet/development/tests/liquidity_pools/foreign_investments.rs index 493e5a8e33..5ff52acadd 100644 --- a/runtime/integration-tests/src/liquidity_pools/pallet/development/tests/liquidity_pools/foreign_investments.rs +++ b/runtime/integration-tests/src/liquidity_pools/pallet/development/tests/liquidity_pools/foreign_investments.rs @@ -30,7 +30,7 @@ use cfg_traits::{ }; use cfg_types::{ domain_address::{Domain, DomainAddress}, - fixed_point::{Quantity, Ratio}, + fixed_point::Ratio, investments::{CollectedAmount, InvestCollection, InvestmentAccount, RedeemCollection, Swap}, orders::FulfillmentWithPrice, permissions::{PermissionScope, PoolRole, Role, UNION}, @@ -359,7 +359,7 @@ mod same_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::one(), - price: Quantity::one(), + price: Ratio::one(), } )); assert_eq!(Tokens::total_issuance(investment_currency_id), amount); @@ -495,7 +495,7 @@ mod same_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(50), - price: Quantity::checked_from_rational(1, 4).unwrap(), + price: Ratio::checked_from_rational(1, 4).unwrap(), } )); @@ -572,7 +572,7 @@ mod same_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::one(), - price: Quantity::checked_from_rational(1, 2).unwrap(), + price: Ratio::checked_from_rational(1, 2).unwrap(), } )); // Order should have been cleared by fulfilling investment @@ -963,7 +963,7 @@ mod same_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::one(), - price: Quantity::one(), + price: Ratio::one(), } )); @@ -1099,7 +1099,7 @@ mod same_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(50), - price: Quantity::checked_from_rational(1, 4).unwrap(), + price: Ratio::checked_from_rational(1, 4).unwrap(), } )); @@ -1167,7 +1167,7 @@ mod same_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::one(), - price: Quantity::checked_from_rational(1, 2).unwrap(), + price: Ratio::checked_from_rational(1, 2).unwrap(), } )); // Order should have been cleared by fulfilling redemption @@ -1371,7 +1371,7 @@ mod same_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::one(), - price: Quantity::one(), + price: Ratio::one(), } )); @@ -1440,7 +1440,7 @@ mod same_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::one(), - price: Quantity::one(), + price: Ratio::one(), } )); @@ -1742,7 +1742,7 @@ mod same_currencies { mod mismatching_currencies { use cfg_traits::investments::ForeignInvestment; use cfg_types::investments::{ForeignInvestmentInfo, Swap}; - use development_runtime::{DefaultTokenSellRate, OrderBook}; + use development_runtime::{DefaultTokenSellRatio, OrderBook}; use pallet_foreign_investments::{types::TokenSwapReason, InvestmentState}; use super::*; @@ -1810,7 +1810,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::one(), - price: Quantity::checked_from_rational(1, 2).unwrap(), + price: Ratio::checked_from_rational(1, 2).unwrap(), } )); assert_ok!(Investments::collect_investments_for( @@ -2270,7 +2270,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(50), - price: Quantity::checked_from_rational(1, 4).unwrap(), + price: Ratio::checked_from_rational(1, 4).unwrap(), } )); assert_eq!( @@ -2342,7 +2342,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(100), - price: Quantity::checked_from_rational(1, 4).unwrap(), + price: Ratio::checked_from_rational(1, 4).unwrap(), } )); assert_ok!(Investments::collect_redemptions_for( @@ -2534,7 +2534,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(50), - price: Quantity::checked_from_rational(1, 4).unwrap(), + price: Ratio::checked_from_rational(1, 4).unwrap(), } )); assert_ok!(Investments::collect_redemptions_for( @@ -2589,7 +2589,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(100), - price: Quantity::checked_from_rational(1, 4).unwrap(), + price: Ratio::checked_from_rational(1, 4).unwrap(), } )); assert_ok!(Investments::collect_redemptions_for( @@ -2644,7 +2644,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(100), - price: Quantity::checked_from_rational(2, 1).unwrap(), + price: Ratio::checked_from_rational(2, 1).unwrap(), } )); assert_ok!(Investments::collect_redemptions_for( @@ -2796,7 +2796,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(50), - price: Quantity::checked_from_rational(1, 4).unwrap(), + price: Ratio::checked_from_rational(1, 4).unwrap(), } )); assert!(Investments::investment_requires_collect( @@ -2881,7 +2881,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(50), - price: Quantity::checked_from_rational(1, 2).unwrap(), + price: Ratio::checked_from_rational(1, 2).unwrap(), } )); assert_noop!( @@ -2916,7 +2916,7 @@ mod mismatching_currencies { default_investment_id(), FulfillmentWithPrice { of_amount: Perquintill::from_percent(100), - price: Quantity::checked_from_rational(1, 4).unwrap(), + price: Ratio::checked_from_rational(1, 4).unwrap(), } )); assert!(Investments::redemption_requires_collect(