Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add integration test helper #991

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "runtime-integration-tests"
version = "1.30.0"
version = "1.31.0"
description = "Integration tests"
authors = ["GalacticCouncil"]
edition = "2021"
Expand Down
53 changes: 53 additions & 0 deletions integration-tests/src/driver/example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use crate::driver::HydrationTestDriver;
use crate::polkadot_test_net::*;
use frame_support::assert_ok;
use hydradx_runtime::*;

#[test]
fn driver_test_example() {
HydrationTestDriver::default()
.setup_hydration()
.execute(|| {
assert_ok!(Tokens::set_balance(
RawOrigin::Root.into(),
CHARLIE.into(),
DOT,
20_000_000_000_000_000_000_000_000,
0,
));

assert_ok!(Omnipool::sell(
hydradx_runtime::RuntimeOrigin::signed(CHARLIE.into()),
DOT,
HDX,
1_000_000_000_000,
0u128,
));
})
.new_block()
.execute_with_driver(|driver| {
// This is useful, so we can have access to some info stored in the driver itself
// such as list of omnipool assets or stablepools
let stable_pool_id = driver.stablepools[0].0;
let stable_asset_a = driver.stablepools[0].1[0].0;
let stable_asset_b = driver.stablepools[0].1[1].0;
let stable_asset_a_decimals = driver.stablepools[0].1[0].1 as u32;

assert_ok!(Tokens::set_balance(
RawOrigin::Root.into(),
CHARLIE.into(),
stable_asset_a,
10 * 10u128.pow(stable_asset_a_decimals),
0,
));

assert_ok!(Stableswap::sell(
hydradx_runtime::RuntimeOrigin::signed(CHARLIE.into()),
stable_pool_id,
stable_asset_a,
stable_asset_b,
1u128 * 10u128.pow(stable_asset_a_decimals),
0u128,
));
});
}
327 changes: 327 additions & 0 deletions integration-tests/src/driver/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
mod example;

use crate::polkadot_test_net::*;
use frame_support::assert_ok;
use frame_support::traits::fungible::Mutate;
use frame_support::BoundedVec;
use hydradx_runtime::*;
use hydradx_traits::stableswap::AssetAmount;
use hydradx_traits::AggregatedPriceOracle;
use pallet_asset_registry::AssetType;
use pallet_stableswap::MAX_ASSETS_IN_POOL;
use primitives::constants::chain::{OMNIPOOL_SOURCE, STABLESWAP_SOURCE};
use primitives::{AccountId, AssetId};
use sp_runtime::{FixedU128, Permill};
use xcm_emulator::TestExt;

pub(crate) struct HydrationTestDriver {
omnipool_assets: Vec<AssetId>,
stablepools: Vec<(AssetId, Vec<(AssetId, u8)>)>,
}

impl HydrationTestDriver {
pub(crate) fn add_omnipool_assets(self, assets: Vec<AssetId>) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason that there are two implementation block for HydrationTestDriver?

let mut driver = self;
driver.omnipool_assets.extend(assets);
driver
}

pub(crate) fn add_stablepools(self, pools: Vec<(AssetId, Vec<(AssetId, u8)>)>) -> Self {
let mut driver = self;
driver.stablepools.extend(pools);
driver
}
}

