Skip to content

Commit

Permalink
partial rebenchmark + update router benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
Roznovjak committed Dec 6, 2023
1 parent c6abed4 commit fa46c26
Show file tree
Hide file tree
Showing 7 changed files with 625 additions and 389 deletions.
293 changes: 209 additions & 84 deletions runtime/basilisk/src/benchmarking/route_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,135 +16,260 @@
// limitations under the License.
#![allow(clippy::result_large_err)]

use crate::{AccountId, AssetId, Balance, Currencies, Runtime};

use super::*;
use crate::{AccountId, AssetId, AssetRegistry, Balance, Currencies, Router, Runtime, RuntimeOrigin, System, LBP, XYK};

use frame_benchmarking::account;
use frame_benchmarking::BenchmarkError;
use frame_support::dispatch::DispatchResult;
use frame_support::sp_runtime::traits::One;
use frame_support::{assert_ok, ensure};
use frame_system::RawOrigin;
use hydradx_traits::router::AssetPair;
use hydradx_traits::router::{PoolType, RouterT, Trade};
use hydradx_traits::Registry;
use orml_benchmarking::runtime_benchmarks;
use orml_traits::{MultiCurrency, MultiCurrencyExtended};
use primitives::constants::currency::UNITS;
use sp_std::vec;

use orml_traits::MultiCurrency;
pub const INITIAL_BALANCE: Balance = 10_000_000 * UNITS;

type RouteExecutor<T> = pallet_route_executor::Pallet<T>;
fn funded_account(name: &'static str, index: u32, assets: &[AssetId]) -> AccountId {
let account: AccountId = account(name, index, 0);
for asset in assets {
assert_ok!(<Currencies as MultiCurrencyExtended<_>>::update_balance(
*asset,
&account,
INITIAL_BALANCE.try_into().unwrap(),
));
}
account
}

