Skip to content

Commit

Permalink
Merge pull request #789 from galacticcouncil/fix/router-set-route-val…
Browse files Browse the repository at this point in the history
…idation

fix: set route validation for lower liquidity pools
  • Loading branch information
mrq1911 authored Mar 18, 2024
2 parents 43ec430 + bee75f3 commit a0c524a
Show file tree
Hide file tree
Showing 22 changed files with 602 additions and 229 deletions.
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

0 comments on commit a0c524a

Please sign in to comment.