impl HydrationTestDriver {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just call it IntegrationTestBase or similar

pub(crate) fn default() -> Self {
TestNet::reset();
HydrationTestDriver {
omnipool_assets: vec![],
stablepools: vec![],
}
}

pub(crate) fn execute(&self, f: impl FnOnce()) -> &Self {
Hydra::ext_wrapper(|| {
f();
});
self
}

pub(crate) fn execute_with_driver(&self, f: impl FnOnce(&Self)) -> &Self {
Hydra::ext_wrapper(|| {
f(self);
});
self
}

pub(crate) fn setup_hydration(self) -> Self {
self.setup_omnipool()
.setup_stableswap()
.add_stablepools_to_omnipool()
.populate_oracle()
}

pub(crate) fn setup_omnipool(self) -> Self {
self.execute(|| {
let acc = hydradx_runtime::Omnipool::protocol_account();
let native_price = FixedU128::from_rational(29903049701668757, 73927734532192294158);
let dot_price = FixedU128::from_rational(103158291366950047, 4566210555614178);

let dot_amount: primitives::Balance = 4566210555614178u128;
let native_amount: primitives::Balance = 73927734532192294158u128;
let weth_amount: primitives::Balance = 1074271742496220564487u128;
let weth_price = FixedU128::from_rational(67852651072676287, 1074271742496220564487);

assert_ok!(Tokens::set_balance(
RawOrigin::Root.into(),
acc.clone(),
DOT,
dot_amount,
0
));
Balances::set_balance(&acc, native_amount);
assert_ok!(Tokens::set_balance(
RawOrigin::Root.into(),
acc.clone(),
WETH,
weth_amount,
0
));

assert_ok!(hydradx_runtime::Omnipool::add_token(
hydradx_runtime::RuntimeOrigin::root(),
HDX,
native_price,
Permill::from_percent(60),
AccountId::from(ALICE),
));

assert_ok!(hydradx_runtime::Omnipool::add_token(
hydradx_runtime::RuntimeOrigin::root(),
DOT,
dot_price,
Permill::from_percent(60),
AccountId::from(ALICE),
));
assert_ok!(hydradx_runtime::Omnipool::add_token(
hydradx_runtime::RuntimeOrigin::root(),
WETH,
weth_price,
Permill::from_percent(60),
AccountId::from(ALICE),
));
});

self.add_omnipool_assets(vec![HDX, DOT, WETH])
}

pub(crate) fn setup_stableswap(self) -> Self {
let mut stable_pool_id = 0;
let mut stable_assets = vec![];
self.execute(|| {
let possible_decimals: Vec<u8> = vec![6u8, 10u8, 12u8, 12u8, 18u8];
let initial_liquidity = 1000u128;
let mut asset_ids: Vec<(AssetId, u8)> = Vec::new();
let mut initial: Vec<AssetAmount<AssetId>> = vec![];

let asset_offset = 555u32;

for idx in 0u32..MAX_ASSETS_IN_POOL {
let name: Vec<u8> = idx.to_ne_bytes().to_vec();
let decimals = possible_decimals[idx as usize % possible_decimals.len() as usize];
let result = AssetRegistry::register(
RawOrigin::Root.into(),
Some(asset_offset + idx),
Some(name.clone().try_into().unwrap()),
AssetType::Token,
Some(1000u128),
Some(name.try_into().unwrap()),
Some(decimals),
None,
None,
true,
);
assert_ok!(result);
let asset_id = asset_offset + idx;
asset_ids.push((asset_id, decimals));

let liquidity = initial_liquidity * 10u128.pow(decimals as u32);

assert_ok!(Currencies::update_balance(
hydradx_runtime::RuntimeOrigin::root(),
AccountId::from(BOB),
asset_id,
liquidity as i128,
));
initial.push(AssetAmount::new(asset_id, liquidity));
}

let pool_id = 222_222u32;
let result = AssetRegistry::register(
RawOrigin::Root.into(),
Some(pool_id),
Some(b"pool".to_vec().try_into().unwrap()),
AssetType::StableSwap,
Some(1u128),
None,
None,
None,
None,
true,
);
assert_ok!(result);
let amplification = 100u16;
let fee = Permill::from_percent(1);

assert_ok!(Stableswap::create_pool(
hydradx_runtime::RuntimeOrigin::root(),
pool_id,
asset_ids.iter().map(|(id, _)| *id).collect(),
amplification,
fee,
));

assert_ok!(Stableswap::add_liquidity(
hydradx_runtime::RuntimeOrigin::signed(BOB.into()),
pool_id,
BoundedVec::truncate_from(initial)
));
stable_pool_id = pool_id;
stable_assets = asset_ids;
});

self.add_stablepools(vec![(stable_pool_id, stable_assets)])
}

pub(crate) fn add_stablepools_to_omnipool(self) -> Self {
self.execute(|| {
let omnipool_acc = hydradx_runtime::Omnipool::protocol_account();
for (pool_id, _) in self.stablepools.iter() {
let pool_id_issuance = Tokens::total_issuance(pool_id);
assert_ok!(hydradx_runtime::Currencies::transfer(
hydradx_runtime::RuntimeOrigin::signed(BOB.into()),
omnipool_acc.clone().into(),
*pool_id,
pool_id_issuance,
));
assert_ok!(hydradx_runtime::Omnipool::add_token(
hydradx_runtime::RuntimeOrigin::root(),
*pool_id,
FixedU128::from_inner(25_650_000_000_000_000),
Permill::from_percent(1),
AccountId::from(BOB),
));
}
});
let stableids = self.stablepools.iter().map(|(pool_id, _)| *pool_id).collect();
self.add_omnipool_assets(stableids)
}

fn populate_oracle(self) -> Self {
//we need to make trades for each asset in omnipool
//for at least 10 block to ensure SHORT oracle is updated too
for _ in 1..=10 {
self.new_block();
let assets = self.omnipool_assets.clone();
let stablepools = self.stablepools.clone();
self.execute(|| {
for asset_id in assets {
let amount_to_sell = 1_000_000_000_000;
assert_ok!(Tokens::set_balance(
RawOrigin::Root.into(),
CHARLIE.into(),
crate::polkadot_test_net::LRNA,
amount_to_sell,
0,
));

assert_ok!(Omnipool::sell(
RuntimeOrigin::signed(CHARLIE.into()),
crate::polkadot_test_net::LRNA,
asset_id,
amount_to_sell,
1
));
}

for (pool_id, assets) in stablepools {
for two_assets in assets.windows(2) {
let asset_a = two_assets[0];
let asset_b = two_assets[1];
let amount = 1u128 * 10u128.pow(asset_a.1 as u32);
assert_ok!(Tokens::set_balance(
RawOrigin::Root.into(),
CHARLIE.into(),
asset_a.0,
amount,
0,
));

assert_ok!(Stableswap::sell(
RuntimeOrigin::signed(CHARLIE.into()),
pool_id,
asset_a.0,
asset_b.0,
amount,
1
));
}
}
});
}

self
}

fn new_block(&self) -> &Self {
self.execute(|| {
hydradx_run_to_next_block();
});
self
}
}