use codec::alloc::string::ToString;
use hydradx_traits::router::PoolType;
use pallet_route_executor::Trade;
use sp_std::vec;
fn setup_lbp(caller: AccountId, asset_in: AssetId, asset_out: AssetId) -> DispatchResult {
let asset_in_amount = 1_000_000_000;
let asset_out_amount = 2_000_000_000;
let initial_weight = 20_000_000;
let final_weight = 90_000_000;
let fee = (2, 1_000);
let fee_collector = caller.clone();
let repay_target = 0;

let pool_id = LBP::pair_account_from_assets(asset_in, asset_out);

LBP::create_pool(
RawOrigin::Root.into(),
caller.clone(),
asset_in,
asset_in_amount,
asset_out,
asset_out_amount,
initial_weight,
final_weight,
pallet_lbp::WeightCurveType::Linear,
fee,
fee_collector,
repay_target,
)?;
ensure!(
pallet_lbp::PoolData::<Runtime>::contains_key(&pool_id),
"Pool does not exist."
);

let start = 1u32;
let end = 11u32;

const SEED: u32 = 1;
pub const UNITS: Balance = 100_000_000_000;
const MAX_NUMBER_OF_TRADES: u32 = 5;
LBP::update_pool_data(
RawOrigin::Signed(caller).into(),
pool_id,
None,
Some(start),
Some(end),
None,
None,
None,
None,
None,
)?;

pub fn register_asset_with_name(name_as_bye_string: &[u8]) -> Result<AssetId, BenchmarkError> {
register_asset(name_as_bye_string.to_vec(), 0u128).map_err(|_| BenchmarkError::Stop("Failed to register asset"))
System::set_block_number(2u32);
Ok(())
}

pub fn create_account(name: &'static str) -> AccountId {
account(name, 0, SEED)
fn create_xyk_pool(asset_a: u32, asset_b: u32) {
let caller: AccountId = funded_account("caller", 0, &[asset_a, asset_b]);

let amount = 100000 * UNITS;
assert_ok!(Currencies::update_balance(
RuntimeOrigin::root(),
caller.clone(),
asset_a,
amount as i128,
));

assert_ok!(Currencies::update_balance(
RuntimeOrigin::root(),
caller.clone(),
asset_b,
amount as i128,
));

assert_ok!(XYK::create_pool(
RuntimeOrigin::signed(caller),
asset_a,
amount,
asset_b,
amount,
));
}

pub fn generate_trades(number_of_trades: u32) -> Result<(AssetId, AssetId, Vec<Trade<AssetId>>), BenchmarkError> {
let pool_maker: AccountId = create_account("pool_maker");
runtime_benchmarks! {
{Runtime, pallet_route_executor}

let balance = 2000 * UNITS;
let main_asset_in = register_asset_with_name(b"TST")?;
let main_asset_out = register_asset_with_name(b"TST2")?;
update_balance(main_asset_in, &pool_maker, balance);
update_balance(main_asset_out, &pool_maker, balance);
// Calculates the weight of LBP trade. Used in the calculation to determine the weight of the overhead.
calculate_and_execute_sell_in_lbp {
let c in 0..1; // if c == 1, calculate_sell_trade_amounts is executed
let s in 0..1; // if e == 1, sell is executed

let number_of_intermediate_assets = number_of_trades - 1;
let asset_in = 1u32;
let asset_out = 2u32;
let caller: AccountId = funded_account("caller", 7, &[asset_in, asset_out]);
let seller: AccountId = funded_account("seller", 8, &[asset_in, asset_out]);

//Create intermediate assets
let mut intermediate_assets: Vec<AssetId> = vec![];
for n in 0..number_of_intermediate_assets {
let intermediate_asset = register_asset_with_name(n.to_string().as_bytes())?;
update_balance(intermediate_asset, &pool_maker, balance);
intermediate_assets.push(intermediate_asset);
}
setup_lbp(caller, asset_in, asset_out)?;

//Create pools and generate trades for intermediate assets
let mut trades: Vec<Trade<AssetId>> = vec![];
let mut asset_in = main_asset_in;
for _ in 0..number_of_intermediate_assets {
let asset_out = intermediate_assets.pop().unwrap();
create_pool(pool_maker.clone(), asset_in, 1_000 * UNITS, asset_out, 500 * UNITS);
let trade = Trade {
pool: PoolType::XYK,
let trades = vec![Trade {
pool: PoolType::LBP,
asset_in,
asset_out,
};
trades.push(trade);
asset_in = asset_out;
}
asset_out
}];

//Create pool and trade for the last trade
create_pool(pool_maker, asset_in, 1_000 * UNITS, main_asset_out, 500 * UNITS);
let last_trade = Trade {
pool: PoolType::XYK,
asset_in,
asset_out: main_asset_out,
};
trades.push(last_trade);
let amount_to_sell: Balance = 100_000_000;

Ok((main_asset_in, main_asset_out, trades))
}
}: {
if c != 0 {
Router::calculate_sell_trade_amounts(trades.as_slice(), amount_to_sell)?;
}
if s != 0 {
Router::sell(RawOrigin::Signed(seller.clone()).into(), asset_in, asset_out, amount_to_sell, 0u128, trades.clone())?;
}
}
verify {
if s != 0 {
assert_eq!(<Currencies as MultiCurrency<_>>::free_balance(
asset_in,
&seller,
), INITIAL_BALANCE - amount_to_sell);
}
}

runtime_benchmarks! {
{ Runtime, pallet_route_executor}
// Calculates the weight of LBP trade. Used in the calculation to determine the weight of the overhead.
calculate_and_execute_buy_in_lbp {
let c in 1..2; // number of times `calculate_buy_trade_amounts` is executed
let b in 0..1; // if e == 1, buy is executed

let asset_in = 1u32;
let asset_out = 2u32;
let caller: AccountId = funded_account("caller", 0, &[asset_in, asset_out]);
let buyer: AccountId = funded_account("buyer", 1, &[asset_in, asset_out]);

sell {
let n in 1..MAX_NUMBER_OF_TRADES;
let (asset_in, asset_out, trades) = generate_trades(n).unwrap();
setup_lbp(caller, asset_in, asset_out)?;

let caller: AccountId = create_account("caller");
let trades = vec![Trade {
pool: PoolType::LBP,
asset_in,
asset_out
}];

let amount_to_sell = 10 * UNITS;
let caller_asset_in_balance = 2000 * UNITS;
let caller_asset_out_balance = 2000 * UNITS;
let amount_to_buy = 100_000_000;

update_balance(asset_in, &caller, caller_asset_in_balance);
}: {
RouteExecutor::<Runtime>::sell(RawOrigin::Signed(caller.clone()).into(), asset_in, asset_out, amount_to_sell, 0u128, trades)?
for _ in 1..c {
Router::calculate_buy_trade_amounts(trades.as_slice(), amount_to_buy)?;
}
if b != 0 {
Router::buy(RawOrigin::Signed(buyer.clone()).into(), asset_in, asset_out, amount_to_buy, u128::MAX, trades)?
}
}
verify{
assert_eq!(<Currencies as MultiCurrency<_>>::total_balance(asset_in, &caller), caller_asset_in_balance - amount_to_sell);
assert!(<Currencies as MultiCurrency<_>>::total_balance(asset_out, &caller) > 0);
verify {
if b != 0 {
assert!(<Currencies as MultiCurrency<_>>::free_balance(
asset_in,
&buyer,
) < INITIAL_BALANCE);
}
}

buy {
let n in 1..MAX_NUMBER_OF_TRADES;
let (asset_in, asset_out, trades) = generate_trades(n).unwrap();
// Calculates the weight of xyk set route. Used in the calculation to determine the weight of the overhead.
set_route_for_xyk {
let asset_1 = 1u32;
let asset_2 = AssetRegistry::create_asset(&b"FCA".to_vec(), Balance::one())?;
let asset_3 = AssetRegistry::create_asset(&b"FCB".to_vec(), Balance::one())?;

let caller: AccountId = create_account("caller");
let caller: AccountId = funded_account("caller", 0, &[asset_1, asset_2,asset_3]);
let buyer: AccountId = funded_account("buyer", 1, &[asset_1, asset_2,asset_3]);
create_xyk_pool(asset_1, asset_2);
create_xyk_pool(asset_1, asset_3);
create_xyk_pool(asset_2, asset_3);

let amount_to_buy = UNITS;
let caller_asset_in_balance = 2000 * UNITS;
let route = vec![Trade {
pool: PoolType::XYK,
asset_in: asset_1,
asset_out: asset_2
},Trade {
pool: PoolType::XYK,
asset_in: asset_2,
asset_out: asset_3
}];

Router::set_route(
RawOrigin::Signed(caller.clone()).into(),
AssetPair::new(asset_1, asset_3),
route,
)?;

let better_route = vec![Trade {
pool: PoolType::XYK,
asset_in: asset_1,
asset_out: asset_3
}];

update_balance(asset_in, &caller, caller_asset_in_balance);
}: {
RouteExecutor::<Runtime>::buy(RawOrigin::Signed(caller.clone()).into(), asset_in, asset_out, amount_to_buy, 10000u128 * UNITS, trades)?
Router::set_route(
RawOrigin::Signed(caller.clone()).into(),
AssetPair::new(asset_1, asset_3),
better_route.clone(),
)?;
}
verify{
assert!(<Currencies as MultiCurrency<_>>::total_balance(asset_in, &caller) < caller_asset_in_balance);
assert_eq!(<Currencies as MultiCurrency<_>>::total_balance(asset_out, &caller), amount_to_buy);
verify {
let stored_route = Router::route(AssetPair::new(asset_1, asset_3)).unwrap();
assert_eq!(stored_route, better_route);
}

}

#[cfg(test)]
mod tests {
use super::*;
use crate::NativeExistentialDeposit;
use orml_benchmarking::impl_benchmark_test_suite;
use sp_runtime::BuildStorage;

fn new_test_ext() -> sp_io::TestExternalities {
frame_system::GenesisConfig::<crate::Runtime>::default()
let mut t = frame_system::GenesisConfig::<Runtime>::default()
.build_storage()
.unwrap()
.into()
.unwrap();

pallet_asset_registry::GenesisConfig::<Runtime> {
registered_assets: vec![
(b"LRNA".to_vec(), 1_000u128, Some(1)),
(b"DAI".to_vec(), 1_000u128, Some(2)),
],
native_asset_name: b"HDX".to_vec(),
native_existential_deposit: NativeExistentialDeposit::get(),
}
.assimilate_storage(&mut t)
.unwrap();

sp_io::TestExternalities::new(t)
}

impl_benchmark_test_suite!(new_test_ext(),);
Expand Down
Loading

0 comments on commit fa46c26

Please sign in to comment.