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

fix: set route validation for lower liquidity pools #789

Merged
merged 22 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
12 changes: 6 additions & 6 deletions 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.19.9"
version = "1.19.10"
description = "Integration tests"
authors = ["GalacticCouncil"]
edition = "2021"
Expand Down
144 changes: 98 additions & 46 deletions integration-tests/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,53 @@ fn router_weights_should_be_non_zero() {
mod router_different_pools_tests {
use super::*;

#[test]
fn route_should_fail_when_route_is_not_consistent() {
TestNet::reset();

Hydra::execute_with(|| {
//Arrange
init_omnipool();
create_xyk_pool_with_amounts(DAI, 1000000 * UNITS, DOT, 1000000 * UNITS);
create_xyk_pool_with_amounts(ETH, 1000000 * UNITS, DOT, 1000000 * UNITS);

assert_ok!(Currencies::update_balance(
hydradx_runtime::RuntimeOrigin::root(),
BOB.into(),
ETH,
300000000 * UNITS as i128,
));

let amount_to_sell = UNITS;
let limit = 0;
let trades = vec![
Trade {
pool: PoolType::Omnipool,
asset_in: HDX,
asset_out: DAI,
},
Trade {
pool: PoolType::XYK,
asset_in: ETH,
asset_out: DOT,
},
];

//Act
assert_noop!(
Router::sell(
RuntimeOrigin::signed(BOB.into()),
HDX,
DOT,
amount_to_sell,
limit,
trades
),
pallet_route_executor::Error::<Runtime>::InvalidRoute
);
});
}

#[test]
fn sell_should_work_when_route_contains_trades_with_different_pools() {
TestNet::reset();
Expand Down Expand Up @@ -2847,7 +2894,7 @@ mod set_route {
}

#[test]
fn set_route_should_not_work_when_no_existing_and_reversed_route_is_not_valid_for_trade() {
fn set_route_should_not_work_when_new_route_is_invalid() {
TestNet::reset();

Hydra::execute_with(|| {
Expand Down Expand Up @@ -2913,16 +2960,22 @@ mod set_route {
},
];

assert_ok!(hydradx_runtime::Omnipool::set_asset_tradable_state(
hydradx_runtime::RuntimeOrigin::root(),
DOT,
Tradability::FROZEN
));

//Act and assert
assert_noop!(
Router::set_route(hydradx_runtime::RuntimeOrigin::signed(ALICE.into()), asset_pair, route2),
pallet_route_executor::Error::<hydradx_runtime::Runtime>::InvalidRoute
pallet_omnipool::Error::<hydradx_runtime::Runtime>::NotAllowed
);
});
}

#[test]
fn set_route_should_not_work_when_reversed_route_is_not_valid_due_to_maxout_ratio() {
fn set_route_should_work_when_stored_route_is_broken_due_to_frozen_asset() {
TestNet::reset();

Hydra::execute_with(|| {
Expand All @@ -2933,7 +2986,7 @@ mod set_route {
hydradx_runtime::RuntimeOrigin::root(),
Omnipool::protocol_account(),
DOT,
3000 * UNITS as i128,
1000000000000 * UNITS as i128,
));

assert_ok!(hydradx_runtime::Omnipool::add_token(
Expand All @@ -2945,20 +2998,12 @@ mod set_route {
));

create_xyk_pool_with_amounts(HDX, 1000000 * UNITS, DOT, 1000000 * UNITS);
create_xyk_pool_with_amounts(DOT, 1000000 * UNITS, BTC, 1000000 * UNITS);

create_xyk_pool_with_amounts(HDX, 1000000 * UNITS, DAI, 1000000 * UNITS);
create_xyk_pool_with_amounts(DAI, 1000000 * UNITS, DOT, 1000000 * UNITS);
create_xyk_pool_with_amounts(DOT, 50000 * UNITS, BTC, 4000000 * UNITS);

let route1 = vec![
Trade {
pool: PoolType::XYK,
pool: PoolType::Omnipool,
asset_in: HDX,
asset_out: DAI,
},
Trade {
pool: PoolType::XYK,
asset_in: DAI,
asset_out: DOT,
},
Trade {
Expand All @@ -2976,9 +3021,15 @@ mod set_route {
route1
));

assert_ok!(Omnipool::set_asset_tradable_state(
RuntimeOrigin::root(),
DOT,
Tradability::FROZEN
));

let route2 = vec![
Trade {
pool: PoolType::Omnipool,
pool: PoolType::XYK,
asset_in: HDX,
asset_out: DOT,
},
Expand All @@ -2989,16 +3040,43 @@ mod set_route {
},
];

//Act and assert
assert_ok!(Router::set_route(
hydradx_runtime::RuntimeOrigin::signed(ALICE.into()),
asset_pair,
route2
),);
});
}

#[test]
fn set_route_should_fail_when_no_prestored_but_inverse_route_is_invalid() {
TestNet::reset();

Hydra::execute_with(|| {
//Arrange
init_omnipool();

create_xyk_pool_with_amounts(HDX, 100 * UNITS, BTC, 100000000 * UNITS);

let asset_pair = Pair::new(HDX, BTC);

let route2 = vec![Trade {
pool: PoolType::XYK,
asset_in: HDX,
asset_out: BTC,
}];

//Act and assert
assert_noop!(
Router::set_route(hydradx_runtime::RuntimeOrigin::signed(ALICE.into()), asset_pair, route2),
pallet_route_executor::Error::<hydradx_runtime::Runtime>::InvalidRoute
sp_runtime::TokenError::BelowMinimum
);
});
}

#[test]
fn set_route_should_work_when_stored_route_is_broken_due_to_frozen_asset() {
fn set_route_should_pass_when_normal_is_broken_but_revalidated_with_amount_from_inverse() {
TestNet::reset();

Hydra::execute_with(|| {
Expand All @@ -3009,7 +3087,7 @@ mod set_route {
hydradx_runtime::RuntimeOrigin::root(),
Omnipool::protocol_account(),
DOT,
1000000000000 * UNITS as i128,
100000000 * UNITS as i128,
));

assert_ok!(hydradx_runtime::Omnipool::add_token(
Expand All @@ -3020,39 +3098,13 @@ mod set_route {
AccountId::from(BOB),
));

create_xyk_pool_with_amounts(HDX, 1000000 * UNITS, DOT, 1000000 * UNITS);
create_xyk_pool_with_amounts(DOT, 50000 * UNITS, BTC, 4000000 * UNITS);

let route1 = vec![
Trade {
pool: PoolType::Omnipool,
asset_in: HDX,
asset_out: DOT,
},
Trade {
pool: PoolType::XYK,
asset_in: DOT,
asset_out: BTC,
},
];
create_xyk_pool_with_amounts(DOT, 1 * UNITS, BTC, 1 * UNITS);

let asset_pair = Pair::new(HDX, BTC);

assert_ok!(Router::set_route(
hydradx_runtime::RuntimeOrigin::signed(ALICE.into()),
asset_pair,
route1
));

assert_ok!(Omnipool::set_asset_tradable_state(
RuntimeOrigin::root(),
DOT,
Tradability::FROZEN
));

let route2 = vec![
Trade {
pool: PoolType::XYK,
pool: PoolType::Omnipool,
asset_in: HDX,
asset_out: DOT,
},
Expand Down
2 changes: 1 addition & 1 deletion pallets/dca/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = 'pallet-dca'
version = "1.4.0"
version = "1.4.1"
description = 'A pallet to manage DCA scheduling'
authors = ['GalacticCouncil']
edition = '2021'
Expand Down
1 change: 1 addition & 0 deletions pallets/dca/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ impl pallet_route_executor::Config for Test {
type InspectRegistry = MockedAssetRegistry;
type DefaultRoutePoolType = DefaultRoutePoolType;
type WeightInfo = ();
type TechnicalOrigin = EnsureRoot<Self::AccountId>;
}

type OriginForRuntime = OriginFor<Test>;
Expand Down
2 changes: 1 addition & 1 deletion pallets/route-executor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = 'pallet-route-executor'
version = '2.1.0'
version = '2.2.0'
description = 'A pallet to execute a route containing a sequence of trades'
authors = ['GalacticCouncil']
edition = '2021'
Expand Down
3 changes: 3 additions & 0 deletions pallets/route-executor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ If the route is set successfully, then the fee is payed back.

If the route setting fails, it emits event `RouteUpdateIsNotSuccessful`

### Force insert route
The route can be force inserted for any asset pair by technical origin without involving any validation.

### Providing routes
This pallet is also responsible for providing the best routes for asset pairs.

Expand Down
Loading
Loading