#[test]
fn test_hydration_setup() {
HydrationTestDriver::default()
.setup_hydration()
.execute_with_driver(|driver| {
assert_ok!(Tokens::set_balance(
RawOrigin::Root.into(),
CHARLIE.into(),
DOT,
20_000_000_000_000_000_000_000_000,
0,
));

assert_ok!(Omnipool::sell(
hydradx_runtime::RuntimeOrigin::signed(CHARLIE.into()),
DOT,
HDX,
1_000_000_000_000,
0u128,
));

assert_eq!(driver.omnipool_assets, vec![HDX, DOT, WETH, 222_222]);
assert!(driver.stablepools.len() > 0);

let stablepool_1 = driver.stablepools[0].clone();
let first_asset_id = stablepool_1.1[0].0;
let pool_id = stablepool_1.0;

// assert oracle initial values
for supported_period in crate::oracle::SUPPORTED_PERIODS {
assert!(
EmaOracle::get_price(HDX, crate::polkadot_test_net::LRNA, *supported_period, OMNIPOOL_SOURCE)
.is_ok()
);
assert!(
EmaOracle::get_price(DOT, crate::polkadot_test_net::LRNA, *supported_period, OMNIPOOL_SOURCE)
.is_ok()
);
assert!(EmaOracle::get_price(first_asset_id, pool_id, *supported_period, STABLESWAP_SOURCE).is_ok());
}
});
}
Loading
Loading