From 1a732d2f24649595da367a1ba6ed0c5f47214d75 Mon Sep 17 00:00:00 2001 From: Nikita Smirnov Date: Thu, 26 Oct 2023 18:28:37 +0200 Subject: [PATCH 01/11] farming clippy fixes --- pallets/farming/src/benchmarking.rs | 20 ++++++++++---------- pallets/farming/src/lib.rs | 6 ++---- pallets/farming/src/mock.rs | 16 ++++++++-------- pallets/farming/src/tests.rs | 20 ++++++++++---------- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/pallets/farming/src/benchmarking.rs b/pallets/farming/src/benchmarking.rs index b51297f7f5..4270d354cf 100644 --- a/pallets/farming/src/benchmarking.rs +++ b/pallets/farming/src/benchmarking.rs @@ -51,7 +51,7 @@ fn asset_owner() -> T::AccountId { } fn signed_origin(account_id: T::AccountId) -> OriginFor { - RawOrigin::Signed(account_id.clone()).into() + RawOrigin::Signed(account_id).into() } fn prepare_pools(count: u32) -> (Vec, Vec) { @@ -76,17 +76,17 @@ fn prepare_pools(count: u32) -> (Vec, Vec) assert_ok!(trading_pair::Pallet::::register( signed_origin::(asset_owner::()), Default::default(), - xor_asset.clone(), - other_asset.clone(), + xor_asset, + other_asset, )); assert_ok!(pool_xyk::Pallet::::initialize_pool( signed_origin::(asset_owner::()), Default::default(), - xor_asset.clone(), - other_asset.clone(), + xor_asset, + other_asset, )); - let pool = pool_xyk::Properties::::get(xor_asset, other_asset.clone()) + let pool = pool_xyk::Properties::::get(xor_asset, other_asset) .unwrap() .0; pools.push(pool); @@ -97,7 +97,7 @@ fn prepare_pools(count: u32) -> (Vec, Vec) fn prepare_good_accounts(count: u32, assets: &[T::AssetId]) { let xor_asset: T::AssetId = XOR.into(); - let xor_owner = assets::Pallet::::asset_owner(&xor_asset).unwrap(); + let xor_owner = assets::Pallet::::asset_owner(xor_asset).unwrap(); for other_asset in assets { for j in 0..count { let account_id = utils::account::(j); @@ -109,7 +109,7 @@ fn prepare_good_accounts(count: u32, assets: &[T::AssetId]) { )); assert_ok!(assets::Pallet::::mint_to( - &other_asset, + other_asset, &asset_owner::(), &account_id, balance!(50000), @@ -119,7 +119,7 @@ fn prepare_good_accounts(count: u32, assets: &[T::AssetId]) { signed_origin::(account_id), Default::default(), XOR.into(), - other_asset.clone(), + *other_asset, balance!(1.1), balance!(2.2), balance!(1.1), @@ -155,7 +155,7 @@ benchmarks! { prepare_good_accounts::(a, &assets); Pallet::::refresh_pools(T::VESTING_FREQUENCY); let pool = pools.remove(0); - let farmers = PoolFarmers::::get(&pool); + let farmers = PoolFarmers::::get(pool); let mut accounts = BTreeMap::new(); Pallet::::prepare_accounts_for_vesting(T::VESTING_FREQUENCY, &mut accounts); }: { diff --git a/pallets/farming/src/lib.rs b/pallets/farming/src/lib.rs index e136f5cf2d..1ebec16ce0 100644 --- a/pallets/farming/src/lib.rs +++ b/pallets/farming/src/lib.rs @@ -29,8 +29,6 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] #[cfg(feature = "runtime-benchmarks")] mod benchmarking; @@ -173,7 +171,7 @@ impl Pallet { ) -> Balance { let base_asset_amt = pool_xyk::Pallet::::get_base_asset_part_from_pool_account( pool, - &trading_pair, + trading_pair, pool_tokens, ) .unwrap_or(0); @@ -235,7 +233,7 @@ impl Pallet { // Vi(t) let now_u128: u128 = now.unique_saturated_into(); let coeff = (FixedWrapper::from(balance!(1)) - + farmer_farming_time.clone() / FixedWrapper::from(balance!(now_u128))) + + farmer_farming_time / FixedWrapper::from(balance!(now_u128))) .pow(T::VESTING_COEFF); coeff * farmer_weight diff --git a/pallets/farming/src/mock.rs b/pallets/farming/src/mock.rs index 5d721b7e00..e46a5d801d 100644 --- a/pallets/farming/src/mock.rs +++ b/pallets/farming/src/mock.rs @@ -114,9 +114,9 @@ parameter_types! { pub GetPswapDistributionAccountId: AccountId = AccountId32::from([3; 32]); pub const GetDefaultSubscriptionFrequency: BlockNumber = 10; pub const GetBurnUpdateFrequency: BlockNumber = 14400; - pub GetIncentiveAssetId: AssetId = common::PSWAP.into(); + pub GetIncentiveAssetId: AssetId = common::PSWAP; pub GetParliamentAccountId: AccountId = AccountId32::from([8; 32]); - pub RewardDoublingAssets: Vec = vec![VAL.into(), PSWAP.into()]; + pub RewardDoublingAssets: Vec = vec![VAL, PSWAP]; pub GetXykFee: Fixed = fixed!(0.003); pub GetMarketMakerRewardsAccountId: AccountId = AccountId32::from([12; 32]); pub GetBondingCurveRewardsAccountId: AccountId = AccountId32::from([13; 32]); @@ -451,7 +451,7 @@ impl Default for ExtBuilder { (CHARLIE(), Scope::Unlimited, preset01.clone()), (DAVE(), Scope::Unlimited, preset01.clone()), (EVE(), Scope::Unlimited, preset01.clone()), - (FERDIE(), Scope::Unlimited, preset01.clone()), + (FERDIE(), Scope::Unlimited, preset01), ], } } @@ -492,7 +492,7 @@ impl ExtBuilder { assets::GenesisConfig:: { endowed_assets: vec![ ( - XOR.into(), + XOR, ALICE(), AssetSymbol(b"XOR".to_vec()), AssetName(b"SORA".to_vec()), @@ -503,7 +503,7 @@ impl ExtBuilder { None, ), ( - DOT.into(), + DOT, ALICE(), AssetSymbol(b"DOT".to_vec()), AssetName(b"DOT".to_vec()), @@ -514,7 +514,7 @@ impl ExtBuilder { None, ), ( - PSWAP.into(), + PSWAP, ALICE(), AssetSymbol(b"PSWAP".to_vec()), AssetName(b"PSWAP".to_vec()), @@ -525,7 +525,7 @@ impl ExtBuilder { None, ), ( - VAL.into(), + VAL, ALICE(), AssetSymbol(b"VAL".to_vec()), AssetName(b"VAL".to_vec()), @@ -536,7 +536,7 @@ impl ExtBuilder { None, ), ( - XSTUSD.into(), + XSTUSD, ALICE(), AssetSymbol(b"XSTUSD".to_vec()), AssetName(b"XSTUSD".to_vec()), diff --git a/pallets/farming/src/tests.rs b/pallets/farming/src/tests.rs index b96611d3e0..3475566dcc 100644 --- a/pallets/farming/src/tests.rs +++ b/pallets/farming/src/tests.rs @@ -305,31 +305,31 @@ fn test() { mock::run_to_block(VESTING_FREQUENCY); - let alice_reward = *Rewards::::get(&ALICE()) + let alice_reward = *Rewards::::get(ALICE()) .rewards .get(&RewardReason::LiquidityProvisionFarming) .unwrap(); assert_eq!(alice_reward, balance!(147095.556665051128722662)); - let bob_reward = *Rewards::::get(&BOB()) + let bob_reward = *Rewards::::get(BOB()) .rewards .get(&RewardReason::LiquidityProvisionFarming) .unwrap(); assert_eq!(bob_reward, balance!(20230.033841899841271451)); - let charlie_reward = *Rewards::::get(&CHARLIE()) + let charlie_reward = *Rewards::::get(CHARLIE()) .rewards .get(&RewardReason::LiquidityProvisionFarming) .unwrap(); assert_eq!(charlie_reward, balance!(188323.224128231249527342)); - let dave_reward = *Rewards::::get(&DAVE()) + let dave_reward = *Rewards::::get(DAVE()) .rewards .get(&RewardReason::LiquidityProvisionFarming) .unwrap(); assert_eq!(dave_reward, balance!(41855.242431516907913566)); - let eve_reward = *Rewards::::get(&EVE()) + let eve_reward = *Rewards::::get(EVE()) .rewards .get(&RewardReason::LiquidityProvisionFarming) .unwrap(); @@ -372,7 +372,7 @@ fn test() { run_to_block(VESTING_FREQUENCY + VESTING_FREQUENCY); - let info = Rewards::::get(&ALICE()); + let info = Rewards::::get(ALICE()); assert_eq!( *info .rewards @@ -381,7 +381,7 @@ fn test() { balance!(362281.956723538535819602) ); - let info = Rewards::::get(&BOB()); + let info = Rewards::::get(BOB()); // BOB's rewards didn't change assert_eq!( *info @@ -391,7 +391,7 @@ fn test() { balance!(20230.033841899841271451) ); - let info = Rewards::::get(&CHARLIE()); + let info = Rewards::::get(CHARLIE()); assert_eq!( *info .rewards @@ -400,7 +400,7 @@ fn test() { balance!(395638.161949291391006768) ); - let info = Rewards::::get(&DAVE()); + let info = Rewards::::get(DAVE()); assert_eq!( *info .rewards @@ -409,7 +409,7 @@ fn test() { balance!(73254.876962256299307236) ); - let info = Rewards::::get(&EVE()); + let info = Rewards::::get(EVE()); assert_eq!( *info .rewards From 36f8e1a1e2ec41d0ef40848f2c504e781e62d0a5 Mon Sep 17 00:00:00 2001 From: Nikita Smirnov Date: Thu, 26 Oct 2023 18:34:33 +0200 Subject: [PATCH 02/11] faucet clippy fixes --- pallets/faucet/src/benchmarking.rs | 5 ++--- pallets/faucet/src/lib.rs | 2 -- pallets/faucet/src/mock.rs | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pallets/faucet/src/benchmarking.rs b/pallets/faucet/src/benchmarking.rs index 9789adb595..7acba81eea 100644 --- a/pallets/faucet/src/benchmarking.rs +++ b/pallets/faucet/src/benchmarking.rs @@ -53,8 +53,7 @@ fn alice() -> T::AccountId { fn add_assets(n: u32) -> Result<(), &'static str> { let owner = alice::(); frame_system::Pallet::::inc_providers(&owner); - let owner_origin: ::RuntimeOrigin = - RawOrigin::Signed(owner.clone()).into(); + let owner_origin: ::RuntimeOrigin = RawOrigin::Signed(owner).into(); for _i in 0..n { Assets::::register( owner_origin.clone(), @@ -99,7 +98,7 @@ benchmarks! { reset_rewards { add_assets::(100)?; let caller = alice::(); - let caller_origin: ::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); + let caller_origin: ::RuntimeOrigin = RawOrigin::Signed(caller).into(); }: { Pallet::::reset_rewards(caller_origin)?; } diff --git a/pallets/faucet/src/lib.rs b/pallets/faucet/src/lib.rs index 3e714514fd..e59915660b 100644 --- a/pallets/faucet/src/lib.rs +++ b/pallets/faucet/src/lib.rs @@ -29,8 +29,6 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] use common::{balance, AssetInfoProvider, Balance, HERMES_ASSET_ID, PSWAP, VAL, XOR}; use frame_support::ensure; diff --git a/pallets/faucet/src/mock.rs b/pallets/faucet/src/mock.rs index a9d760454f..6d3962dbd7 100644 --- a/pallets/faucet/src/mock.rs +++ b/pallets/faucet/src/mock.rs @@ -274,7 +274,7 @@ impl ExtBuilder { None, ), ( - VAL.into(), + VAL, alice(), AssetSymbol(b"VAL".to_vec()), AssetName(b"SORA Validator Token".to_vec()), @@ -292,7 +292,7 @@ impl ExtBuilder { TokensConfig { balances: vec![( account_id.clone(), - VAL.into(), + VAL, (faucet::DEFAULT_LIMIT * FixedWrapper::from(1.5)).into_balance(), )], } From db2df62cbe77c79c83749fcbea518e5470cb482f Mon Sep 17 00:00:00 2001 From: Nikita Smirnov Date: Thu, 26 Oct 2023 18:39:54 +0200 Subject: [PATCH 03/11] hermes-governance-platform clippy fixes --- .../src/benchmarking.rs | 26 ++-- pallets/hermes-governance-platform/src/lib.rs | 43 +++--- .../src/migrations.rs | 10 +- .../hermes-governance-platform/src/mock.rs | 5 +- .../hermes-governance-platform/src/tests.rs | 146 +++++++++--------- 5 files changed, 110 insertions(+), 120 deletions(-) diff --git a/pallets/hermes-governance-platform/src/benchmarking.rs b/pallets/hermes-governance-platform/src/benchmarking.rs index 77b45a87cf..fb0601783c 100644 --- a/pallets/hermes-governance-platform/src/benchmarking.rs +++ b/pallets/hermes-governance-platform/src/benchmarking.rs @@ -47,7 +47,7 @@ benchmarks! { let nonce = frame_system::Pallet::::account_nonce(&caller); let encoded: [u8; 32] = (&caller, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); - let owner: T::AccountId = assets::AssetOwners::::get::(HERMES_ASSET_ID.clone().into()).unwrap(); + let owner: T::AccountId = assets::AssetOwners::::get::(HERMES_ASSET_ID.into()).unwrap(); let mut options = BoundedVec::default(); options.try_push("Yes".try_into().unwrap()).unwrap(); options.try_push("No".try_into().unwrap()).unwrap(); @@ -70,11 +70,11 @@ benchmarks! { options }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, &hermes_poll_info); }: { let _ = HermesGovernancePlatform::::vote( RawOrigin::Signed(caller.clone()).into(), - poll_id.clone(), + poll_id, voting_option.try_into().unwrap(), ).unwrap(); } @@ -89,7 +89,7 @@ benchmarks! { let poll_start_timestamp = Timestamp::::get(); let poll_end_timestamp = Timestamp::::get() + (14400*1000u32).into(); let hermes_amount = balance!(100000); - let owner: T::AccountId = assets::AssetOwners::::get::(HERMES_ASSET_ID.clone().into()).unwrap(); + let owner: T::AccountId = assets::AssetOwners::::get::(HERMES_ASSET_ID.into()).unwrap(); let mut options = BoundedVec::default(); options.try_push("Yes".try_into().unwrap()).unwrap(); options.try_push("No".try_into().unwrap()).unwrap(); @@ -125,7 +125,7 @@ benchmarks! { let poll_start_timestamp = Timestamp::::get(); let poll_end_timestamp = Timestamp::::get() + (14400*1000u32).into(); let current_timestamp = Timestamp::::get(); - let owner: T::AccountId = assets::AssetOwners::::get::(HERMES_ASSET_ID.clone().into()).unwrap(); + let owner: T::AccountId = assets::AssetOwners::::get::(HERMES_ASSET_ID.into()).unwrap(); let nonce = frame_system::Pallet::::account_nonce(&caller); let encoded: [u8; 32] = (&caller, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); @@ -134,7 +134,7 @@ benchmarks! { options.try_push("No".try_into().unwrap()).unwrap(); let _ = Assets::::mint( - RawOrigin::Signed(owner.clone()).into(), + RawOrigin::Signed(owner).into(), HERMES_ASSET_ID.into(), caller.clone(), number_of_hermes @@ -151,20 +151,20 @@ benchmarks! { options }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, &hermes_poll_info); let _ = HermesGovernancePlatform::::vote( RawOrigin::Signed(caller.clone()).into(), - poll_id.clone(), + poll_id, voting_option.try_into().unwrap(), ); - let hermes_voting_info = pallet::HermesVotings::::get(&poll_id, &caller).unwrap(); + let hermes_voting_info = pallet::HermesVotings::::get(poll_id, &caller).unwrap(); pallet_timestamp::Now::::put(current_timestamp + (14401*1000u32).into()); }: { let _ = HermesGovernancePlatform::::withdraw_funds_voter( RawOrigin::Signed(caller.clone()).into(), - poll_id.clone() + poll_id ); } verify { @@ -180,7 +180,7 @@ benchmarks! { let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); let poll_start_timestamp = Timestamp::::get(); let poll_end_timestamp = Timestamp::::get() + (14400*1000u32).into(); - let owner: T::AccountId = assets::AssetOwners::::get::(HERMES_ASSET_ID.clone().into()).unwrap(); + let owner: T::AccountId = assets::AssetOwners::::get::(HERMES_ASSET_ID.into()).unwrap(); let nonce = frame_system::Pallet::::account_nonce(&caller); let encoded: [u8; 32] = (&caller, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); @@ -206,7 +206,7 @@ benchmarks! { options }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, &hermes_poll_info); let pallet_account: AccountIdOf = PalletId(*b"hermsgov").into_account_truncating(); assert_ok!(Assets::::transfer_from( @@ -221,7 +221,7 @@ benchmarks! { }: { let _ = HermesGovernancePlatform::::withdraw_funds_creator( RawOrigin::Signed(caller.clone()).into(), - poll_id.clone() + poll_id ); } verify { diff --git a/pallets/hermes-governance-platform/src/lib.rs b/pallets/hermes-governance-platform/src/lib.rs index 042dcb9d1a..1a75740ae6 100644 --- a/pallets/hermes-governance-platform/src/lib.rs +++ b/pallets/hermes-governance-platform/src/lib.rs @@ -1,6 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] +#![allow(clippy::type_complexity)] mod benchmarking; pub mod migrations; @@ -284,7 +283,7 @@ pub mod pallet { let current_timestamp = Timestamp::::get(); let hermes_poll_info = - >::get(&poll_id).ok_or(Error::::PollDoesNotExist)?; + >::get(poll_id).ok_or(Error::::PollDoesNotExist)?; ensure!( current_timestamp >= hermes_poll_info.poll_start_timestamp, @@ -303,13 +302,12 @@ pub mod pallet { ensure!( MinimumHermesVotingAmount::::get() - <= Assets::::free_balance(&T::HermesAssetId::get().into(), &user) - .unwrap_or(0), + <= Assets::::free_balance(&T::HermesAssetId::get(), &user).unwrap_or(0), Error::::NotEnoughHermesForVoting ); ensure!( - !>::contains_key(&poll_id, &user), + !>::contains_key(poll_id, &user), Error::::AlreadyVoted ); @@ -321,7 +319,7 @@ pub mod pallet { // Transfer Hermes to pallet Assets::::transfer_from( - &T::HermesAssetId::get().into(), + &T::HermesAssetId::get(), &user, &Self::account_id(), hermes_voting_info.number_of_hermes, @@ -329,7 +327,7 @@ pub mod pallet { .map_err(|_assets_err| Error::::NotEnoughHermesForVoting)?; // Update storage - >::insert(&poll_id, &user, hermes_voting_info); + >::insert(poll_id, &user, hermes_voting_info); // Emit event Self::deposit_event(Event::::Voted(user, poll_id, voting_option)); @@ -374,8 +372,7 @@ pub mod pallet { ensure!( MinimumHermesAmountForCreatingPoll::::get() - <= Assets::::free_balance(&T::HermesAssetId::get().into(), &user) - .unwrap_or(0), + <= Assets::::free_balance(&T::HermesAssetId::get(), &user).unwrap_or(0), Error::::NotEnoughHermesForCreatingPoll ); @@ -409,18 +406,18 @@ pub mod pallet { // Transfer Hermes to pallet Assets::::transfer_from( - &T::HermesAssetId::get().into(), - &user.clone(), + &T::HermesAssetId::get(), + &user, &Self::account_id(), hermes_poll_info.hermes_locked, ) .map_err(|_assets_err| Error::::NotEnoughHermesForCreatingPoll)?; - >::insert(&poll_id, hermes_poll_info); + >::insert(poll_id, hermes_poll_info); // Emit event Self::deposit_event(Event::::Created( - user.clone(), + user, title, poll_start_timestamp, poll_end_timestamp, @@ -440,7 +437,7 @@ pub mod pallet { let user = ensure_signed(origin)?; let current_timestamp = Timestamp::::get(); let hermes_poll_info = - >::get(&poll_id).ok_or(Error::::PollDoesNotExist)?; + >::get(poll_id).ok_or(Error::::PollDoesNotExist)?; ensure!( current_timestamp > hermes_poll_info.poll_end_timestamp, @@ -448,23 +445,23 @@ pub mod pallet { ); let mut hermes_voting_info = - >::get(&poll_id, &user).ok_or(Error::::NotVoted)?; + >::get(poll_id, &user).ok_or(Error::::NotVoted)?; ensure!( - hermes_voting_info.hermes_withdrawn == false, + !hermes_voting_info.hermes_withdrawn, Error::::FundsAlreadyWithdrawn ); // Withdraw Hermes Assets::::transfer_from( - &T::HermesAssetId::get().into(), + &T::HermesAssetId::get(), &Self::account_id(), &user, hermes_voting_info.number_of_hermes, )?; hermes_voting_info.hermes_withdrawn = true; - >::insert(&poll_id, &user, &hermes_voting_info); + >::insert(poll_id, &user, &hermes_voting_info); // Emit event Self::deposit_event(Event::::VoterFundsWithdrawn( @@ -486,7 +483,7 @@ pub mod pallet { let user = ensure_signed(origin)?; let current_timestamp = Timestamp::::get(); let mut hermes_poll_info = - >::get(&poll_id).ok_or(Error::::PollDoesNotExist)?; + >::get(poll_id).ok_or(Error::::PollDoesNotExist)?; ensure!( hermes_poll_info.creator == user, @@ -499,20 +496,20 @@ pub mod pallet { ); ensure!( - hermes_poll_info.creator_hermes_withdrawn == false, + !hermes_poll_info.creator_hermes_withdrawn, Error::::FundsAlreadyWithdrawn ); // Withdraw Creator Hermes Assets::::transfer_from( - &T::HermesAssetId::get().into(), + &T::HermesAssetId::get(), &Self::account_id(), &user, hermes_poll_info.hermes_locked, )?; hermes_poll_info.creator_hermes_withdrawn = true; - >::insert(&poll_id, &hermes_poll_info); + >::insert(poll_id, &hermes_poll_info); // Emit event Self::deposit_event(Event::::CreatorFundsWithdrawn( diff --git a/pallets/hermes-governance-platform/src/migrations.rs b/pallets/hermes-governance-platform/src/migrations.rs index 9fcdf03fc2..61bc623bc8 100644 --- a/pallets/hermes-governance-platform/src/migrations.rs +++ b/pallets/hermes-governance-platform/src/migrations.rs @@ -46,13 +46,11 @@ pub fn migrate_voting_and_poll_data() -> Weight { |(voting_option, number_of_hermes, hermes_withdrawn)| { weight += 1; - let new_voting_option; - - if voting_option == VotingOption::Yes { - new_voting_option = "Yes"; + let new_voting_option = if voting_option == VotingOption::Yes { + "Yes" } else { - new_voting_option = "No"; - } + "No" + }; Some(HermesVotingInfo { voting_option: BoundedString::truncate_from(new_voting_option), diff --git a/pallets/hermes-governance-platform/src/mock.rs b/pallets/hermes-governance-platform/src/mock.rs index b917860a38..3add4e0713 100644 --- a/pallets/hermes-governance-platform/src/mock.rs +++ b/pallets/hermes-governance-platform/src/mock.rs @@ -11,7 +11,7 @@ use currencies::BasicCurrencyAdapter; use frame_support::traits::{Everything, GenesisBuild, Hooks}; use frame_support::weights::Weight; use frame_support::{construct_runtime, parameter_types}; -use frame_system; + use frame_system::pallet_prelude::BlockNumberFor; use sp_core::H256; use sp_runtime::testing::Header; @@ -75,7 +75,7 @@ parameter_types! { pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub GetXykFee: Fixed = fixed!(0.003); - pub GetIncentiveAssetId: AssetId = common::PSWAP.into(); + pub GetIncentiveAssetId: AssetId = common::PSWAP; pub const GetDefaultSubscriptionFrequency: BlockNumber = 10; pub const GetBurnUpdateFrequency: BlockNumber = 14400; pub GetParliamentAccountId: AccountId = 100; @@ -289,6 +289,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = (); } +#[allow(clippy::type_complexity)] pub struct ExtBuilder { endowed_assets: Vec<( AssetId, diff --git a/pallets/hermes-governance-platform/src/tests.rs b/pallets/hermes-governance-platform/src/tests.rs index 648cafd0dc..59658fcb32 100644 --- a/pallets/hermes-governance-platform/src/tests.rs +++ b/pallets/hermes-governance-platform/src/tests.rs @@ -224,7 +224,7 @@ fn create_poll_ok() { for (_, p_info) in pallet::HermesPollData::::iter() { assert_eq!(p_info.poll_start_timestamp, poll_start_timestamp); assert_eq!(p_info.poll_end_timestamp, poll_end_timestamp); - assert_eq!(p_info.creator_hermes_withdrawn, false); + assert!(!p_info.creator_hermes_withdrawn); assert_eq!(p_info.hermes_locked, hermes_locked); } @@ -251,7 +251,7 @@ fn vote_poll_does_not_exist() { let user = ALICE; let voting_option = "Option 1".try_into().unwrap(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); @@ -270,7 +270,7 @@ fn vote_poll_is_not_started() { let poll_end_timestamp = pallet_timestamp::Pallet::::get() + 14_400_000; let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 1".try_into().unwrap(); @@ -292,7 +292,7 @@ fn vote_poll_is_not_started() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_err!( HermesGovernancePlatform::vote(RuntimeOrigin::signed(ALICE), poll_id, voting_option), @@ -310,7 +310,7 @@ fn vote_poll_is_finished() { let user = ALICE; let current_timestamp = pallet_timestamp::Pallet::::get(); let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 1".try_into().unwrap(); @@ -330,7 +330,7 @@ fn vote_poll_is_finished() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); pallet_timestamp::Pallet::::set_timestamp(current_timestamp + 604800001); assert_err!( @@ -348,7 +348,7 @@ fn vote_invalid_option() { let poll_end_timestamp = pallet_timestamp::Pallet::::get() + 604800000; let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 5".try_into().unwrap(); @@ -368,7 +368,7 @@ fn vote_invalid_option() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_err!( HermesGovernancePlatform::vote(RuntimeOrigin::signed(ALICE), poll_id, voting_option,), @@ -385,7 +385,7 @@ fn vote_not_enough_hermes_for_voting() { let poll_end_timestamp = pallet_timestamp::Pallet::::get() + 604800000; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); let user = ALICE; - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 1".try_into().unwrap(); @@ -404,7 +404,7 @@ fn vote_not_enough_hermes_for_voting() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_err!( HermesGovernancePlatform::vote(RuntimeOrigin::signed(BOB), poll_id, voting_option), @@ -421,7 +421,7 @@ fn vote_already_voted() { let poll_end_timestamp = pallet_timestamp::Pallet::::get() + 604800000; let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 1"; @@ -441,18 +441,18 @@ fn vote_already_voted() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_ok!(HermesGovernancePlatform::vote( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, voting_option.try_into().unwrap() )); assert_err!( HermesGovernancePlatform::vote( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, voting_option.try_into().unwrap() ), Error::::AlreadyVoted @@ -469,7 +469,7 @@ fn vote_ok() { let user = ALICE; let number_of_hermes = pallet::MinimumHermesVotingAmount::::get(); let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 1"; @@ -490,21 +490,21 @@ fn vote_ok() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_ok!(HermesGovernancePlatform::vote( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, voting_option.try_into().unwrap(), )); - let hermes_voting_info = pallet::HermesVotings::::get(&poll_id, &ALICE).unwrap(); + let hermes_voting_info = pallet::HermesVotings::::get(poll_id, ALICE).unwrap(); assert_eq!( hermes_voting_info.voting_option, voting_option.try_into().unwrap() ); - assert_eq!(hermes_voting_info.hermes_withdrawn, false); + assert!(!hermes_voting_info.hermes_withdrawn); assert_eq!(hermes_voting_info.number_of_hermes, number_of_hermes); // Check ALICE's balances @@ -528,7 +528,7 @@ fn withdraw_funds_voter_poll_does_not_exist() { let mut ext = ExtBuilder::default().build(); ext.execute_with(|| { let user = ALICE; - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); @@ -547,7 +547,7 @@ fn withdraw_funds_voter_poll_is_not_finished() { let poll_end_timestamp = pallet_timestamp::Pallet::::get() + 604800000; let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 1".try_into().unwrap(); @@ -567,11 +567,11 @@ fn withdraw_funds_voter_poll_is_not_finished() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_ok!(HermesGovernancePlatform::vote( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, voting_option, )); @@ -591,7 +591,7 @@ fn withdraw_funds_voter_not_voted() { let user = ALICE; let current_timestamp = pallet_timestamp::Pallet::::get(); let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let mut options = BoundedVec::default(); @@ -610,7 +610,7 @@ fn withdraw_funds_voter_not_voted() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); pallet_timestamp::Pallet::::set_timestamp(current_timestamp + 604900000); @@ -630,7 +630,7 @@ fn withdraw_funds_voter_funds_already_withdrawn() { let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); let current_timestamp = pallet_timestamp::Pallet::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 1".try_into().unwrap(); @@ -649,11 +649,11 @@ fn withdraw_funds_voter_funds_already_withdrawn() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_ok!(HermesGovernancePlatform::vote( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, voting_option, )); @@ -661,14 +661,11 @@ fn withdraw_funds_voter_funds_already_withdrawn() { assert_ok!(HermesGovernancePlatform::withdraw_funds_voter( RuntimeOrigin::signed(ALICE), - poll_id.clone() + poll_id )); assert_err!( - HermesGovernancePlatform::withdraw_funds_voter( - RuntimeOrigin::signed(ALICE), - poll_id.clone(), - ), + HermesGovernancePlatform::withdraw_funds_voter(RuntimeOrigin::signed(ALICE), poll_id,), Error::::FundsAlreadyWithdrawn ); }); @@ -684,7 +681,7 @@ fn withdraw_funds_voter_ok() { let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); let number_of_hermes = pallet::MinimumHermesVotingAmount::::get(); let current_timestamp = pallet_timestamp::Pallet::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let voting_option = "Option 1"; @@ -704,11 +701,11 @@ fn withdraw_funds_voter_ok() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_ok!(HermesGovernancePlatform::vote( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, voting_option.try_into().unwrap() )); @@ -716,17 +713,17 @@ fn withdraw_funds_voter_ok() { assert_ok!(HermesGovernancePlatform::withdraw_funds_voter( RuntimeOrigin::signed(ALICE), - poll_id.clone() + poll_id )); - let hermes_voting_info = pallet::HermesVotings::::get(&poll_id, &ALICE).unwrap(); + let hermes_voting_info = pallet::HermesVotings::::get(poll_id, ALICE).unwrap(); assert_eq!( hermes_voting_info.voting_option, voting_option.try_into().unwrap() ); assert_eq!(hermes_voting_info.number_of_hermes, number_of_hermes); - assert_eq!(hermes_voting_info.hermes_withdrawn, true); + assert!(hermes_voting_info.hermes_withdrawn); // Check ALICE's balances assert_eq!( @@ -749,7 +746,7 @@ fn withdraw_funds_creator_poll_does_not_exist() { let mut ext = ExtBuilder::default().build(); ext.execute_with(|| { let user = ALICE; - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); @@ -769,7 +766,7 @@ fn withdraw_funds_creator_you_are_not_creator() { let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); let current_timestamp = pallet_timestamp::Pallet::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let mut options = BoundedVec::default(); @@ -787,15 +784,12 @@ fn withdraw_funds_creator_you_are_not_creator() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); pallet_timestamp::Pallet::::set_timestamp(current_timestamp + 604900000); assert_err!( - HermesGovernancePlatform::withdraw_funds_creator( - RuntimeOrigin::signed(BOB), - poll_id.clone(), - ), + HermesGovernancePlatform::withdraw_funds_creator(RuntimeOrigin::signed(BOB), poll_id,), Error::::YouAreNotCreator ); }); @@ -809,7 +803,7 @@ fn withdraw_funds_creator_poll_is_not_finished() { let poll_end_timestamp = pallet_timestamp::Pallet::::get() + 604800000; let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let mut options = BoundedVec::default(); @@ -828,12 +822,12 @@ fn withdraw_funds_creator_poll_is_not_finished() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, hermes_poll_info); assert_err!( HermesGovernancePlatform::withdraw_funds_creator( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, ), Error::::PollIsNotFinished ); @@ -849,7 +843,7 @@ fn withdraw_funds_creator_funds_already_withdrawn() { let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); let current_timestamp = pallet_timestamp::Pallet::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let mut options = BoundedVec::default(); @@ -869,11 +863,11 @@ fn withdraw_funds_creator_funds_already_withdrawn() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, &hermes_poll_info); let pallet_account = PalletId(*b"hermsgov").into_account_truncating(); assert_ok!(Assets::transfer_from( - &HERMES_ASSET_ID.into(), + &HERMES_ASSET_ID, &user, &pallet_account, hermes_poll_info.hermes_locked @@ -883,13 +877,13 @@ fn withdraw_funds_creator_funds_already_withdrawn() { assert_ok!(HermesGovernancePlatform::withdraw_funds_creator( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, )); assert_err!( HermesGovernancePlatform::withdraw_funds_creator( RuntimeOrigin::signed(ALICE), - poll_id.clone(), + poll_id, ), Error::::FundsAlreadyWithdrawn ); @@ -902,10 +896,10 @@ fn withdraw_funds_creator_ok() { ext.execute_with(|| { let poll_start_timestamp = pallet_timestamp::Pallet::::get(); let poll_end_timestamp = pallet_timestamp::Pallet::::get() + 604800000; - let user = ALICE.into(); + let user = ALICE; let hermes_locked = pallet::MinimumHermesAmountForCreatingPoll::::get(); let current_timestamp = pallet_timestamp::Pallet::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id = H256::from(encoded); let mut options = BoundedVec::default(); @@ -924,11 +918,11 @@ fn withdraw_funds_creator_ok() { options, }; - pallet::HermesPollData::::insert(&poll_id, &hermes_poll_info); + pallet::HermesPollData::::insert(poll_id, &hermes_poll_info); let pallet_account = PalletId(*b"hermsgov").into_account_truncating(); assert_ok!(Assets::transfer_from( - &HERMES_ASSET_ID.into(), + &HERMES_ASSET_ID, &user, &pallet_account, hermes_poll_info.hermes_locked @@ -938,11 +932,11 @@ fn withdraw_funds_creator_ok() { assert_ok!(HermesGovernancePlatform::withdraw_funds_creator( RuntimeOrigin::signed(ALICE), - poll_id.clone() + poll_id )); - let hermes_info = pallet::HermesPollData::::get(&poll_id).unwrap(); - assert_eq!(hermes_info.creator_hermes_withdrawn, true); + let hermes_info = pallet::HermesPollData::::get(poll_id).unwrap(); + assert!(hermes_info.creator_hermes_withdrawn); // Check ALICE's balances assert_eq!( @@ -1033,7 +1027,7 @@ fn hermes_governance_storage_migration_works() { let user = ALICE; let user1 = CHARLES; let number_of_hermes = pallet::MinimumHermesVotingAmount::::get(); - let nonce = frame_system::Pallet::::account_nonce(&user); + let nonce = frame_system::Pallet::::account_nonce(user); let encoded: [u8; 32] = (&user, nonce).using_encoded(blake2_256); let poll_id_a = H256::from(encoded); let poll_id_b = H256::from(encoded); @@ -1072,18 +1066,18 @@ fn hermes_governance_storage_migration_works() { let old_poll_data = OldHermesPollInfo { creator: user, hermes_locked: number_of_hermes, - poll_start_timestamp: poll_start_timestamp, - poll_end_timestamp: poll_end_timestamp, + poll_start_timestamp, + poll_end_timestamp, title: "Titile".try_into().unwrap(), description: "Description".try_into().unwrap(), creator_hermes_withdrawn: false, }; - OldHermesVotings::insert(&poll_id_a, user, old_voting_info_a); - OldHermesVotings::insert(&poll_id_b, user1, old_voting_info_b); + OldHermesVotings::insert(poll_id_a, user, old_voting_info_a); + OldHermesVotings::insert(poll_id_b, user1, old_voting_info_b); - OldHermesPollData::insert(&poll_id_a, &old_poll_data); - OldHermesPollData::insert(&poll_id_b, &old_poll_data); + OldHermesPollData::insert(poll_id_a, &old_poll_data); + OldHermesPollData::insert(poll_id_b, &old_poll_data); pallet_timestamp::Pallet::::set_timestamp(10000000); run_to_block(5); @@ -1091,13 +1085,13 @@ fn hermes_governance_storage_migration_works() { //Storage migration pallet::Pallet::::on_runtime_upgrade(); - let poll_a = pallet::HermesPollData::::get(&poll_id_a).unwrap(); - let voting_a = pallet::HermesVotings::::get(&poll_id_a, &user).unwrap(); + let poll_a = pallet::HermesPollData::::get(poll_id_a).unwrap(); + let voting_a = pallet::HermesVotings::::get(poll_id_a, user).unwrap(); assert_eq!(poll_a.options, options); assert_eq!(voting_a.voting_option, "Yes".try_into().unwrap()); - let poll_b = pallet::HermesPollData::::get(&poll_id_b).unwrap(); - let voting_b = pallet::HermesVotings::::get(&poll_id_b, &user1).unwrap(); + let poll_b = pallet::HermesPollData::::get(poll_id_b).unwrap(); + let voting_b = pallet::HermesVotings::::get(poll_id_b, user1).unwrap(); assert_eq!(poll_b.options, options); assert_eq!(voting_b.voting_option, "No".try_into().unwrap()); @@ -1108,13 +1102,13 @@ fn hermes_governance_storage_migration_works() { // Storage migration pallet::Pallet::::on_runtime_upgrade(); - let poll_a = pallet::HermesPollData::::get(&poll_id_a).unwrap(); - let voting_a = pallet::HermesVotings::::get(&poll_id_a, &user).unwrap(); + let poll_a = pallet::HermesPollData::::get(poll_id_a).unwrap(); + let voting_a = pallet::HermesVotings::::get(poll_id_a, user).unwrap(); assert_eq!(poll_a.options, options); assert_eq!(voting_a.voting_option, "Yes".try_into().unwrap()); - let poll_b = pallet::HermesPollData::::get(&poll_id_b).unwrap(); - let voting_b = pallet::HermesVotings::::get(&poll_id_b, &user1).unwrap(); + let poll_b = pallet::HermesPollData::::get(poll_id_b).unwrap(); + let voting_b = pallet::HermesVotings::::get(poll_id_b, user1).unwrap(); assert_eq!(poll_b.options, options); assert_eq!(voting_b.voting_option, "No".try_into().unwrap()); }); From 5621da508302df60bbfc873f66c8421cd180c7d6 Mon Sep 17 00:00:00 2001 From: Nikita Smirnov Date: Thu, 26 Oct 2023 19:00:47 +0200 Subject: [PATCH 04/11] iroha-migration clippy fixes --- pallets/iroha-migration/src/lib.rs | 39 ++++++++++++++-------------- pallets/iroha-migration/src/mock.rs | 20 ++++++-------- pallets/iroha-migration/src/tests.rs | 33 ++++++++++++----------- 3 files changed, 44 insertions(+), 48 deletions(-) diff --git a/pallets/iroha-migration/src/lib.rs b/pallets/iroha-migration/src/lib.rs index e9c5ea5487..c3188ad3c1 100644 --- a/pallets/iroha-migration/src/lib.rs +++ b/pallets/iroha-migration/src/lib.rs @@ -36,11 +36,11 @@ //! All migrated accounts are stored to use when their referrals migrate or when a user attempts to migrate again #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] #[macro_use] extern crate alloc; +use core::cmp::Ordering; + use alloc::string::String; #[cfg(feature = "runtime-benchmarks")] @@ -115,8 +115,8 @@ impl Pallet { fn migrate_weight( iroha_address: &String, - iroha_public_key: &String, - iroha_signature: &String, + iroha_public_key: &str, + iroha_signature: &str, ) -> (Weight, Pays) { let pays = if Self::check_migrate(iroha_address, iroha_public_key, iroha_signature).is_ok() { @@ -130,20 +130,20 @@ impl Pallet { /// Checks if migration would succeed if the parameters were passed to migrate extrinsic. fn check_migrate( iroha_address: &String, - iroha_public_key: &String, - iroha_signature: &String, + iroha_public_key: &str, + iroha_signature: &str, ) -> Result<(), DispatchError> { let iroha_public_key = iroha_public_key.to_lowercase(); let iroha_signature = iroha_signature.to_lowercase(); ensure!( - !MigratedAccounts::::contains_key(&iroha_address), + !MigratedAccounts::::contains_key(iroha_address), Error::::AccountAlreadyMigrated ); // This account isn't migrated so the abusers couldn't copy signature from the blockchain for single-signature accounts. - Self::verify_signature(&iroha_address, &iroha_public_key, &iroha_signature)?; + Self::verify_signature(iroha_address, &iroha_public_key, &iroha_signature)?; // However, for multi-signature accounts, their signatures can be abused so we continue checking. let public_keys = - PublicKeys::::try_get(&iroha_address).map_err(|_| Error::::PublicKeyNotFound)?; + PublicKeys::::try_get(iroha_address).map_err(|_| Error::::PublicKeyNotFound)?; let already_migrated = public_keys .iter() .find_map(|(already_migrated, key)| { @@ -160,7 +160,7 @@ impl Pallet { fn parse_public_key(iroha_public_key: &str) -> Result { let iroha_public_key = - hex::decode(&iroha_public_key).map_err(|_| Error::::PublicKeyParsingFailed)?; + hex::decode(iroha_public_key).map_err(|_| Error::::PublicKeyParsingFailed)?; let public_key = PublicKey::from_bytes(iroha_public_key.as_slice()) .map_err(|_| Error::::PublicKeyParsingFailed)?; Ok(public_key) @@ -243,17 +243,17 @@ impl Pallet { Self::migrate_account(iroha_address, multi_account)?; } else { let quorum = Quorums::::get(&iroha_address) as usize; - if approval_count == quorum { - PendingMultiSigAccounts::::mutate(&iroha_address, |a| { + match approval_count.cmp(&quorum) { + Ordering::Equal => PendingMultiSigAccounts::::mutate(&iroha_address, |a| { a.approving_accounts.push(account); let migrate_at = frame_system::Pallet::::block_number() + blocks_till_migration::(); a.migrate_at = Some(migrate_at); - }); - } else if approval_count < quorum { - PendingMultiSigAccounts::::mutate(&iroha_address, |a| { + }), + Ordering::Less => PendingMultiSigAccounts::::mutate(&iroha_address, |a| { a.approving_accounts.push(account); - }); + }), + _ => (), } } Ok(()) @@ -299,7 +299,7 @@ impl Pallet { // Free up memory Referrers::::remove(iroha_address); if let Some(referrer) = MigratedAccounts::::get(&referrer) { - referrals::Pallet::::set_referrer_to(&account, referrer) + referrals::Pallet::::set_referrer_to(account, referrer) .map_err(|_| Error::::ReferralMigrationFailed)?; } else { PendingReferrals::::mutate(&referrer, |referrals| { @@ -476,6 +476,7 @@ pub mod pallet { StorageMap<_, Blake2_128Concat, String, Vec, ValueQuery>; #[pallet::genesis_config] + #[allow(clippy::type_complexity)] pub struct GenesisConfig { pub account_id: Option, pub iroha_accounts: Vec<(String, Balance, Option, u8, Vec)>, @@ -494,8 +495,8 @@ pub mod pallet { #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - frame_system::Pallet::::inc_consumers(&self.account_id.as_ref().unwrap()).unwrap(); - Account::::put(&self.account_id.as_ref().unwrap()); + frame_system::Pallet::::inc_consumers(self.account_id.as_ref().unwrap()).unwrap(); + Account::::put(self.account_id.as_ref().unwrap()); for (account_id, balance, referrer, threshold, public_keys) in &self.iroha_accounts { Balances::::insert(account_id, *balance); diff --git a/pallets/iroha-migration/src/mock.rs b/pallets/iroha-migration/src/mock.rs index bdae17d63a..b16a591273 100644 --- a/pallets/iroha-migration/src/mock.rs +++ b/pallets/iroha-migration/src/mock.rs @@ -229,11 +229,7 @@ pub fn test_ext(add_iroha_accounts: bool) -> sp_io::TestExternalities { .unwrap(); pallet_balances::GenesisConfig:: { - balances: vec![ - (ALICE, 0u128.into()), - (BOB, 0u128.into()), - (MINTING_ACCOUNT, 0u128.into()), - ], + balances: vec![(ALICE, 0u128), (BOB, 0u128), (MINTING_ACCOUNT, 0u128)], } .assimilate_storage(&mut t) .unwrap(); @@ -270,7 +266,7 @@ pub fn test_ext(add_iroha_accounts: bool) -> sp_io::TestExternalities { tokens::GenesisConfig:: { balances: vec![ - (ALICE, VAL, 0u128.into()), + (ALICE, VAL, 0u128), (eth_bridge_account_id, VAL, balance!(1000)), ], } @@ -279,7 +275,7 @@ pub fn test_ext(add_iroha_accounts: bool) -> sp_io::TestExternalities { technical::GenesisConfig:: { register_tech_accounts: vec![ - (MINTING_ACCOUNT, tech_account_id.clone()), + (MINTING_ACCOUNT, tech_account_id), (eth_bridge_account_id, eth_bridge_tech_account_id), ], } @@ -290,7 +286,7 @@ pub fn test_ext(add_iroha_accounts: bool) -> sp_io::TestExternalities { vec![ ( "did_sora_d9bda3688c6f608ab15c@sora".to_string(), - Balance::from(0u128), + 0u128, None, 1, vec![ @@ -299,7 +295,7 @@ pub fn test_ext(add_iroha_accounts: bool) -> sp_io::TestExternalities { ), ( "did_sora_balance@sora".to_string(), - Balance::from(300u128), + 300u128, None, 1, vec![ @@ -308,7 +304,7 @@ pub fn test_ext(add_iroha_accounts: bool) -> sp_io::TestExternalities { ), ( "did_sora_referral@sora".to_string(), - Balance::from(0u128), + 0u128, Some("did_sora_referrer@sora".to_string()), 1, vec![ @@ -317,7 +313,7 @@ pub fn test_ext(add_iroha_accounts: bool) -> sp_io::TestExternalities { ), ( "did_sora_referrer@sora".to_string(), - Balance::from(0u128), + 0u128, None, 1, vec![ @@ -326,7 +322,7 @@ pub fn test_ext(add_iroha_accounts: bool) -> sp_io::TestExternalities { ), ( "did_sora_multi_sig@sora".to_string(), - Balance::from(1000u128), + 1000u128, None, 2, vec![ diff --git a/pallets/iroha-migration/src/tests.rs b/pallets/iroha-migration/src/tests.rs index 8ef3c7328e..bf78124c81 100644 --- a/pallets/iroha-migration/src/tests.rs +++ b/pallets/iroha-migration/src/tests.rs @@ -30,7 +30,6 @@ use crate::mock::*; use crate::{Error, MigratedAccounts, Pallet, PendingMultiSigAccounts, PendingReferrals}; -use common::prelude::Balance; use common::{AssetInfoProvider, VAL}; use frame_support::assert_noop; use frame_support::assert_ok; @@ -84,13 +83,13 @@ fn test_already_migrated() { #[test] fn test_migrate_balance() { new_test_ext().execute_with(|| { - assert_eq!(Assets::free_balance(&VAL, &ALICE).unwrap(), Balance::from(0u128)); + assert_eq!(Assets::free_balance(&VAL, &ALICE).unwrap(), 0u128); assert_ok!(Pallet::::migrate( RuntimeOrigin::signed(ALICE), "did_sora_balance@sora".to_string(), "9a685d77bcd3f60e6cc1e91eedc7a48e11bbcf1a036b920f3bae0372a78A5432".to_string(), "233896712f752760713539f56c92534ff8f4f290812e8f129Ce0b513b99cbdffcea95abeed68edd1b0a4e4b52877c13c26c6c89e5bb6bf023ac6c0f4f53c0c02".to_string())); - assert_eq!(Assets::free_balance(&VAL, &ALICE).unwrap(), Balance::from(300u128)); + assert_eq!(Assets::free_balance(&VAL, &ALICE).unwrap(), 300u128); }); } @@ -106,8 +105,8 @@ fn test_migrate_referrer_migrates_first() { "did_sora_referral@sora".to_string(), "cba1c8c2eeaf287d734bd167b10d762e89c0ee8327a29e04f064ae94086ef1e9".to_string(), "dd878f4223026ad274212bf153a59fffff0a84a2ef5c40C60905b1fd2219508296eecd8f56618986352653757628e41fcaaab202cfe6cf3abcc28d7972a68e06".to_string())); - assert_eq!(Referrers::::get(&BOB), Some(ALICE)); - assert!(PendingReferrals::::get(&"did_sora_referrer@sora".to_string()).is_empty()); + assert_eq!(Referrers::::get(BOB), Some(ALICE)); + assert!(PendingReferrals::::get("did_sora_referrer@sora".to_string()).is_empty()); }); } @@ -119,13 +118,13 @@ fn test_migrate_referral_migrates_first() { "did_sora_referral@sora".to_string(), "cba1c8c2eeaf287d734bd167b10d762e89c0ee8327A29e04f064ae94086ef1e9".to_string(), "dd878f4223026ad274212bf153a59fffff0a84a2Ef5c40c60905b1fd2219508296eecd8f56618986352653757628e41fcaaab202cfe6cf3abcc28d7972a68e06".to_string())); - assert_eq!(PendingReferrals::::get(&"did_sora_referrer@sora".to_string()), vec![BOB]); + assert_eq!(PendingReferrals::::get("did_sora_referrer@sora".to_string()), vec![BOB]); assert_ok!(Pallet::::migrate( RuntimeOrigin::signed(ALICE), "did_sora_referrer@sora".to_string(), "dd54e9efb95531154316cf3e28e2232abab349296dDe94353febc9ebbb3ff283".to_string(), "f87bfa375cb4be3ee530ca6d76790b6aac9dbbbbff5dceb58021491a1d83526e31685c8d38f8c2dcb932939599ab4ff6733f0547c362322f1a51a666877ab003".to_string())); - assert_eq!(Referrers::::get(&BOB), Some(ALICE)); + assert_eq!(Referrers::::get(BOB), Some(ALICE)); }); } @@ -146,7 +145,7 @@ fn test_migrate_multi_sig() { signatories.sort(); pallet_multisig::Pallet::::multi_account_id(&signatories, 2) }; - assert_eq!(Assets::free_balance(&VAL, &multi_account).unwrap(), Balance::from(0u128)); + assert_eq!(Assets::free_balance(&VAL, &multi_account).unwrap(), 0u128); assert_ok!(Pallet::::migrate( RuntimeOrigin::signed(BOB), iroha_address.clone(), @@ -162,7 +161,7 @@ fn test_migrate_multi_sig() { ); assert!(MigratedAccounts::::contains_key(&iroha_address)); assert!(!PendingMultiSigAccounts::::contains_key(&iroha_address)); - assert_eq!(Assets::free_balance(&VAL, &multi_account).unwrap(), Balance::from(1000u128)); + assert_eq!(Assets::free_balance(&VAL, &multi_account).unwrap(), 1000u128); }); } @@ -189,8 +188,8 @@ fn test_migrate_multi_sig_after_timeout() { signatories.sort(); pallet_multisig::Pallet::::multi_account_id(&signatories, 2) }; - assert_eq!(Assets::free_balance(&VAL, &multi_account_of_2).unwrap(), Balance::from(0u128)); - assert_eq!(Assets::free_balance(&VAL, &multi_account_of_3).unwrap(), Balance::from(0u128)); + assert_eq!(Assets::free_balance(&VAL, &multi_account_of_2).unwrap(), 0u128); + assert_eq!(Assets::free_balance(&VAL, &multi_account_of_3).unwrap(), 0u128); assert_ok!(Pallet::::migrate( RuntimeOrigin::signed(BOB), @@ -201,19 +200,19 @@ fn test_migrate_multi_sig_after_timeout() { assert!(!MigratedAccounts::::contains_key(&iroha_address)); assert!(PendingMultiSigAccounts::::contains_key(&iroha_address)); - assert_eq!(Assets::free_balance(&VAL, &multi_account_of_2).unwrap(), Balance::from(0u128)); - assert_eq!(Assets::free_balance(&VAL, &multi_account_of_3).unwrap(), Balance::from(0u128)); + assert_eq!(Assets::free_balance(&VAL, &multi_account_of_2).unwrap(), 0u128); + assert_eq!(Assets::free_balance(&VAL, &multi_account_of_3).unwrap(), 0u128); Pallet::::on_initialize(crate::blocks_till_migration::() + 1); assert!(MigratedAccounts::::contains_key(&iroha_address)); assert!(!PendingMultiSigAccounts::::contains_key(&iroha_address)); - assert_eq!(Assets::free_balance(&VAL, &multi_account_of_2).unwrap(), Balance::from(1000u128)); - assert_eq!(Assets::free_balance(&VAL, &multi_account_of_3).unwrap(), Balance::from(0u128)); + assert_eq!(Assets::free_balance(&VAL, &multi_account_of_2).unwrap(), 1000u128); + assert_eq!(Assets::free_balance(&VAL, &multi_account_of_3).unwrap(), 0u128); assert_noop!(Pallet::::migrate( RuntimeOrigin::signed(CHARLIE), - iroha_address.clone(), + iroha_address, "57571ec82cff710143eba60c05d88de14a22799048137162d63C534a8b02dc20".to_string(), "3cfd2e95676ec7f4a7eb6f8bf91b447990c1bb4d771784e5e5D6027852eef75c13ad911d6fac9130b24f67e2088c3b908d25c092f87b77ed8a44dcd62572cc0f".to_string()), Error::::AccountAlreadyMigrated, @@ -235,7 +234,7 @@ fn test_migrate_multi_sig_public_key_already_used() { assert!(PendingMultiSigAccounts::::contains_key(&iroha_address)); assert_noop!(Pallet::::migrate( RuntimeOrigin::signed(ALICE), - iroha_address.clone(), + iroha_address, "f7d89d39d48a67e4741a612de10650234f9148e84fE9e8b2a9fad322b0d8e5bc".to_string(), "d5f6dcc6967aa05df71894dd2c253085b236026efC1c66d4b33ee88dda20fc751b516aef631d1f96919f8cba2e15334022e04ef6602298d6b9820daeefe13e03".to_string()), Error::::PublicKeyAlreadyUsed From 0d861dad12f3724aca6f51448ef40f288ae5074b Mon Sep 17 00:00:00 2001 From: Nikita Smirnov Date: Thu, 26 Oct 2023 19:15:36 +0200 Subject: [PATCH 05/11] liquidity-proxy clippy fixes --- pallets/liquidity-proxy/src/lib.rs | 154 ++++++----- pallets/liquidity-proxy/src/mock.rs | 55 ++-- pallets/liquidity-proxy/src/test_utils.rs | 8 +- pallets/liquidity-proxy/src/tests.rs | 321 +++++++++++----------- 4 files changed, 268 insertions(+), 270 deletions(-) diff --git a/pallets/liquidity-proxy/src/lib.rs b/pallets/liquidity-proxy/src/lib.rs index ad6d4786e9..875f3273a9 100644 --- a/pallets/liquidity-proxy/src/lib.rs +++ b/pallets/liquidity-proxy/src/lib.rs @@ -29,8 +29,6 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] extern crate core; @@ -247,7 +245,7 @@ impl Pallet { pub fn is_forbidden_filter( input_asset_id: &T::AssetId, output_asset_id: &T::AssetId, - selected_source_types: &Vec, + selected_source_types: &[LiquiditySourceType], filter_mode: &FilterMode, ) -> bool { let tbc_reserve_assets = T::PrimaryMarketTBC::enabled_target_assets(); @@ -255,10 +253,7 @@ impl Pallet { #[allow(unused_mut)] // order-book #[allow(unused_assignments)] // order-book // TODO remake - let mut is_order_book = match filter_mode { - FilterMode::ForbidSelected => true, - _ => false, - }; + let mut is_order_book = matches!(filter_mode, FilterMode::ForbidSelected); #[cfg(feature = "wip")] // order-book { @@ -299,6 +294,7 @@ impl Pallet { Ok(()) } + #[allow(clippy::too_many_arguments)] pub fn inner_swap( sender: T::AccountId, receiver: T::AccountId, @@ -360,6 +356,7 @@ impl Pallet { /// Those individual swaps are subject to liquidity aggregation algorithm. /// /// This a wrapper for `exchange_single`. + #[allow(clippy::type_complexity)] pub fn inner_exchange( dex_id: T::DEXId, sender: &T::AccountId, @@ -391,6 +388,7 @@ impl Pallet { /// Exchange sequence of assets, where each pair is a direct exchange. /// The swaps path is selected via `select_best_path` + #[allow(clippy::type_complexity)] fn exchange_sequence( dex_info: &DEXInfo, sender: &T::AccountId, @@ -460,9 +458,9 @@ impl Pallet { input_amount, filter, ) - .and_then(|(mut swap, sources, weight)| { + .map(|(mut swap, sources, weight)| { swap.amount = input_amount; - Ok((swap, sources, quote_weight.saturating_add(weight))) + (swap, sources, quote_weight.saturating_add(weight)) }) } } @@ -471,6 +469,7 @@ impl Pallet { /// Exchange sequence of assets using input amount. /// /// Performs [`Self::exchange_single()`] for each pair of assets and aggregates the results. + #[allow(clippy::type_complexity)] fn exchange_sequence_with_input_amount( dex_info: &DEXInfo, sender: &T::AccountId, @@ -567,8 +566,8 @@ impl Pallet { .map(|(from, to)| -> Result<_, DispatchError> { let (quote, _, _, weight) = Self::quote_single( &dex_info.base_asset_id, - &from, - &to, + from, + to, QuoteAmount::with_desired_output(amount), filter.clone(), true, @@ -583,6 +582,7 @@ impl Pallet { } /// Performs a swap given a number of liquidity sources and a distribution of the swap amount across the sources. + #[allow(clippy::type_complexity)] fn exchange_single( sender: &T::AccountId, receiver: &T::AccountId, @@ -654,6 +654,7 @@ impl Pallet { /// Those individual swaps are subject to liquidity aggregation algorithm. /// /// This a wrapper for `quote_single`. + #[allow(clippy::type_complexity)] pub fn inner_quote( dex_id: T::DEXId, input_asset_id: &T::AssetId, @@ -678,6 +679,7 @@ impl Pallet { /// Quote sequence of assets, where each pair is a direct exchange. /// Selects swaps path via `select_best_path` + #[allow(clippy::type_complexity)] fn quote_sequence( dex_info: &DEXInfo, asset_paths: Vec>, @@ -715,6 +717,7 @@ impl Pallet { /// `QuoteAmount::WithDesiredOutput` /// /// Returns Result containing a quote result and the selected path + #[allow(clippy::type_complexity)] fn select_best_path( dex_info: &DEXInfo, asset_paths: Vec>, @@ -786,6 +789,7 @@ impl Pallet { /// Quote given pairs of assets using `amount_ctr` to construct [`QuoteAmount`] for each pair. /// /// Performs [`Self::quote_single()`] for each pair and aggregates the results. + #[allow(clippy::type_complexity)] fn quote_pairs_with_flexible_amount<'asset, F: Fn(Balance) -> QuoteAmount>( dex_info: &DEXInfo, asset_pairs: impl Iterator, @@ -881,13 +885,14 @@ impl Pallet { // Would likely to fail if operating near the limits, // because it uses i128 for fixed-point arithmetics. // TODO: switch to unsigned internal representation + #[allow(clippy::type_complexity)] fn calculate_amount_without_impact( input_asset_id: &T::AssetId, output_asset_id: &T::AssetId, - distribution: &Vec<( + distribution: &[( LiquiditySourceId, QuoteAmount, - )>, + )], outcome_amount: u128, outcome_without_impact: u128, deduce_fee: bool, @@ -919,7 +924,7 @@ impl Pallet { // multiply all amounts in distribution to adjust prev quote without impact: let distribution = distribution - .into_iter() + .iter() .filter(|(_, part_amount)| part_amount.amount() > balance!(0)) .map(|(market, amount)| { // Should not overflow unless the amounts are comparable to 10^38 . @@ -966,6 +971,7 @@ impl Pallet { /// - `filter` - a filter composed of a list of liquidity sources IDs to accept or ban for this trade. /// - `skip_info` - flag that indicates that additional info should not be shown, that is needed when actual exchange is performed. /// + #[allow(clippy::type_complexity)] fn quote_single( base_asset_id: &T::AssetId, input_asset_id: &T::AssetId, @@ -1004,7 +1010,7 @@ impl Pallet { src, input_asset_id, output_asset_id, - amount.into(), + amount, deduce_fee, )?; total_weight = total_weight.saturating_add(weight); @@ -1064,7 +1070,7 @@ impl Pallet { base_asset_id, input_asset_id, output_asset_id, - amount.clone(), + amount, skip_info, deduce_fee, )?; @@ -1105,7 +1111,7 @@ impl Pallet { path.iter() .tuple_windows() .filter_map(|(from, to)| { - let pair = Self::weak_sort_pair(&dex_info, *from, *to); + let pair = Self::weak_sort_pair(dex_info, *from, *to); // TODO: #441 use TradingPairSourceManager instead of trading-pair pallet trading_pair::Pallet::::list_enabled_sources_for_trading_pair( @@ -1126,11 +1132,11 @@ impl Pallet { ) -> Result, DispatchError> { let sources_set = fallible_iterator::convert(path.to_vec().iter().tuple_windows().map( |(from, to)| -> Result<_, DispatchError> { - let pair = Self::weak_sort_pair(&dex_info, *from, *to); + let pair = Self::weak_sort_pair(dex_info, *from, *to); // TODO: #441 use TradingPairSourceManager instead of trading-pair pallet let sources = trading_pair::Pallet::::list_enabled_sources_for_trading_pair( - &dex_id, + dex_id, &pair.base_asset_id, &pair.target_asset_id, )?; @@ -1231,7 +1237,7 @@ impl Pallet { let mut weights = Vec::new(); for path in trivial_path { - if path.0.len() > 0 { + if !path.0.is_empty() { let total_exchange_weight = exchange_weight.saturating_mul(path.0.len() as u64 - 1); weights.push( weight @@ -1266,11 +1272,9 @@ impl Pallet { let inner_exchange_weight = Self::inner_exchange_weight(dex_id, input, output, swap_variant); - let weight = ::WeightInfo::check_indivisible_assets() + ::WeightInfo::check_indivisible_assets() .saturating_add(::WeightInfo::is_forbidden_filter()) - .saturating_add(inner_exchange_weight); - - weight + .saturating_add(inner_exchange_weight) } /// Calculates the max potential weight of swap_transfer_batch @@ -1421,6 +1425,8 @@ impl Pallet { /// - `amount` - the amount with "direction" (sell or buy) together with the maximum price impact (slippage). /// - `skip_info` - flag that indicates that additional info should not be shown, that is needed when actual exchange is performed. /// + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] fn smart_split( primary_source_id: &LiquiditySourceIdOf, secondary_source_id: &LiquiditySourceIdOf, @@ -1479,7 +1485,7 @@ impl Pallet { Self::decide_primary_market_amount_buying_base_asset( base_asset_id, other_asset, - amount.clone(), + amount, (reserves_base, reserves_other), ) .unwrap_or( @@ -1491,7 +1497,7 @@ impl Pallet { Self::decide_primary_market_amount_selling_base_asset( base_asset_id, other_asset, - amount.clone(), + amount, (reserves_base, reserves_other), ) .unwrap_or(amount.copy_direction(balance!(0))) @@ -1515,7 +1521,7 @@ impl Pallet { primary_source_id, input_asset_id, output_asset_id, - amount_primary.clone(), + amount_primary, deduce_fee, ) .and_then(|(outcome_primary, weight)| { @@ -1528,10 +1534,10 @@ impl Pallet { secondary_source_id, input_asset_id, output_asset_id, - amount_secondary.clone(), + amount_secondary, deduce_fee, ) - .and_then(|(outcome_secondary, weight)| { + .map(|(outcome_secondary, weight)| { total_weight = total_weight.saturating_add(weight); if !skip_info { for info in vec![ @@ -1563,7 +1569,6 @@ impl Pallet { (primary_source_id.clone(), amount_primary), (secondary_source_id.clone(), amount_secondary), ]; - Ok(()) }) } else { best = outcome_primary.amount; @@ -1583,18 +1588,17 @@ impl Pallet { secondary_source_id, input_asset_id, output_asset_id, - amount.clone(), + amount, deduce_fee, ) - .and_then(|(outcome, weight)| { + .map(|(outcome, weight)| { total_weight = total_weight.saturating_add(weight); if is_better(outcome.amount, best) { best = outcome.amount; total_fee = outcome.fee; - distr = vec![(secondary_source_id.clone(), amount.clone())]; + distr = vec![(secondary_source_id.clone(), amount)]; if !skip_info { - let (input_amount, output_amount) = - amount.place_input_and_output(outcome.clone()); + let (input_amount, output_amount) = amount.place_input_and_output(outcome); let reward_weight; (rewards, reward_weight) = T::LiquidityRegistry::check_rewards( secondary_source_id, @@ -1607,7 +1611,6 @@ impl Pallet { total_weight = total_weight.saturating_add(reward_weight); }; }; - Ok(()) }); // Check if we have got a result at either of the steps @@ -1829,13 +1832,14 @@ impl Pallet { /// Swaps tokens for the following batch distribution and calculates a remainder. /// Remainder is used due to inaccuracy of the quote calculation. + #[allow(clippy::too_many_arguments)] fn exchange_batch_tokens( sender: &T::AccountId, num_of_receivers: u128, input_asset_id: &T::AssetId, output_asset_id: &T::AssetId, max_input_amount: Balance, - selected_source_types: &Vec, + selected_source_types: &[LiquiditySourceType], dex_id: T::DEXId, filter_mode: &FilterMode, out_amount: Balance, @@ -1846,14 +1850,14 @@ impl Pallet { let filter = LiquiditySourceFilter::with_mode( dex_id, filter_mode.clone(), - selected_source_types.clone(), + selected_source_types.to_vec(), ); if Self::is_forbidden_filter( - &input_asset_id, - &output_asset_id, - &selected_source_types, - &filter_mode, + input_asset_id, + output_asset_id, + selected_source_types, + filter_mode, ) { fail!(Error::::ForbiddenFilter); } @@ -1869,23 +1873,23 @@ impl Pallet { weights, ) = Self::inner_exchange( dex_id, - &sender, - &sender, - &input_asset_id, - &output_asset_id, + sender, + sender, + input_asset_id, + output_asset_id, SwapAmount::WithDesiredOutput { desired_amount_out: out_amount, max_amount_in: max_input_amount, }, - filter.clone(), + filter, )?; total_weight = total_weight.saturating_add(weights); Self::deposit_event(Event::::Exchange( sender.clone(), dex_id, - input_asset_id.clone(), - output_asset_id.clone(), + *input_asset_id, + *output_asset_id, executed_input_amount, out_amount, fee_amount, @@ -1893,7 +1897,7 @@ impl Pallet { )); let caller_output_asset_balance = - assets::Pallet::::total_balance(&output_asset_id, &sender)?; + assets::Pallet::::total_balance(output_asset_id, sender)?; let remainder_per_receiver: Balance = if caller_output_asset_balance < out_amount { let remainder = out_amount.saturating_sub(caller_output_asset_balance); remainder / num_of_receivers + remainder % num_of_receivers @@ -1910,18 +1914,16 @@ impl Pallet { remainder_per_receiver: Balance, ) -> Result { let len = receivers.len(); - fallible_iterator::convert(receivers.into_iter().map(|val| Ok(val))).for_each( - |receiver| { - assets::Pallet::::transfer_from( - &output_asset_id, - &sender, - &receiver.account_id, - receiver - .target_amount - .saturating_sub(remainder_per_receiver), - ) - }, - )?; + fallible_iterator::convert(receivers.into_iter().map(Ok)).for_each(|receiver| { + assets::Pallet::::transfer_from( + output_asset_id, + sender, + &receiver.account_id, + receiver + .target_amount + .saturating_sub(remainder_per_receiver), + ) + })?; Ok(::WeightInfo::transfer().saturating_mul(len as u64)) } @@ -1940,7 +1942,7 @@ impl Pallet { input_asset_id: &T::AssetId, swap_batches: Vec>, mut max_input_amount: Balance, - selected_source_types: &Vec, + selected_source_types: &[LiquiditySourceType], filter_mode: &FilterMode, ) -> Result<(Balance, Balance, Weight), DispatchError> { let mut unique_asset_ids: BTreeSet = BTreeSet::new(); @@ -1949,7 +1951,7 @@ impl Pallet { let mut total_weight = Weight::zero(); - fallible_iterator::convert(swap_batches.into_iter().map(|val| Ok(val))).for_each( + fallible_iterator::convert(swap_batches.into_iter().map(Ok)).for_each( |swap_batch_info| { let SwapBatchInfo { outcome_asset_id: asset_id, @@ -1958,18 +1960,18 @@ impl Pallet { outcome_asset_reuse, } = swap_batch_info; - let balance = assets::Pallet::::free_balance(&asset_id, &sender)?; + let balance = assets::Pallet::::free_balance(&asset_id, sender)?; if balance < outcome_asset_reuse { fail!(Error::::InsufficientBalance); } // extrinsic fails if there are duplicate output asset ids - if !unique_asset_ids.insert(asset_id.clone()) { + if !unique_asset_ids.insert(asset_id) { fail!(Error::::AggregationError); } - if receivers.len() == 0 { + if receivers.is_empty() { fail!(Error::::InvalidReceiversInfo); } @@ -1987,14 +1989,14 @@ impl Pallet { ) = if &asset_id != input_asset_id { if !out_amount.is_zero() { Self::exchange_batch_tokens( - &sender, + sender, receivers.len() as u128, - &input_asset_id, + input_asset_id, &asset_id, max_input_amount, - &selected_source_types, + selected_source_types, dex_id, - &filter_mode, + filter_mode, out_amount, )? } else { @@ -2014,7 +2016,7 @@ impl Pallet { .ok_or(Error::::SlippageNotTolerated)?; let transfer_weight = Self::transfer_batch_tokens_unchecked( - &sender, + sender, &asset_id, receivers, remainder_per_receiver, @@ -2115,6 +2117,10 @@ impl SwapBatchInfo { pub fn len(&self) -> usize { self.receivers.len() } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } pub struct LiquidityProxyBuyBackHandler(PhantomData<(T, GetDEXId)>); @@ -2127,7 +2133,7 @@ impl> BuyBackHandler Result { - let owner = assets::Pallet::::asset_owner(&mint_asset_id) + let owner = assets::Pallet::::asset_owner(mint_asset_id) .ok_or(assets::Error::::AssetIdNotExists)?; let transit = T::GetTechnicalAccountId::get(); assets::Pallet::::mint_to(mint_asset_id, &owner, &transit, amount)?; @@ -2188,6 +2194,7 @@ impl, GetReferenceAssetId: Get> } } +#[allow(clippy::too_many_arguments)] #[frame_support::pallet] pub mod pallet { use super::*; @@ -2236,6 +2243,7 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet {} + #[allow(clippy::too_many_arguments)] #[pallet::call] impl Pallet { /// Perform swap of tokens (input/output defined via SwapAmount direction). diff --git a/pallets/liquidity-proxy/src/mock.rs b/pallets/liquidity-proxy/src/mock.rs index fdfe5199cc..e86ff96877 100644 --- a/pallets/liquidity-proxy/src/mock.rs +++ b/pallets/liquidity-proxy/src/mock.rs @@ -41,7 +41,7 @@ use currencies::BasicCurrencyAdapter; use frame_support::traits::{Everything, GenesisBuild}; use frame_support::weights::Weight; use frame_support::{construct_runtime, ensure, fail, parameter_types}; -use frame_system; + use traits::MultiCurrency; use common::prelude::{Balance, FixedWrapper, QuoteAmount, SwapAmount, SwapOutcome}; @@ -96,18 +96,17 @@ parameter_types! { pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub GetLiquidityProxyTechAccountId: TechAccountId = { - let tech_account_id = TechAccountId::from_generic_pair( + + TechAccountId::from_generic_pair( crate::TECH_ACCOUNT_PREFIX.to_vec(), crate::TECH_ACCOUNT_MAIN.to_vec(), - ); - tech_account_id + ) }; pub GetLiquidityProxyAccountId: AccountId = { let tech_account_id = GetLiquidityProxyTechAccountId::get(); - let account_id = - technical::Pallet::::tech_account_id_to_account_id(&tech_account_id) - .expect("Failed to get ordinary account id for technical account id."); - account_id + + technical::Pallet::::tech_account_id_to_account_id(&tech_account_id) + .expect("Failed to get ordinary account id for technical account id.") }; pub const GetNumSamples: usize = 40; pub const GetBaseAssetId: AssetId = XOR; @@ -117,7 +116,7 @@ parameter_types! { pub GetFee10: Fixed = fixed_from_basis_points(10u16); pub GetFee20: Fixed = fixed_from_basis_points(20u16); pub GetFee30: Fixed = fixed_from_basis_points(30u16); - pub GetIncentiveAssetId: AssetId = common::PSWAP.into(); + pub GetIncentiveAssetId: AssetId = common::PSWAP; pub GetPswapDistributionAccountId: AccountId = AccountId32::from([151; 32]); pub const GetDefaultSubscriptionFrequency: BlockNumber = 10; pub const GetBurnUpdateFrequency: BlockNumber = 14400; @@ -605,7 +604,7 @@ impl MockMCBCPool { impl LiquiditySource for MockMCBCPool { fn can_exchange(_dex_id: &DEXId, _input_asset_id: &AssetId, output_asset_id: &AssetId) -> bool { - if output_asset_id == &XOR.into() { + if output_asset_id == &XOR { return true; } let reserves_tech_account_id = @@ -639,7 +638,7 @@ impl LiquiditySource for Mock Currencies::free_balance(*output_asset_id, &reserves_account_id).into(); let buy_spot_price: FixedWrapper = Self::_spot_price(output_asset_id).into(); let sell_spot_price: FixedWrapper = buy_spot_price.clone() * fixed_wrapper!(0.8); - let pretended_base_reserves = collateral_reserves.clone() / sell_spot_price.clone(); + let pretended_base_reserves = collateral_reserves.clone() / sell_spot_price; let ideal_reserves: FixedWrapper = (buy_spot_price + get_initial_price() @@ -662,7 +661,7 @@ impl LiquiditySource for Mock } => { let input_wrapped: FixedWrapper = desired_amount_in.into(); let input_after_fee: FixedWrapper = - input_wrapped * (fixed_wrapper!(1) - extra_fee.clone()); + input_wrapped * (fixed_wrapper!(1) - extra_fee); let output_collateral = (input_after_fee.clone() * collateral_reserves) / (pretended_base_reserves + input_after_fee); let output_amount: Balance = output_collateral.try_into_balance().unwrap(); @@ -754,7 +753,7 @@ impl LiquiditySource for Mock Ok(( vec![( output_amount, - output_asset_id.clone(), + *output_asset_id, RewardReason::BuyOnBondingCurve, )], Weight::zero(), @@ -993,28 +992,22 @@ impl ExtBuilder { for (dex_id, asset, (base_reserve, asset_reserve)) in self.xyk_reserves { let mint_amount: Balance = asset_reserve * 2; - trading_pair::Pallet::::register( - owner_origin.clone(), - dex_id.into(), - XOR.into(), - asset.into(), - ) - .unwrap(); - assets::Pallet::::mint_to(&asset.into(), &owner, &owner, mint_amount) + trading_pair::Pallet::::register(owner_origin.clone(), dex_id, XOR, asset) .unwrap(); + assets::Pallet::::mint_to(&asset, &owner, &owner, mint_amount).unwrap(); pool_xyk::Pallet::::initialize_pool( owner_origin.clone(), - dex_id.into(), - XOR.into(), - asset.into(), + dex_id, + XOR, + asset, ) .unwrap(); if asset_reserve != balance!(0) && base_reserve != balance!(0) { pool_xyk::Pallet::::deposit_liquidity( owner_origin.clone(), - dex_id.into(), - XOR.into(), - asset.into(), + dex_id, + XOR, + asset, base_reserve, asset_reserve, balance!(1), @@ -1046,12 +1039,10 @@ impl MockXSTPool { impl LiquiditySource for MockXSTPool { fn can_exchange(_dex_id: &DEXId, input_asset_id: &AssetId, output_asset_id: &AssetId) -> bool { - if output_asset_id == &XST.into() && input_asset_id == &XSTUSD.into() { - return true; - } else if input_asset_id == &XST.into() && output_asset_id == &XSTUSD.into() { - return true; + if output_asset_id == &XST && input_asset_id == &XSTUSD { + true } else { - return false; + input_asset_id == &XST && output_asset_id == &XSTUSD } } diff --git a/pallets/liquidity-proxy/src/test_utils.rs b/pallets/liquidity-proxy/src/test_utils.rs index 5ea439fa35..c5b52d7efa 100644 --- a/pallets/liquidity-proxy/src/test_utils.rs +++ b/pallets/liquidity-proxy/src/test_utils.rs @@ -78,7 +78,7 @@ pub fn check_swap_batch_executed_amount( } pub fn check_adar_commission( - swap_batches: &Vec, DEXId, AccountId>>, + swap_batches: &[SwapBatchInfo, DEXId, AccountId>], sources: Vec, ) { let actual_input_amount = calculate_swap_batch_input_amount(swap_batches, sources); @@ -93,7 +93,7 @@ pub fn check_adar_commission( } pub fn calculate_swap_batch_input_amount( - swap_batches: &Vec, DEXId, AccountId>>, + swap_batches: &[SwapBatchInfo, DEXId, AccountId>], sources: Vec, ) -> Balance { let actual_input_amount: Balance = swap_batches @@ -105,7 +105,7 @@ pub fn calculate_swap_batch_input_amount( dex_id, outcome_asset_reuse, .. - } = batch.clone(); + } = batch; let target_amount = batch .receivers .into_iter() @@ -131,7 +131,7 @@ pub fn calculate_swap_batch_input_amount( } pub fn calculate_swap_batch_input_amount_with_adar_commission( - swap_batches: &Vec, DEXId, AccountId>>, + swap_batches: &[SwapBatchInfo, DEXId, AccountId>], sources: Vec, ) -> Balance { let amount_in = calculate_swap_batch_input_amount(swap_batches, sources); diff --git a/pallets/liquidity-proxy/src/tests.rs b/pallets/liquidity-proxy/src/tests.rs index 7cecd02e88..f10a6013c9 100644 --- a/pallets/liquidity-proxy/src/tests.rs +++ b/pallets/liquidity-proxy/src/tests.rs @@ -385,7 +385,7 @@ fn test_poly_quote_exact_output_1_should_pass() { &alice(), &KSM, &DOT, - SwapAmount::with_desired_output(balance!(934.572151021276260545), balance!(101)).into(), + SwapAmount::with_desired_output(balance!(934.572151021276260545), balance!(101)), LiquiditySourceFilter::empty(DEX_A_ID), ) .expect("Failed to swap via LiquiditySource trait"); @@ -483,7 +483,7 @@ fn test_poly_quote_exact_output_2_should_pass() { &alice(), &DOT, &KSM, - SwapAmount::with_desired_output(balance!(555.083861089846196673), balance!(501)).into(), + SwapAmount::with_desired_output(balance!(555.083861089846196673), balance!(501)), LiquiditySourceFilter::empty(DEX_A_ID), ) .expect("Failed to swap via LiquiditySource trait"); @@ -1036,7 +1036,7 @@ fn test_quote_fast_split_exact_input_base_should_pass() { &GetBaseAssetId::get(), &DOT, QuoteAmount::with_desired_input(balance!(200)), - filter.clone(), + filter, false, true, ) @@ -1147,7 +1147,7 @@ fn test_quote_fast_split_exact_output_target_should_pass() { &GetBaseAssetId::get(), &DOT, QuoteAmount::with_desired_output(balance!(1000)), - filter.clone(), + filter, false, true, ) @@ -1201,7 +1201,7 @@ fn test_quote_fast_split_exact_output_base_should_pass() { rewards, vec![( balance!(23.258770902877438466), - XOR.into(), + XOR, RewardReason::BuyOnBondingCurve )] ); @@ -1264,7 +1264,7 @@ fn test_quote_fast_split_exact_output_base_should_pass() { &DOT, &GetBaseAssetId::get(), QuoteAmount::with_desired_output(balance!(100)), - filter.clone(), + filter, false, true, ) @@ -1327,7 +1327,7 @@ fn test_quote_fast_split_exact_input_target_should_pass() { rewards, vec![( balance!(14.388332979612791988), - XOR.into(), + XOR, RewardReason::BuyOnBondingCurve )] ); @@ -1390,7 +1390,7 @@ fn test_quote_fast_split_exact_input_target_should_pass() { &DOT, &GetBaseAssetId::get(), QuoteAmount::with_desired_input(balance!(500)), - filter.clone(), + filter, false, true, ) @@ -1497,7 +1497,7 @@ fn test_quote_fast_split_exact_output_target_undercollateralized_should_pass() { &GetBaseAssetId::get(), &DOT, QuoteAmount::with_desired_output(balance!(1000)), - filter.clone(), + filter, false, true, ) @@ -1544,7 +1544,7 @@ fn test_quote_should_return_rewards_for_single_source() { &GetBaseAssetId::get(), &VAL, QuoteAmount::with_desired_output(balance!(100)), - filter.clone(), + filter, false, true, ) @@ -1553,7 +1553,7 @@ fn test_quote_should_return_rewards_for_single_source() { // Mock tbc defined reward as output token amount. assert_eq!( rewards_forward, - vec![(balance!(100), XOR.into(), RewardReason::BuyOnBondingCurve)] + vec![(balance!(100), XOR, RewardReason::BuyOnBondingCurve)] ); assert_eq!(rewards_backward, vec![]); }); @@ -1570,10 +1570,10 @@ fn test_quote_should_return_rewards_for_multiple_sources() { ]) .build(); ext.execute_with(|| { - MockLiquiditySource::add_reward((balance!(101), PSWAP.into(), RewardReason::Unspecified)); - MockLiquiditySource2::add_reward((balance!(201), VAL.into(), RewardReason::Unspecified)); - MockLiquiditySource2::add_reward((balance!(202), XOR.into(), RewardReason::Unspecified)); - MockLiquiditySource3::add_reward((balance!(301), DOT.into(), RewardReason::Unspecified)); + MockLiquiditySource::add_reward((balance!(101), PSWAP, RewardReason::Unspecified)); + MockLiquiditySource2::add_reward((balance!(201), VAL, RewardReason::Unspecified)); + MockLiquiditySource2::add_reward((balance!(202), XOR, RewardReason::Unspecified)); + MockLiquiditySource3::add_reward((balance!(301), DOT, RewardReason::Unspecified)); let amount: Balance = balance!(500); let QuoteInfo { rewards, .. } = LiquidityProxy::inner_quote( @@ -1591,10 +1591,10 @@ fn test_quote_should_return_rewards_for_multiple_sources() { assert_eq!( rewards, vec![ - (balance!(101), PSWAP.into(), RewardReason::Unspecified), - (balance!(201), VAL.into(), RewardReason::Unspecified), - (balance!(202), XOR.into(), RewardReason::Unspecified), - (balance!(301), DOT.into(), RewardReason::Unspecified), + (balance!(101), PSWAP, RewardReason::Unspecified), + (balance!(201), VAL, RewardReason::Unspecified), + (balance!(202), XOR, RewardReason::Unspecified), + (balance!(301), DOT, RewardReason::Unspecified), ] ); }); @@ -1626,8 +1626,7 @@ fn test_quote_should_work_for_synthetics() { false, true, ) - .expect(&format!("Failed to get a quote for {}-{} pair", from, to)) - .0; + .unwrap_or_else(|_| panic!("Failed to get a quote for {}-{} pair", from, to)); } }); } @@ -1746,12 +1745,12 @@ fn test_is_path_available_should_pass_1() { TradingPair::register(RuntimeOrigin::signed(alice()), 0, XOR, PSWAP).expect("failed to register pair"); TradingPair::enable_source_for_trading_pair(&0, &XOR, &VAL, XYKPool).expect("failed to enable source"); TradingPair::enable_source_for_trading_pair(&0, &XOR, &PSWAP, MulticollateralBondingCurvePool).expect("failed to enable source"); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, PSWAP).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, PSWAP, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, PSWAP, VAL).unwrap(), true); + assert!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap()); + assert!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XOR, PSWAP).unwrap()); + assert!(LiquidityProxy::is_path_available(0, PSWAP, XOR).unwrap()); + assert!(LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap()); + assert!(LiquidityProxy::is_path_available(0, PSWAP, VAL).unwrap()); }); } @@ -1764,12 +1763,12 @@ fn test_is_path_available_should_pass_2() { TradingPair::register(RuntimeOrigin::signed(alice()), 0, XOR, VAL).expect("failed to register pair"); TradingPair::register(RuntimeOrigin::signed(alice()), 0, XOR, PSWAP).expect("failed to register pair"); TradingPair::enable_source_for_trading_pair(&0, &XOR, &PSWAP, MulticollateralBondingCurvePool).expect("failed to enable source"); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap(), false); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap(), false); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, PSWAP).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, PSWAP, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap(), false); - assert_eq!(LiquidityProxy::is_path_available(0, PSWAP, VAL).unwrap(), false); + assert!(!LiquidityProxy::is_path_available(0, XOR, VAL).unwrap()); + assert!(!LiquidityProxy::is_path_available(0, VAL, XOR).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XOR, PSWAP).unwrap()); + assert!(LiquidityProxy::is_path_available(0, PSWAP, XOR).unwrap()); + assert!(!LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap()); + assert!(!LiquidityProxy::is_path_available(0, PSWAP, VAL).unwrap()); }); } @@ -1783,12 +1782,12 @@ fn test_is_path_available_should_pass_3() { TradingPair::register(RuntimeOrigin::signed(alice()), 0, XOR, PSWAP).expect("failed to register pair"); TradingPair::enable_source_for_trading_pair(&0, &XOR, &VAL, XYKPool).expect("failed to enable source"); TradingPair::enable_source_for_trading_pair(&0, &XOR, &VAL, MulticollateralBondingCurvePool).expect("failed to enable source"); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, PSWAP).unwrap(), false); - assert_eq!(LiquidityProxy::is_path_available(0, PSWAP, XOR).unwrap(), false); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap(), false); - assert_eq!(LiquidityProxy::is_path_available(0, PSWAP, VAL).unwrap(), false); + assert!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap()); + assert!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap()); + assert!(!LiquidityProxy::is_path_available(0, XOR, PSWAP).unwrap()); + assert!(!LiquidityProxy::is_path_available(0, PSWAP, XOR).unwrap()); + assert!(!LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap()); + assert!(!LiquidityProxy::is_path_available(0, PSWAP, VAL).unwrap()); }); } @@ -1803,12 +1802,12 @@ fn test_is_path_available_should_pass_4() { TradingPair::enable_source_for_trading_pair(&0, &XOR, &VAL, XYKPool).expect("failed to enable source"); TradingPair::enable_source_for_trading_pair(&0, &XOR, &PSWAP, XYKPool).expect("failed to enable source"); TradingPair::enable_source_for_trading_pair(&0, &XOR, &PSWAP, MulticollateralBondingCurvePool).expect("failed to enable source"); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, PSWAP).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, PSWAP, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, PSWAP, VAL).unwrap(), true); + assert!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap()); + assert!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XOR, PSWAP).unwrap()); + assert!(LiquidityProxy::is_path_available(0, PSWAP, XOR).unwrap()); + assert!(LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap()); + assert!(LiquidityProxy::is_path_available(0, PSWAP, VAL).unwrap()); }); } @@ -1820,7 +1819,7 @@ fn test_is_path_available_should_pass_5() { use LiquiditySourceType::*; assets::Pallet::::register_asset_id( alice(), - XST.into(), + XST, AssetSymbol(b"XST".to_vec()), AssetName(b"SORA Synthetics".to_vec()), 0, @@ -1831,7 +1830,7 @@ fn test_is_path_available_should_pass_5() { ).expect("failed to register XST asset"); assets::Pallet::::register_asset_id( alice(), - XSTUSD.into(), + XSTUSD, AssetSymbol(b"XSTUSD".to_vec()), AssetName(b"SORA Synthetic USD".to_vec()), 0, @@ -1848,19 +1847,19 @@ fn test_is_path_available_should_pass_5() { TradingPair::enable_source_for_trading_pair(&0, &XOR, &PSWAP, XYKPool).expect("failed to enable source"); TradingPair::enable_source_for_trading_pair(&0, &XOR, &XST, XYKPool).expect("failed to enable source"); TradingPair::enable_source_for_trading_pair(&0, &XST, &XSTUSD, XSTPool).expect("failed to enable source"); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, XST).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, VAL, XSTUSD).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, XST).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XOR, XSTUSD).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XST, XSTUSD).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XST, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XST, VAL).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XSTUSD, XST).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XSTUSD, XOR).unwrap(), true); - assert_eq!(LiquidityProxy::is_path_available(0, XSTUSD, VAL).unwrap(), true); + assert!(LiquidityProxy::is_path_available(0, VAL, PSWAP).unwrap()); + assert!(LiquidityProxy::is_path_available(0, VAL, XOR).unwrap()); + assert!(LiquidityProxy::is_path_available(0, VAL, XST).unwrap()); + assert!(LiquidityProxy::is_path_available(0, VAL, XSTUSD).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XOR, VAL).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XOR, XST).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XOR, XSTUSD).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XST, XSTUSD).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XST, XOR).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XST, VAL).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XSTUSD, XST).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XSTUSD, XOR).unwrap()); + assert!(LiquidityProxy::is_path_available(0, XSTUSD, VAL).unwrap()); }); } @@ -1874,7 +1873,7 @@ fn test_smart_split_with_extreme_total_supply_works() { ) { let mut ext = ExtBuilder::with_total_supply_and_reserves( total_supply, - vec![(0, collateral_asset_id, xyk_pool_reserves.clone())], + vec![(0, collateral_asset_id, xyk_pool_reserves)], ) .build(); ext.execute_with(|| { @@ -1903,7 +1902,7 @@ fn test_smart_split_with_extreme_total_supply_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_input(amount_base.clone()), + QuoteAmount::with_desired_input(amount_base), filter_both.clone(), false, true, @@ -1913,7 +1912,7 @@ fn test_smart_split_with_extreme_total_supply_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_input(amount_base.clone()), + QuoteAmount::with_desired_input(amount_base), filter_xyk.clone(), false, true, @@ -1926,7 +1925,7 @@ fn test_smart_split_with_extreme_total_supply_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_output(amount_base.clone()), + QuoteAmount::with_desired_output(amount_base), filter_both.clone(), false, true, @@ -1936,7 +1935,7 @@ fn test_smart_split_with_extreme_total_supply_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_output(amount_base.clone()), + QuoteAmount::with_desired_output(amount_base), filter_xyk.clone(), false, true, @@ -1949,7 +1948,7 @@ fn test_smart_split_with_extreme_total_supply_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_input(amount_collateral.clone()), + QuoteAmount::with_desired_input(amount_collateral), filter_both.clone(), false, true, @@ -1959,7 +1958,7 @@ fn test_smart_split_with_extreme_total_supply_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_input(amount_collateral.clone()), + QuoteAmount::with_desired_input(amount_collateral), filter_xyk.clone(), false, true, @@ -1972,8 +1971,8 @@ fn test_smart_split_with_extreme_total_supply_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_output(amount_collateral.clone()), - filter_both.clone(), + QuoteAmount::with_desired_output(amount_collateral), + filter_both, false, true, ) @@ -1982,8 +1981,8 @@ fn test_smart_split_with_extreme_total_supply_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_output(amount_collateral.clone()), - filter_xyk.clone(), + QuoteAmount::with_desired_output(amount_collateral), + filter_xyk, false, true, ) @@ -2022,7 +2021,7 @@ fn test_smart_split_with_low_collateral_reserves_works() { ) { let mut ext = ExtBuilder::with_total_supply_and_reserves( total_supply, - vec![(0, collateral_asset_id, xyk_pool_reserves.clone())], + vec![(0, collateral_asset_id, xyk_pool_reserves)], ) .build(); ext.execute_with(|| { @@ -2051,7 +2050,7 @@ fn test_smart_split_with_low_collateral_reserves_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_input(amount_base.clone()), + QuoteAmount::with_desired_input(amount_base), filter_both.clone(), false, true, @@ -2061,7 +2060,7 @@ fn test_smart_split_with_low_collateral_reserves_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_input(amount_base.clone()), + QuoteAmount::with_desired_input(amount_base), filter_xyk.clone(), false, true, @@ -2074,7 +2073,7 @@ fn test_smart_split_with_low_collateral_reserves_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_output(amount_base.clone()), + QuoteAmount::with_desired_output(amount_base), filter_both.clone(), false, true, @@ -2084,7 +2083,7 @@ fn test_smart_split_with_low_collateral_reserves_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_output(amount_base.clone()), + QuoteAmount::with_desired_output(amount_base), filter_xyk.clone(), false, true, @@ -2097,7 +2096,7 @@ fn test_smart_split_with_low_collateral_reserves_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_input(amount_collateral.clone()), + QuoteAmount::with_desired_input(amount_collateral), filter_both.clone(), false, true, @@ -2107,7 +2106,7 @@ fn test_smart_split_with_low_collateral_reserves_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_input(amount_collateral.clone()), + QuoteAmount::with_desired_input(amount_collateral), filter_xyk.clone(), false, true, @@ -2120,8 +2119,8 @@ fn test_smart_split_with_low_collateral_reserves_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_output(amount_collateral.clone()), - filter_both.clone(), + QuoteAmount::with_desired_output(amount_collateral), + filter_both, false, true, ) @@ -2130,8 +2129,8 @@ fn test_smart_split_with_low_collateral_reserves_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_output(amount_collateral.clone()), - filter_xyk.clone(), + QuoteAmount::with_desired_output(amount_collateral), + filter_xyk, false, true, ) @@ -2171,7 +2170,7 @@ fn test_smart_split_with_low_xykpool_reserves_works() { ) { let mut ext = ExtBuilder::with_total_supply_and_reserves( total_supply, - vec![(0, collateral_asset_id, xyk_pool_reserves.clone())], + vec![(0, collateral_asset_id, xyk_pool_reserves)], ) .build(); ext.execute_with(|| { @@ -2196,7 +2195,7 @@ fn test_smart_split_with_low_xykpool_reserves_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_input(amount_base.clone()), + QuoteAmount::with_desired_input(amount_base), filter_both.clone(), false, true, @@ -2206,7 +2205,7 @@ fn test_smart_split_with_low_xykpool_reserves_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_input(amount_base.clone()), + QuoteAmount::with_desired_input(amount_base), filter_mcbc.clone(), false, true, @@ -2219,7 +2218,7 @@ fn test_smart_split_with_low_xykpool_reserves_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_output(amount_base.clone()), + QuoteAmount::with_desired_output(amount_base), filter_both.clone(), false, true, @@ -2229,7 +2228,7 @@ fn test_smart_split_with_low_xykpool_reserves_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_output(amount_base.clone()), + QuoteAmount::with_desired_output(amount_base), filter_mcbc.clone(), false, true, @@ -2242,7 +2241,7 @@ fn test_smart_split_with_low_xykpool_reserves_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_input(amount_collateral.clone()), + QuoteAmount::with_desired_input(amount_collateral), filter_both.clone(), false, true, @@ -2252,7 +2251,7 @@ fn test_smart_split_with_low_xykpool_reserves_works() { &base_asset, &collateral_asset_id, &base_asset, - QuoteAmount::with_desired_input(amount_collateral.clone()), + QuoteAmount::with_desired_input(amount_collateral), filter_mcbc.clone(), false, true, @@ -2265,8 +2264,8 @@ fn test_smart_split_with_low_xykpool_reserves_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_output(amount_collateral.clone()), - filter_both.clone(), + QuoteAmount::with_desired_output(amount_collateral), + filter_both, false, true, ) @@ -2275,8 +2274,8 @@ fn test_smart_split_with_low_xykpool_reserves_works() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_output(amount_collateral.clone()), - filter_mcbc.clone(), + QuoteAmount::with_desired_output(amount_collateral), + filter_mcbc, false, true, ) @@ -2359,7 +2358,7 @@ fn test_smart_split_selling_xor_should_fail() { ) { let mut ext = ExtBuilder::with_total_supply_and_reserves( total_supply, - vec![(0, collateral_asset_id, xyk_pool_reserves.clone())], + vec![(0, collateral_asset_id, xyk_pool_reserves)], ) .build(); ext.execute_with(|| { @@ -2380,8 +2379,8 @@ fn test_smart_split_selling_xor_should_fail() { &base_asset, &base_asset, &collateral_asset_id, - QuoteAmount::with_desired_output(amount_collateral.clone()), - filter_both.clone(), + QuoteAmount::with_desired_output(amount_collateral), + filter_both, false, true, ); @@ -2448,7 +2447,7 @@ fn test_smart_split_error_handling_works() { ) { let mut ext = ExtBuilder::with_total_supply_and_reserves( balance!(350000), - vec![(0, collateral_asset_id, xyk_pool_reserves.clone())], + vec![(0, collateral_asset_id, xyk_pool_reserves)], ) .build(); ext.execute_with(|| { @@ -2503,23 +2502,23 @@ fn selecting_xyk_only_filter_is_forbidden() { use FilterMode::*; // xyk only selection, base case - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &PSWAP, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, Ð, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&VAL, &XOR, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&PSWAP, &XOR, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&DAI, &XOR, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(Ð, &XOR, &vec![XYKPool], &AllowSelected), true); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, &PSWAP, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, Ð, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&VAL, &XOR, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&PSWAP, &XOR, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&DAI, &XOR, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(Ð, &XOR, &[XYKPool], &AllowSelected)); // xyk only selection, indirect swaps - assert_eq!(LiquidityProxy::is_forbidden_filter(&DAI, &PSWAP, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&PSWAP, &VAL, &vec![XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&USDT, &VAL, &vec![XYKPool], &AllowSelected), true); + assert!(LiquidityProxy::is_forbidden_filter(&DAI, &PSWAP, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&PSWAP, &VAL, &[XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&USDT, &VAL, &[XYKPool], &AllowSelected)); // xyk only selection, non-reserve assets - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &vec![XYKPool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&USDT, &XOR, &vec![XYKPool], &AllowSelected), false); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &[XYKPool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&USDT, &XOR, &[XYKPool], &AllowSelected)); #[allow(unused_assignments)] // order-book let mut sources_except_xyk = Vec::new(); @@ -2534,71 +2533,71 @@ fn selecting_xyk_only_filter_is_forbidden() { } // xyk only selection, base case - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &PSWAP, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, Ð, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&VAL, &XOR, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&PSWAP, &XOR, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&DAI, &XOR, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(Ð, &XOR, &sources_except_xyk, &ForbidSelected), true); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, &PSWAP, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, Ð, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&VAL, &XOR, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&PSWAP, &XOR, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&DAI, &XOR, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(Ð, &XOR, &sources_except_xyk, &ForbidSelected)); // xyk only selection, indirect swaps - assert_eq!(LiquidityProxy::is_forbidden_filter(&DAI, &PSWAP, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&PSWAP, &VAL, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&USDT, &VAL, &sources_except_xyk, &ForbidSelected), true); + assert!(LiquidityProxy::is_forbidden_filter(&DAI, &PSWAP, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&PSWAP, &VAL, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&USDT, &VAL, &sources_except_xyk, &ForbidSelected)); // xyk only selection, non-reserve assets - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &sources_except_xyk, &ForbidSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&USDT, &XOR, &sources_except_xyk, &ForbidSelected), false); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &sources_except_xyk, &ForbidSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&USDT, &XOR, &sources_except_xyk, &ForbidSelected)); // smart selection, base case - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &PSWAP, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, Ð, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&VAL, &XOR, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&PSWAP, &XOR, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&DAI, &XOR, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &vec![], &Disabled), false); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &PSWAP, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, Ð, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&VAL, &XOR, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&PSWAP, &XOR, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&DAI, &XOR, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &[], &Disabled)); // smart selection, indirect swaps - assert_eq!(LiquidityProxy::is_forbidden_filter(&DAI, &PSWAP, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&PSWAP, &VAL, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&USDT, &VAL, &vec![], &Disabled), false); + assert!(!LiquidityProxy::is_forbidden_filter(&DAI, &PSWAP, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&PSWAP, &VAL, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&USDT, &VAL, &[], &Disabled)); // smart selection, non-reserve assets - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&USDT, &XOR, &vec![], &Disabled), false); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&USDT, &XOR, &[], &Disabled)); // tbc only selection, base case - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &PSWAP, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, Ð, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&VAL, &XOR, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&PSWAP, &XOR, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&DAI, &XOR, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(Ð, &XOR, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &[MulticollateralBondingCurvePool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &PSWAP, &[MulticollateralBondingCurvePool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &DAI, &[MulticollateralBondingCurvePool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, Ð, &[MulticollateralBondingCurvePool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&VAL, &XOR, &[MulticollateralBondingCurvePool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&PSWAP, &XOR, &[MulticollateralBondingCurvePool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&DAI, &XOR, &[MulticollateralBondingCurvePool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(Ð, &XOR, &[MulticollateralBondingCurvePool], &AllowSelected)); // tbc only selection, indirect swaps - assert_eq!(LiquidityProxy::is_forbidden_filter(&DAI, &PSWAP, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&PSWAP, &VAL, &vec![], &Disabled), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&USDT, &VAL, &vec![], &Disabled), false); + assert!(!LiquidityProxy::is_forbidden_filter(&DAI, &PSWAP, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&PSWAP, &VAL, &[], &Disabled)); + assert!(!LiquidityProxy::is_forbidden_filter(&USDT, &VAL, &[], &Disabled)); // tbc only selection, non-reserve assets - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); - assert_eq!(LiquidityProxy::is_forbidden_filter(&USDT, &XOR, &vec![MulticollateralBondingCurvePool], &AllowSelected), false); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &[MulticollateralBondingCurvePool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&USDT, &XOR, &[MulticollateralBondingCurvePool], &AllowSelected)); // hack cases with unavailable sources - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &vec![MockPool, XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&VAL, &PSWAP, &vec![MockPool, XYKPool], &AllowSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &vec![MockPool, XYKPool], &AllowSelected), false); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &[MockPool, XYKPool], &AllowSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&VAL, &PSWAP, &[MockPool, XYKPool], &AllowSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &[MockPool, XYKPool], &AllowSelected)); sources_except_xyk.push(MockPool); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&VAL, &PSWAP, &sources_except_xyk, &ForbidSelected), true); - assert_eq!(LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &sources_except_xyk, &ForbidSelected), false); + assert!(LiquidityProxy::is_forbidden_filter(&XOR, &VAL, &sources_except_xyk, &ForbidSelected)); + assert!(LiquidityProxy::is_forbidden_filter(&VAL, &PSWAP, &sources_except_xyk, &ForbidSelected)); + assert!(!LiquidityProxy::is_forbidden_filter(&XOR, &USDT, &sources_except_xyk, &ForbidSelected)); }); } @@ -2848,7 +2847,7 @@ fn test_quote_with_no_price_impact_with_desired_input() { &VAL, &KSM, QuoteAmount::with_desired_input(amount_val_in), - filter.clone(), + filter, false, true, ) @@ -3001,7 +3000,7 @@ fn test_quote_with_no_price_impact_with_desired_output() { &VAL, &KSM, QuoteAmount::with_desired_output(amount_ksm_out), - filter.clone(), + filter, false, true, ) @@ -3375,10 +3374,10 @@ fn test_batch_swap_emits_event() { assert_ok!(LiquidityProxy::swap_transfer_batch( RuntimeOrigin::signed(alice()), - swap_batches.clone(), + swap_batches, XOR, max_input_amount, - sources.clone(), + sources, filter_mode, )); @@ -3753,10 +3752,10 @@ fn test_batch_swap_asset_reuse_fails() { assert_noop!( LiquidityProxy::swap_transfer_batch( RuntimeOrigin::signed(alice()), - swap_batches.clone(), + swap_batches, XOR, max_input_amount, - sources.clone(), + sources, filter_mode, ), Error::::InsufficientBalance From e9cce161ae026077381b6616aa0763bbb646146c Mon Sep 17 00:00:00 2001 From: pakrentos Date: Mon, 30 Oct 2023 11:08:21 +0200 Subject: [PATCH 06/11] liquidity-proxy-rpc clippy fixes --- Cargo.lock | 62 +++++++++++++++++++++++++- pallets/liquidity-proxy/rpc/Cargo.toml | 2 +- pallets/liquidity-proxy/rpc/src/lib.rs | 3 +- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51d6b45a90..a4269c4eb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4789,6 +4789,10 @@ name = "futures-timer" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +dependencies = [ + "gloo-timers", + "send_wrapper 0.4.0", +] [[package]] name = "futures-util" @@ -4956,6 +4960,26 @@ dependencies = [ "regex", ] +[[package]] +name = "gloo-net" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9902a044653b26b99f7e3693a42f171312d9be8b26b5697bd1e43ad1f8a35e10" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "gloo-timers" version = "0.2.6" @@ -4968,6 +4992,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "group" version = "0.12.1" @@ -5695,6 +5732,7 @@ dependencies = [ "jsonrpsee-proc-macros", "jsonrpsee-server", "jsonrpsee-types", + "jsonrpsee-wasm-client", "jsonrpsee-ws-client", "tracing", ] @@ -5705,7 +5743,11 @@ version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8b3815d9f5d5de348e5f162b316dc9cdf4548305ebb15b4eb9328e66cf27d7a" dependencies = [ + "anyhow", + "futures-channel", + "futures-timer", "futures-util", + "gloo-net", "http", "jsonrpsee-core", "jsonrpsee-types", @@ -5746,6 +5788,7 @@ dependencies = [ "thiserror", "tokio", "tracing", + "wasm-bindgen-futures", ] [[package]] @@ -5816,6 +5859,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "jsonrpsee-wasm-client" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5df77c8f625d36e4cfb583c5a674eccebe32403fcfe42f7ceff7fac9324dd" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-types", +] + [[package]] name = "jsonrpsee-ws-client" version = "0.16.3" @@ -11716,6 +11770,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "send_wrapper" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" + [[package]] name = "send_wrapper" version = "0.6.0" @@ -15116,7 +15176,7 @@ dependencies = [ "log", "pharos", "rustc_version 0.4.0", - "send_wrapper", + "send_wrapper 0.6.0", "thiserror", "wasm-bindgen", "wasm-bindgen-futures", diff --git a/pallets/liquidity-proxy/rpc/Cargo.toml b/pallets/liquidity-proxy/rpc/Cargo.toml index 33b5edb9f7..1123a2a490 100644 --- a/pallets/liquidity-proxy/rpc/Cargo.toml +++ b/pallets/liquidity-proxy/rpc/Cargo.toml @@ -10,7 +10,7 @@ repository = 'https://github.com/sora-xor/sora2-network' [dependencies] serde = { version = "1.0.101", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3" } -jsonrpsee = { version = "0.16.2", features = ["server", "macros"] } +jsonrpsee = { version = "0.16.2", features = ["client", "server", "macros"] } sp-runtime = { git = "https://github.com/sora-xor/substrate.git", branch = "polkadot-v0.9.38" } sp-api = { git = "https://github.com/sora-xor/substrate.git", branch = "polkadot-v0.9.38" } sp-blockchain = { git = "https://github.com/sora-xor/substrate.git", branch = "polkadot-v0.9.38" } diff --git a/pallets/liquidity-proxy/rpc/src/lib.rs b/pallets/liquidity-proxy/rpc/src/lib.rs index 613cc08943..5a5ce486be 100644 --- a/pallets/liquidity-proxy/rpc/src/lib.rs +++ b/pallets/liquidity-proxy/rpc/src/lib.rs @@ -28,8 +28,7 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// TODO #167: fix clippy warnings -#![allow(clippy::all)] +#![allow(clippy::too_many_arguments)] use codec::Codec; use common::BalanceWrapper; From 622bee0564a486aa34eb00f32ab9bb4f38b2a3b9 Mon Sep 17 00:00:00 2001 From: pakrentos Date: Mon, 30 Oct 2023 11:12:17 +0200 Subject: [PATCH 07/11] mock-liquidity-source clippy fixes --- pallets/mock-liquidity-source/src/lib.rs | 8 ++++---- pallets/mock-liquidity-source/src/mock.rs | 9 +-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/pallets/mock-liquidity-source/src/lib.rs b/pallets/mock-liquidity-source/src/lib.rs index dbf9ca3667..44f583ab54 100644 --- a/pallets/mock-liquidity-source/src/lib.rs +++ b/pallets/mock-liquidity-source/src/lib.rs @@ -29,8 +29,6 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] use common::fixnum::ops::One; use common::prelude::{FixedWrapper, QuoteAmount, SwapAmount, SwapOutcome}; @@ -55,6 +53,7 @@ mod tests; #[allow(non_snake_case)] impl, I: 'static> Pallet { #[cfg(feature = "std")] + #[allow(clippy::type_complexity)] fn initialize_reserves(reserves: &[(T::DEXId, T::AssetId, (Fixed, Fixed))]) { reserves .iter() @@ -126,7 +125,7 @@ impl, I: 'static> Pallet { let amount_in_with_fee = base_amount_in - fee_amount.clone(); let X: FixedWrapper = base_reserve.into(); let Y: FixedWrapper = target_reserve.into(); - let d_X: FixedWrapper = amount_in_with_fee.into(); + let d_X: FixedWrapper = amount_in_with_fee; let amount_out = (Y * d_X.clone() / (X + d_X)) .get() .map_err(|_| Error::::InsufficientLiquidity)?; @@ -244,7 +243,7 @@ impl, I: 'static> Pallet { let account_id = technical::Pallet::::tech_account_id_to_account_id(&account)?; frame_system::Pallet::::inc_consumers(&account_id) .map_err(|_| Error::::IncRefError)?; - ReservesAcc::::set(account.clone()); + ReservesAcc::::set(account); let permissions = [BURN, MINT]; for permission in &permissions { permissions::Pallet::::assign_permission( @@ -623,6 +622,7 @@ pub mod pallet { StorageValue<_, Vec<(Balance, T::AssetId, RewardReason)>, ValueQuery>; #[pallet::genesis_config] + #[allow(clippy::type_complexity)] pub struct GenesisConfig, I: 'static = ()> { pub phantom: sp_std::marker::PhantomData, pub reserves: Vec<(T::DEXId, T::AssetId, (Fixed, Fixed))>, diff --git a/pallets/mock-liquidity-source/src/mock.rs b/pallets/mock-liquidity-source/src/mock.rs index 2e17c4c113..2357d84ace 100644 --- a/pallets/mock-liquidity-source/src/mock.rs +++ b/pallets/mock-liquidity-source/src/mock.rs @@ -222,18 +222,11 @@ impl trading_pair::Config for Runtime { type WeightInfo = (); } +#[derive(Default)] pub struct ExtBuilder { // add additional fields for other pallets genesis } -impl Default for ExtBuilder { - fn default() -> Self { - Self { - // add values for mock genesis - } - } -} - impl ExtBuilder { pub fn build(self) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default() From fe6c20814abb0c30ca519ea10ca87ffbb0429a6a Mon Sep 17 00:00:00 2001 From: pakrentos Date: Mon, 30 Oct 2023 11:24:41 +0200 Subject: [PATCH 08/11] mbc-pool clippy fixes --- .../src/benchmarking.rs | 36 +- .../src/lib.rs | 74 +- .../src/mock.rs | 20 +- .../src/tests.rs | 7237 ++++++++--------- 4 files changed, 3612 insertions(+), 3755 deletions(-) diff --git a/pallets/multicollateral-bonding-curve-pool/src/benchmarking.rs b/pallets/multicollateral-bonding-curve-pool/src/benchmarking.rs index 953e749a8c..b58c6e1a10 100644 --- a/pallets/multicollateral-bonding-curve-pool/src/benchmarking.rs +++ b/pallets/multicollateral-bonding-curve-pool/src/benchmarking.rs @@ -95,21 +95,9 @@ fn setup_benchmark() -> Result<(), &'static str> { permissions::Scope::Unlimited, ) .unwrap(); - Assets::::mint_to(&XOR.into(), &owner.clone(), &owner.clone(), balance!(5000)).unwrap(); - Assets::::mint_to( - &DAI.into(), - &owner.clone(), - &owner.clone(), - balance!(50000000), - ) - .unwrap(); - Assets::::mint_to( - &VAL.into(), - &owner.clone(), - &owner.clone(), - balance!(50000000), - ) - .unwrap(); + Assets::::mint_to(&XOR.into(), &owner, &owner, balance!(5000)).unwrap(); + Assets::::mint_to(&DAI.into(), &owner, &owner, balance!(50000000)).unwrap(); + Assets::::mint_to(&VAL.into(), &owner, &owner, balance!(50000000)).unwrap(); XYKPool::::initialize_pool(owner_origin.clone(), DEX.into(), XOR.into(), DAI.into()) .unwrap(); @@ -128,7 +116,7 @@ fn setup_benchmark() -> Result<(), &'static str> { ) .unwrap(); XYKPool::::deposit_liquidity( - owner_origin.clone(), + owner_origin, DEX.into(), XOR.into(), VAL.into(), @@ -341,7 +329,7 @@ benchmarks! { ) .unwrap(); Pallet::::initialize_pool( - RawOrigin::Signed(caller.clone()).into(), + RawOrigin::Signed(caller).into(), USDT.into() ).unwrap(); @@ -388,8 +376,8 @@ benchmarks! { .unwrap(); Assets::::mint_to( &USDT.into(), - &caller.clone(), - &caller.clone(), + &caller, + &caller, balance!(50000000), ) .unwrap(); @@ -421,7 +409,7 @@ benchmarks! { // run only for benchmarks, not for tests // TODO: remake when unit tests use chainspec #[cfg(not(test))] - Pallet::::exchange(&caller, &caller, &dex_id, &USDT.into(), &XOR.into(), amount.into()).unwrap(); + Pallet::::exchange(&caller, &caller, &dex_id, &USDT.into(), &XOR.into(), amount).unwrap(); } verify { #[cfg(not(test))] @@ -459,7 +447,7 @@ benchmarks! { USDT.into() ).unwrap(); Pallet::::initialize_pool( - RawOrigin::Signed(caller.clone()).into(), + RawOrigin::Signed(caller).into(), USDT.into() ).unwrap(); }: { @@ -497,8 +485,8 @@ benchmarks! { .unwrap(); Assets::::mint_to( &USDT.into(), - &caller.clone(), - &caller.clone(), + &caller, + &caller, balance!(50000000), ) .unwrap(); @@ -510,7 +498,7 @@ benchmarks! { ) .unwrap(); Pallet::::initialize_pool( - RawOrigin::Signed(caller.clone()).into(), + RawOrigin::Signed(caller).into(), USDT.into() ).unwrap(); diff --git a/pallets/multicollateral-bonding-curve-pool/src/lib.rs b/pallets/multicollateral-bonding-curve-pool/src/lib.rs index 63043689ff..495ab7dbd5 100644 --- a/pallets/multicollateral-bonding-curve-pool/src/lib.rs +++ b/pallets/multicollateral-bonding-curve-pool/src/lib.rs @@ -29,8 +29,6 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] pub mod weights; @@ -264,7 +262,7 @@ pub mod pallet { origin, ManagementMode::Private, )?; - ReferenceAssetId::::put(reference_asset_id.clone()); + ReferenceAssetId::::put(reference_asset_id); Self::deposit_event(Event::ReferenceAssetChanged(reference_asset_id)); Ok(().into()) } @@ -288,8 +286,8 @@ pub mod pallet { Error::::UnsupportedCollateralAssetId ); // NOTE: not using insert() here because it unwraps Option, which is not intended - AssetsWithOptionalRewardMultiplier::::mutate(&collateral_asset_id, |opt| { - *opt = multiplier.clone() + AssetsWithOptionalRewardMultiplier::::mutate(collateral_asset_id, |opt| { + *opt = multiplier }); Self::deposit_event(Event::OptionalRewardMultiplierUpdated( collateral_asset_id, @@ -571,13 +569,13 @@ pub mod pallet { #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - frame_system::Pallet::::inc_consumers(&self.incentives_account_id.as_ref().unwrap()) + frame_system::Pallet::::inc_consumers(self.incentives_account_id.as_ref().unwrap()) .unwrap(); ReservesAcc::::put(&self.reserves_account_id); DistributionAccountsEntry::::put(&self.distribution_accounts); - ReferenceAssetId::::put(&self.reference_asset_id); - IncentivesAccountId::::put(&self.incentives_account_id.as_ref().unwrap()); - FreeReservesAccountId::::put(&self.free_reserves_account_id.as_ref().unwrap()); + ReferenceAssetId::::put(self.reference_asset_id); + IncentivesAccountId::::put(self.incentives_account_id.as_ref().unwrap()); + FreeReservesAccountId::::put(self.free_reserves_account_id.as_ref().unwrap()); self.initial_collateral_assets .iter() .cloned() @@ -656,16 +654,16 @@ impl BuyMainAsset { return Ok(()); } - if !Pallet::::attempt_free_reserves_distribution( + if Pallet::::attempt_free_reserves_distribution( &self.reserves_account_id, &self.collateral_asset_id, free_amount, ) - .is_ok() + .is_err() { Pallet::::add_free_reserves_to_pending_list( &self.reserves_account_id, - self.collateral_asset_id.clone(), + self.collateral_asset_id, free_amount, )?; } @@ -696,7 +694,7 @@ impl BuyMainAsset { main_asset_amount, )?; if let Some(multiplier) = - AssetsWithOptionalRewardMultiplier::::get(&self.collateral_asset_id) + AssetsWithOptionalRewardMultiplier::::get(self.collateral_asset_id) { pswap_amount = (FixedWrapper::from(pswap_amount) * multiplier) .try_into_balance() @@ -739,7 +737,7 @@ impl BuyMainAsset { self.update_reward(input_amount, output_amount)?; self.deposit_input(input_amount)?; self.distribute_reserves(input_amount)?; - self.mint_output(output_amount.clone())?; + self.mint_output(output_amount)?; Ok(result) }) } @@ -753,12 +751,12 @@ impl Pallet { PendingFreeReserves::::mutate(|vec| { let len = vec.len(); vec.retain(|(collateral_asset_id, free_amount)| { - !Pallet::::attempt_free_reserves_distribution( + Pallet::::attempt_free_reserves_distribution( &free_reserves_acc, - &collateral_asset_id, + collateral_asset_id, *free_amount, ) - .is_ok() + .is_err() }); Ok(len.try_into().unwrap_or(u32::max_value())) }) @@ -787,14 +785,13 @@ impl Pallet { DEXId::Polkaswap.into(), holder, holder, - &collateral_asset_id, + collateral_asset_id, &base_asset_id, - SwapAmount::with_desired_input(free_amount, Balance::zero()).into(), + SwapAmount::with_desired_input(free_amount, Balance::zero()), Pallet::::self_excluding_filter(), )? - .amount - .into(); - Assets::::burn_from(&base_asset_id, &holder, &holder, swapped_xor_amount)?; + .amount; + Assets::::burn_from(&base_asset_id, holder, holder, swapped_xor_amount)?; let fw_swapped_xor_amount = FixedWrapper::from(swapped_xor_amount); let mut undistributed_xor_amount = fw_swapped_xor_amount @@ -820,7 +817,7 @@ impl Pallet { Technical::::tech_account_id_to_account_id(account)? } }; - Assets::::mint_to(&base_asset_id, &holder, &account, amount)?; + Assets::::mint_to(&base_asset_id, holder, &account, amount)?; undistributed_xor_amount = undistributed_xor_amount.saturating_sub(amount); } @@ -897,7 +894,7 @@ impl Pallet { Ok(()) }; if transactional { - common::with_transaction(|| code()) + common::with_transaction(code) } else { code() } @@ -1025,8 +1022,8 @@ impl Pallet { let sqrt = (current_state.clone() * current_state.clone() * price_change_coeff.clone() - + (fixed_wrapper!(2.0) * collateral_reference_in.clone())) - .multiply_and_sqrt(&price_change_coeff); + + (fixed_wrapper!(2.0) * collateral_reference_in)) + .multiply_and_sqrt(&price_change_coeff); sqrt - current_state * price_change_coeff }; @@ -1192,7 +1189,7 @@ impl Pallet { let input_amount = Self::buy_price( main_asset_id, collateral_asset_id, - QuoteAmount::with_desired_output(desired_amount_out_with_fee.clone()), + QuoteAmount::with_desired_output(desired_amount_out_with_fee), )?; let input_amount = input_amount .into_bits() @@ -1290,9 +1287,7 @@ impl Pallet { let output_amount = Self::sell_price( main_asset_id, collateral_asset_id, - QuoteAmount::with_desired_input( - desired_amount_in.saturating_sub(fee_amount.clone()), - ), + QuoteAmount::with_desired_input(desired_amount_in.saturating_sub(fee_amount)), )?; let output_amount = output_amount .into_bits() @@ -1372,7 +1367,7 @@ impl Pallet { technical::Pallet::::transfer_out( collateral_asset_id, &reserves_tech_account_id, - &to_account_id, + to_account_id, output_amount, )?; Assets::::burn_from( @@ -1442,8 +1437,8 @@ impl Pallet { collateral_asset_id: &T::AssetId, price_variant: PriceVariant, ) -> Result { - let reserve = Assets::::free_balance(&collateral_asset_id, &reserves_account_id)?; - let price = Self::reference_price(&collateral_asset_id, price_variant)?; + let reserve = Assets::::free_balance(collateral_asset_id, reserves_account_id)?; + let price = Self::reference_price(collateral_asset_id, price_variant)?; (FixedWrapper::from(reserve) * price) .try_into_balance() .map_err(|_| Error::::PriceCalculationFailed.into()) @@ -1552,9 +1547,9 @@ impl LiquiditySource::get().contains(&output_asset_id) + EnabledTargets::::get().contains(output_asset_id) } else if output_asset_id == &T::GetBaseAssetId::get() { - EnabledTargets::::get().contains(&input_asset_id) + EnabledTargets::::get().contains(input_asset_id) } else { false } @@ -1572,9 +1567,9 @@ impl LiquiditySource Ok(( @@ -1655,8 +1650,7 @@ impl LiquiditySource::get(&input_asset_id) - { + if let Some(multiplier) = AssetsWithOptionalRewardMultiplier::::get(input_asset_id) { pswap_amount = (FixedWrapper::from(pswap_amount) * multiplier) .try_into_balance() .map_err(|_| Error::::PriceCalculationFailed)?; @@ -1704,7 +1698,7 @@ impl LiquiditySource::FailedToCalculatePriceWithoutImpact)?; diff --git a/pallets/multicollateral-bonding-curve-pool/src/mock.rs b/pallets/multicollateral-bonding-curve-pool/src/mock.rs index ec2b85f8b3..03b5ccc72b 100644 --- a/pallets/multicollateral-bonding-curve-pool/src/mock.rs +++ b/pallets/multicollateral-bonding-curve-pool/src/mock.rs @@ -93,9 +93,8 @@ pub fn tmp_account() -> AccountId { pub fn get_pool_reserves_account_id() -> AccountId { let reserves_tech_account_id = crate::ReservesAcc::::get(); - let reserves_account_id = - Technical::tech_account_id_to_account_id(&reserves_tech_account_id).unwrap(); - reserves_account_id + + Technical::tech_account_id_to_account_id(&reserves_tech_account_id).unwrap() } pub const DEX_A_ID: DEXId = DEXId::Polkaswap; @@ -114,7 +113,7 @@ parameter_types! { pub const CreationFee: u128 = 0; pub const TransactionByteFee: u128 = 1; pub const GetNumSamples: usize = 40; - pub GetIncentiveAssetId: AssetId = common::AssetId32::from_bytes(hex!("0200050000000000000000000000000000000000000000000000000000000000").into()); + pub GetIncentiveAssetId: AssetId = common::AssetId32::from_bytes(hex!("0200050000000000000000000000000000000000000000000000000000000000")); pub GetPswapDistributionAccountId: AccountId = AccountId32::from([151; 32]); pub const GetDefaultSubscriptionFrequency: BlockNumber = 10; pub const GetBurnUpdateFrequency: BlockNumber = 14400; @@ -217,7 +216,7 @@ impl BuyBackHandler for BuyBackHandlerImpl { amount: Balance, ) -> Result { let owner = Assets::asset_owner(&mint_asset_id).unwrap(); - Assets::mint_to(&mint_asset_id, &owner, &tmp_account(), amount)?; + Assets::mint_to(mint_asset_id, &owner, &tmp_account(), amount)?; let amount = Self::buy_back_and_burn(&tmp_account(), mint_asset_id, buy_back_asset_id, amount)?; Ok(amount) @@ -413,7 +412,7 @@ pub type MockPrices = impl MockDEXApi { pub fn with_price(asset_pair: (AssetId, AssetId), price: Balance) { - MockPrices::insert(asset_pair.clone(), price); + MockPrices::insert(asset_pair, price); MockPrices::insert( (asset_pair.1, asset_pair.0), (fixed_wrapper!(1) / FixedWrapper::from(price)) @@ -423,8 +422,7 @@ impl MockDEXApi { } fn get_mock_source_account() -> Result<(TechAccountId, AccountId), DispatchError> { - let tech_account_id = - TechAccountId::Pure(DEXId::Polkaswap.into(), TechPurpose::FeeCollector); + let tech_account_id = TechAccountId::Pure(DEXId::Polkaswap, TechPurpose::FeeCollector); let account_id = Technical::tech_account_id_to_account_id(&tech_account_id)?; Ok((tech_account_id, account_id)) } @@ -465,11 +463,11 @@ impl MockDEXApi { input_asset_id: &AssetId, output_asset_id: &AssetId, ) -> bool { - MockPrices::contains_key(&(*input_asset_id, *output_asset_id)) + MockPrices::contains_key((*input_asset_id, *output_asset_id)) } fn get_price(input_asset_id: &AssetId, output_asset_id: &AssetId) -> Balance { - MockPrices::get(&(*input_asset_id, *output_asset_id)).unwrap() + MockPrices::get((*input_asset_id, *output_asset_id)).unwrap() } fn inner_quote( @@ -659,7 +657,7 @@ impl PriceToolsPallet for MockDEXApi { _price_variant: PriceVariant, ) -> Result { Ok(Self::inner_quote( - &DEXId::Polkaswap.into(), + &DEXId::Polkaswap, input_asset_id, output_asset_id, QuoteAmount::with_desired_input(balance!(1)), diff --git a/pallets/multicollateral-bonding-curve-pool/src/tests.rs b/pallets/multicollateral-bonding-curve-pool/src/tests.rs index 7265e6a362..22f3d6f4e4 100644 --- a/pallets/multicollateral-bonding-curve-pool/src/tests.rs +++ b/pallets/multicollateral-bonding-curve-pool/src/tests.rs @@ -28,3843 +28,3720 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -mod tests { - use crate::{ - mock::*, DistributionAccount, DistributionAccountData, DistributionAccounts, Error, Pallet, - RETRY_DISTRIBUTION_FREQUENCY, - }; - use common::assert_approx_eq; - use common::{ - self, balance, fixed, fixed_wrapper, - fixnum::ops::One as _, - fixnum::ops::Zero as _, - prelude::{Balance, FixedWrapper, QuoteAmount, SwapAmount, SwapOutcome}, - AssetInfoProvider, AssetName, AssetSymbol, DEXId, Fixed, LiquidityProxyTrait, - LiquiditySource, LiquiditySourceFilter, PriceVariant, TechPurpose, DAI, - DEFAULT_BALANCE_PRECISION, PSWAP, TBCD, USDT, VAL, XOR, XST, XSTUSD, - }; - use frame_support::assert_err; - use frame_support::assert_noop; - use frame_support::storage::{with_transaction, TransactionOutcome}; - use frame_support::traits::OnInitialize; - use sp_arithmetic::traits::Zero; - use sp_runtime::DispatchError; - - type MBCPool = Pallet; - - fn assert_swap_outcome( - left: SwapOutcome, - right: SwapOutcome, - tolerance: Balance, - ) { - assert_approx_eq!(left.amount, right.amount, tolerance); - assert_approx_eq!(left.fee, right.fee, tolerance); - } - - fn ensure_distribution_accounts_balances( - distribution_accounts: DistributionAccounts< - DistributionAccountData>, - >, - balances: Vec, - ) { - let distribution_accounts_array = - distribution_accounts.xor_distribution_accounts_as_array(); - for (account, balance) in distribution_accounts_array - .to_vec() - .into_iter() - .zip(balances) - { - match account { - DistributionAccount::Account(account_id) => { - assert_eq!(Assets::total_balance(&XOR, &account_id).unwrap(), balance,); - } - DistributionAccount::TechAccount(account_id) => { - assert_eq!( - Technical::total_balance(&XOR, &account_id).unwrap(), - balance, - ); - } - } - } - } - - #[test] - fn should_calculate_price() { - let mut ext = ExtBuilder::default().build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - - // base case for buy - assert_eq!( - MBCPool::buy_function(&XOR, &VAL, PriceVariant::Buy, Fixed::ZERO) - .expect("failed to calculate buy price"), - fixed!(536.574420344053851907) - ); - assert_eq!( - MBCPool::buy_price( - &XOR, - &VAL, - QuoteAmount::with_desired_output(balance!(100000)) - ) - .expect("failed to calculate buy assets price"), - fixed!(1151397.348365215316854563) - ); - assert_eq!( - MBCPool::buy_price( - &XOR, - &VAL, - QuoteAmount::with_desired_input(balance!(1151397.348365215316854563)) - ) - .expect("failed to calculate buy assets price"), - fixed!(99999.99999999999998516) // TODO: try to improve precision - ); - - // base case for sell with empty reserves - assert_eq!( - MBCPool::sell_function(&XOR, &VAL, Fixed::ZERO) - .expect("failed to calculate sell price"), - fixed!(429.259536275243081525) - ); - assert_noop!( - MBCPool::sell_price( - &XOR, - &VAL, - QuoteAmount::with_desired_output(balance!(100000)) - ), - Error::::NotEnoughReserves, - ); - assert_noop!( - MBCPool::sell_price( - &XOR, - &VAL, - QuoteAmount::with_desired_input(balance!(100000)) - ), - Error::::NotEnoughReserves, - ); - - // base case for sell with some reserves - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap, - &VAL, - &XOR, - SwapAmount::with_desired_input(balance!(100000), 0), - ) - .expect("Failed to buy XOR."); - assert_eq!( - MBCPool::sell_price( - &XOR, - &VAL, - QuoteAmount::with_desired_output(balance!(50000)) - ) - .expect("failed to calculate buy assets price"), - fixed!(15287.903511880099065775) - ); - assert_eq!( - MBCPool::sell_price( - &XOR, - &VAL, - QuoteAmount::with_desired_input(balance!(15287.903511880099065528)) - ) - .expect("failed to calculate buy assets price"), - fixed!(49999.999999999999999697) // TODO: improve precision - ); - }); - } - - #[test] - fn should_calculate_tbcd_price() { - let mut ext = ExtBuilder::default().with_tbcd().build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - TBCD, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(TBCD, false).expect("Failed to initialize pool."); - - // base case for buy - assert_eq!( - MBCPool::buy_function(&XOR, &TBCD, PriceVariant::Buy, Fixed::ZERO) - .expect("failed to calculate buy price"), - fixed!(100.7), - ); - assert_eq!( - MBCPool::buy_price( - &XOR, - &TBCD, - QuoteAmount::with_desired_output(balance!(1000)) - ) - .expect("failed to calculate buy assets price"), - fixed!(100700.0), - ); - assert_eq!( - MBCPool::buy_price( - &XOR, - &TBCD, - QuoteAmount::with_desired_input(balance!(100700.0)) - ) - .expect("failed to calculate buy assets price"), - fixed!(1000.0), - ); - - assert_eq!( - MBCPool::buy_price( - &XOR, - &TBCD, - QuoteAmount::with_desired_output(balance!(100000)) - ) - .expect("failed to calculate buy assets price"), - fixed!(10070000.0), - ); - assert_eq!( - MBCPool::buy_price( - &XOR, - &TBCD, - QuoteAmount::with_desired_input(balance!(10070000.0)) - ) - .expect("failed to calculate buy assets price"), - fixed!(100000.0), - ); - - // base case for sell with empty reserves - assert_eq!( - MBCPool::sell_function(&XOR, &TBCD, Fixed::ZERO) - .expect("failed to calculate sell price"), - fixed!(80.56) - ); - assert_noop!( - MBCPool::sell_price( - &XOR, - &TBCD, - QuoteAmount::with_desired_output(balance!(100000)) - ), - Error::::NotEnoughReserves, - ); - assert_noop!( - MBCPool::sell_price( - &XOR, - &TBCD, - QuoteAmount::with_desired_input(balance!(100000)) - ), - Error::::NotEnoughReserves, - ); - - // base case for sell with some reserves - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap, - &TBCD, - &XOR, - SwapAmount::with_desired_input(balance!(100000), 0), - ) - .expect("Failed to buy XOR."); - assert_eq!( - MBCPool::sell_price( - &XOR, - &TBCD, - QuoteAmount::with_desired_output(balance!(50000)) - ) - .expect("failed to calculate buy assets price"), - fixed!(1655.081098973849718635), - ); - assert_eq!( - MBCPool::sell_price( - &XOR, - &TBCD, - QuoteAmount::with_desired_input(balance!(1655.081098973849718635)) - ) - .expect("failed to calculate buy assets price"), - fixed!(50000), - ); - }); - } - - #[test] - fn calculate_price_for_boundary_values() { - let mut ext = ExtBuilder::default().build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - // add some reserves - MBCPool::exchange( - &alice, - &alice, - &DEXId::Polkaswap, - &VAL, - &XOR, - SwapAmount::with_desired_input(balance!(1), 0), - ) - .expect("Failed to buy XOR."); - - assert_noop!( - MBCPool::sell_price( - &XOR, - &VAL, - QuoteAmount::with_desired_input(Balance::max_value()), - ), - Error::::PriceCalculationFailed, - ); - assert_noop!( - MBCPool::sell_price( - &XOR, - &VAL, - QuoteAmount::with_desired_output(Balance::max_value()), - ), - Error::::NotEnoughReserves, - ); - assert_eq!( - MBCPool::sell_price(&XOR, &VAL, QuoteAmount::with_desired_input(Balance::zero()),), - Ok(fixed!(0)), - ); - assert_eq!( - MBCPool::sell_price( - &XOR, - &VAL, - QuoteAmount::with_desired_output(Balance::zero()), - ), - Ok(fixed!(0)), - ); - - assert_noop!( - MBCPool::buy_price( - &XOR, - &VAL, - QuoteAmount::with_desired_input(Balance::max_value()), - ), - Error::::PriceCalculationFailed, - ); - assert_noop!( - MBCPool::buy_price( - &XOR, - &VAL, - QuoteAmount::with_desired_output(Balance::max_value()), - ), - Error::::PriceCalculationFailed, - ); - assert_eq!( - MBCPool::buy_price(&XOR, &VAL, QuoteAmount::with_desired_input(Balance::zero()),), - Ok(fixed!(0)), - ); - assert_eq!( - MBCPool::buy_price( - &XOR, - &VAL, - QuoteAmount::with_desired_output(Balance::zero()), - ), - Ok(fixed!(0)), - ); - }); - } - - fn bonding_curve_pool_init( - initial_reserves: Vec<(AssetId, Balance)>, - ) -> Result< - DistributionAccounts< - DistributionAccountData< - DistributionAccount< - ::AccountId, - ::TechAccountId, - >, - >, - >, - DispatchError, - > { - let bonding_curve_tech_account_id = TechAccountId::Pure( - DEXId::Polkaswap, - TechPurpose::Identifier(b"bonding_curve_tech_account_id".to_vec()), - ); - Technical::register_tech_account_id(bonding_curve_tech_account_id.clone())?; - MBCPool::set_reserves_account_id(bonding_curve_tech_account_id.clone())?; - for (asset_id, balance) in initial_reserves { - Technical::mint(&asset_id, &bonding_curve_tech_account_id, balance)?; - } - let initial_price: Fixed = fixed!(200); - crate::InitialPrice::::put(initial_price); - - let val_holders_coefficient = fixed_wrapper!(0.5); - let val_holders_xor_alloc_coeff = val_holders_coefficient.clone() * fixed_wrapper!(0.9); - let val_holders_buy_back_coefficient = - val_holders_coefficient.clone() * fixed_wrapper!(0.1); - let projects_coefficient: FixedWrapper = fixed_wrapper!(1) - val_holders_coefficient; - let projects_sora_citizens_coeff: FixedWrapper = - projects_coefficient.clone() * fixed_wrapper!(0.01); - let projects_stores_and_shops_coeff: FixedWrapper = - projects_coefficient.clone() * fixed_wrapper!(0.04); - let projects_parliament_and_development_coeff: FixedWrapper = - projects_coefficient.clone() * fixed_wrapper!(0.05); - let projects_other_coeff: FixedWrapper = projects_coefficient * fixed_wrapper!(0.9); - - debug_assert_eq!( - Fixed::ONE, - (val_holders_xor_alloc_coeff.clone() - + projects_sora_citizens_coeff.clone() - + projects_stores_and_shops_coeff.clone() - + projects_parliament_and_development_coeff.clone() - + projects_other_coeff.clone() - + val_holders_buy_back_coefficient.clone()) - .get() - .unwrap() - ); - - let xor_allocation = DistributionAccountData::new( - DistributionAccount::TechAccount(TechAccountId::Pure( - DEXId::Polkaswap, - TechPurpose::Identifier(b"xor_allocation".to_vec()), - )), - val_holders_xor_alloc_coeff.get().unwrap(), - ); - let sora_citizens = DistributionAccountData::new( - DistributionAccount::TechAccount(TechAccountId::Pure( - DEXId::Polkaswap, - TechPurpose::Identifier(b"sora_citizens".to_vec()), - )), - projects_sora_citizens_coeff.get().unwrap(), - ); - let stores_and_shops = DistributionAccountData::new( - DistributionAccount::TechAccount(TechAccountId::Pure( - DEXId::Polkaswap, - TechPurpose::Identifier(b"stores_and_shops".to_vec()), - )), - projects_stores_and_shops_coeff.get().unwrap(), - ); - let projects = DistributionAccountData::new( - DistributionAccount::TechAccount(TechAccountId::Pure( - DEXId::Polkaswap, - TechPurpose::Identifier(b"projects".to_vec()), - )), - projects_other_coeff.get().unwrap(), - ); - let val_holders = DistributionAccountData::new( - DistributionAccount::TechAccount(TechAccountId::Pure( - DEXId::Polkaswap, - TechPurpose::Identifier(b"val_holders".to_vec()), - )), - val_holders_buy_back_coefficient.get().unwrap(), - ); - let accounts = DistributionAccounts::<_> { - xor_allocation, - sora_citizens, - stores_and_shops, - projects, - val_holders, - }; - for account in &accounts.xor_distribution_accounts_as_array() { - match account { - DistributionAccount::Account(_) => continue, - DistributionAccount::TechAccount(account) => { - Technical::register_tech_account_id(account.clone())?; - } - } - } - MBCPool::set_distribution_accounts(accounts.clone()); - Ok(accounts) - } - - #[test] - fn should_exchange_with_empty_reserves() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - balance!(10000), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - 0, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(205), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(5.529018162388484076), - balance!(0.003009027081243731), - ), - balance!(0.0001), - ); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - SwapAmount::with_desired_input(balance!(1), Balance::zero()), - ) - .unwrap() - .0, - SwapOutcome::new(balance!(2.100439516374830873), balance!(0.093)), - balance!(0.0001), - ); - }); - } - - #[test] - fn should_exchange_tbcd_with_empty_reserves() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - 0, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - TBCD, - balance!(205), - AssetSymbol(b"TBCD".to_vec()), - AssetName(b"SORA TBC Dollar".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - TBCD, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(TBCD, false).expect("Failed to initialize pool."); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &TBCD, - &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(101.003009027081243711), - balance!(0.003009027081243731), - ), - balance!(0.0001), - ); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &XOR, - &TBCD, - SwapAmount::with_desired_input(balance!(1), Balance::zero()), - ) - .unwrap() - .0, - SwapOutcome::new(balance!(38.370385852073146860), balance!(0.093)), - balance!(0.0001), - ); - }); - } - - #[test] - fn should_exchange_with_nearly_full_reserves() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - balance!(10), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(10000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - balance!(10000), - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let initial_price: Fixed = fixed!(200); - crate::InitialPrice::::put(initial_price); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - let total_issuance = Assets::total_issuance(&XOR).unwrap(); - let reserve_amount_expected = FixedWrapper::from(total_issuance) - * MBCPool::sell_function(&XOR, &VAL, Fixed::ZERO).unwrap(); - let pool_reference_amount = reserve_amount_expected - - FixedWrapper::from( - MBCPool::buy_function(&XOR, &VAL, PriceVariant::Buy, Fixed::ZERO).unwrap(), - ) / balance!(2); - let pool_reference_amount = pool_reference_amount.into_balance(); - let pool_val_amount = MockDEXApi::quote( - DEXId::Polkaswap, - &USDT, - &VAL, - QuoteAmount::with_desired_input(pool_reference_amount), - LiquiditySourceFilter::empty(DEXId::Polkaswap), - true, - ) - .unwrap(); - let distribution_accounts = - bonding_curve_pool_init(vec![(VAL, pool_val_amount.amount)]).unwrap(); - let alice = &alice(); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_output(balance!(1000), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(5536.708257819426729513), - balance!(3.009027081243731193), - ), - balance!(0.0001), - ); - ensure_distribution_accounts_balances( - distribution_accounts, - vec![ - balance!(2.760049066522984224), - balance!(11.040196266091936898), - balance!(248.404415987068580219), - ], - ); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - SwapAmount::with_desired_input(balance!(1000), Balance::zero()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(4365.335149368998667748), - balance!(3.000000000000000000), - ), - balance!(0.0001), - ); - }); - } - - #[test] - fn should_exchange_with_full_reserves() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - balance!(10), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(10000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - balance!(10000), - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let initial_price: Fixed = fixed!(200); - crate::InitialPrice::::put(initial_price); - let total_issuance = Assets::total_issuance(&XOR).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - XSTUSD, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - - let pool_reference_amount = FixedWrapper::from(total_issuance) - * MBCPool::sell_function(&XOR, &VAL, Fixed::ZERO).unwrap(); - let pool_reference_amount = pool_reference_amount.into_balance(); - let pool_val_amount = MockDEXApi::quote( - DEXId::Polkaswap, - &USDT, - &VAL, - QuoteAmount::with_desired_input(pool_reference_amount), - LiquiditySourceFilter::empty(DEXId::Polkaswap), - true, - ) - .unwrap(); - - let distribution_accounts = - bonding_curve_pool_init(vec![(VAL, pool_val_amount.amount)]).unwrap(); - let alice = &alice(); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_output(balance!(1000), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(5536.708257819426729513), - balance!(3.009027081243731193), - ), - balance!(0.0001), - ); - ensure_distribution_accounts_balances( - distribution_accounts, - vec![ - balance!(2.760049066522984224), - balance!(11.040196266091936898), - balance!(248.404415987068580219), - ], - ); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - SwapAmount::with_desired_input(balance!(1000), Balance::zero()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(4365.335415603766574971), - balance!(3.000000000000000000), - ), - balance!(0.0001), - ); - }); - } - - #[test] - fn should_not_sell_without_reserves() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - 0, - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - balance!(1), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - 0, - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .with_tbcd() - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - TBCD, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - MBCPool::initialize_pool_unchecked(TBCD, false).expect("Failed to initialize pool."); - let alice = &alice(); - - assert_err!( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - SwapAmount::with_desired_input(balance!(1), Balance::zero()), - ), - Error::::NotEnoughReserves - ); - - assert_err!( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &XOR, - &TBCD, - SwapAmount::with_desired_input(balance!(1), Balance::zero()), - ), - Error::::NotEnoughReserves - ); - }); - } - - #[test] - fn swaps_should_be_additive() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - 0, - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - 0, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(10000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let alice = &alice(); - let _ = bonding_curve_pool_init(Vec::new()).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - let amount = balance!(100); // TODO: investigate strange precision error dependency on value - let parts = 5; - - let whole_outcome = with_transaction(|| { - let whole_outcome = MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_output(amount.into(), Balance::max_value()), - ); - TransactionOutcome::Rollback(whole_outcome) - }); - - let cumulative_outcome = (0..parts) - .into_iter() - .map(|_i| { - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_output( - (amount / parts).into(), - Balance::max_value(), - ), - ) - .unwrap() - }) - .fold( - SwapOutcome::new(Balance::zero(), Balance::zero()), - |acc, x| SwapOutcome { - amount: acc.amount + x.0.amount, - fee: acc.fee + x.0.fee, - }, - ); - assert_swap_outcome( - whole_outcome.unwrap().0, - cumulative_outcome, - balance!(0.001), - ); - // TODO: improve precision if possible - }); - } - - #[test] - fn should_set_new_reference_token() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - DAI, - balance!(0), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - balance!(1), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(0), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - - let price_a = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(balance!(1)), - true, - ) - .unwrap(); - - MBCPool::set_reference_asset(RuntimeOrigin::signed(alice()), DAI) - .expect("Failed to set new reference asset."); - - let price_b = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(balance!(1)), - true, - ) - .unwrap(); - - assert_ne!(price_a, price_b); - }); - } - - #[test] - fn should_set_price_bias() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - DAI, - balance!(0), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - 18, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - 18, - ), - ( - alice(), - XOR, - balance!(1), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - 18, - ), - ( - alice(), - VAL, - balance!(0), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - 18, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - 18, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - - let price_a = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(balance!(1)), - true, - ) - .unwrap(); - - MBCPool::set_price_bias(RuntimeOrigin::root(), balance!(123)) - .expect("Failed to set price bias"); - assert_eq!( - MBCPool::initial_price(), - FixedWrapper::from(balance!(123)).get().unwrap() - ); - - let price_b = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(balance!(1)), - true, - ) - .unwrap(); - - assert_ne!(price_a, price_b); - }); - } - - #[test] - fn should_set_price_change_config() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - DAI, - balance!(0), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - 18, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - 18, - ), - ( - alice(), - XOR, - balance!(1), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - 18, - ), - ( - alice(), - VAL, - balance!(0), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - 18, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - 18, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - - let price_a = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(balance!(1)), - true, - ) - .unwrap(); - - MBCPool::set_price_change_config(RuntimeOrigin::root(), balance!(12), balance!(2543)) - .expect("Failed to set price bias"); - - assert_eq!( - MBCPool::price_change_rate(), - FixedWrapper::from(balance!(12)).get().unwrap() - ); - assert_eq!( - MBCPool::price_change_step(), - FixedWrapper::from(balance!(2543)).get().unwrap() - ); - - let price_b = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(balance!(1)), - true, - ) - .unwrap(); - - assert_ne!(price_a, price_b); - }); - } - - #[test] - fn test_deducing_fee() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - DAI, - balance!(0), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(4000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - - let amount: Balance = balance!(2000); - let (quote_outcome_a, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_input(amount.clone()), - true, - ) - .unwrap(); - - assert_eq!(quote_outcome_a.amount, balance!(361.549938632002690452)); - assert_eq!(quote_outcome_a.fee, balance!(1.087913556565705186)); - - let (quote_outcome_b, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_input(amount.clone()), - false, - ) - .unwrap(); - - assert_eq!( - quote_outcome_b.amount, - quote_outcome_a.amount + quote_outcome_a.fee - ); - assert_eq!(quote_outcome_b.fee, balance!(0)); - - let (quote_outcome_a, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(amount.clone()), - true, - ) - .unwrap(); - - assert_eq!(quote_outcome_a.amount, balance!(11088.209839932824950839)); - assert_eq!(quote_outcome_a.fee, balance!(6.018054162487462387)); - - let (quote_outcome_b, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(amount.clone()), - false, - ) - .unwrap(); - - assert_eq!(quote_outcome_b.amount, balance!(11054.854916282129860020)); - assert_eq!(quote_outcome_b.fee, balance!(0)); - }) - } - - #[test] - fn similar_returns_should_be_identical() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - DAI, - balance!(0), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(4000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - - // Buy with desired input - let amount_a: Balance = balance!(2000); - let (quote_outcome_a, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_input(amount_a.clone()), - true, - ) - .unwrap(); - let (exchange_outcome_a, _) = MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_input(amount_a.clone(), Balance::zero()), - ) - .unwrap(); - let val_balance_a = Assets::free_balance(&VAL, &alice()).unwrap(); - let xor_balance_a = Assets::free_balance(&XOR, &alice()).unwrap(); - assert_eq!(quote_outcome_a.amount, exchange_outcome_a.amount); - assert_eq!(exchange_outcome_a.amount, xor_balance_a); - assert_eq!(val_balance_a, amount_a.clone()); - - // Buy with desired output - let amount_b: Balance = balance!(200); - let (quote_outcome_b, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(amount_b.clone()), - true, - ) - .unwrap(); - let (exchange_outcome_b, _) = MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_output(amount_b.clone(), Balance::max_value()), - ) - .unwrap(); - let val_balance_b = Assets::free_balance(&VAL, &alice()).unwrap(); - let xor_balance_b = Assets::free_balance(&XOR, &alice()).unwrap(); - assert_eq!(quote_outcome_b.amount, exchange_outcome_b.amount); - assert_eq!(xor_balance_a + amount_b.clone(), xor_balance_b); - assert_eq!(val_balance_b, amount_a.clone() - quote_outcome_b.amount); - - // Sell with desired input - let amount_c: Balance = balance!(300); - let (quote_outcome_c, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_input(amount_c.clone()), - true, - ) - .unwrap(); - let (exchange_outcome_c, _) = MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - SwapAmount::with_desired_input(amount_c.clone(), Balance::zero()), - ) - .unwrap(); - let val_balance_c = Assets::free_balance(&VAL, &alice()).unwrap(); - let xor_balance_c = Assets::free_balance(&XOR, &alice()).unwrap(); - assert_eq!(quote_outcome_c.amount, exchange_outcome_c.amount); - assert_eq!(val_balance_b + exchange_outcome_c.amount, val_balance_c); - assert_eq!(xor_balance_b - amount_c.clone(), xor_balance_c.clone()); - - // Sell with desired output - let amount_d: Balance = balance!(100); - let (quote_outcome_d, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(amount_d.clone()), - true, - ) - .unwrap(); - let (exchange_outcome_d, _) = MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_output(amount_d.clone(), Balance::max_value()), - ) - .unwrap(); - let val_balance_d = Assets::free_balance(&VAL, &alice()).unwrap(); - let xor_balance_d = Assets::free_balance(&XOR, &alice()).unwrap(); - assert_eq!(quote_outcome_d.amount, exchange_outcome_d.amount); - assert_eq!(val_balance_c - quote_outcome_d.amount, val_balance_d); - assert_eq!(xor_balance_c + amount_d.clone(), xor_balance_d); - }); - } - - #[test] - fn similar_returns_should_be_identical_tbcd() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - TBCD, - balance!(4000), - AssetSymbol(b"TBCD".to_vec()), - AssetName(b"SORA TBC Dollar".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - TBCD, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(TBCD, false).expect("Failed to initialize pool."); - - // Buy with desired input - let amount_a: Balance = balance!(2000); - let (quote_outcome_a, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &TBCD, - &XOR, - QuoteAmount::with_desired_input(amount_a.clone()), - true, - ) - .unwrap(); - let (exchange_outcome_a, _) = MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &TBCD, - &XOR, - SwapAmount::with_desired_input(amount_a.clone(), Balance::zero()), - ) - .unwrap(); - let tbcd_balance_a = Assets::free_balance(&TBCD, &alice()).unwrap(); - let xor_balance_a = Assets::free_balance(&XOR, &alice()).unwrap(); - assert_eq!(quote_outcome_a.amount, exchange_outcome_a.amount); - assert_eq!(exchange_outcome_a.amount, xor_balance_a); - assert_eq!(tbcd_balance_a, amount_a.clone()); - - // Buy with desired output - let amount_b: Balance = balance!(10); - let (quote_outcome_b, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &TBCD, - &XOR, - QuoteAmount::with_desired_output(amount_b.clone()), - true, - ) - .unwrap(); - let (exchange_outcome_b, _) = MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &TBCD, - &XOR, - SwapAmount::with_desired_output(amount_b.clone(), Balance::max_value()), - ) - .unwrap(); - let val_balance_b = Assets::free_balance(&TBCD, &alice()).unwrap(); - let tbcd_balance_b = Assets::free_balance(&XOR, &alice()).unwrap(); - assert_eq!(quote_outcome_b.amount, exchange_outcome_b.amount); - assert_eq!(xor_balance_a + amount_b.clone(), tbcd_balance_b); - assert_eq!(val_balance_b, amount_a.clone() - quote_outcome_b.amount); - - // Sell with desired input - let amount_c: Balance = balance!(10); - let (quote_outcome_c, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &XOR, - &TBCD, - QuoteAmount::with_desired_input(amount_c.clone()), - true, - ) - .unwrap(); - let (exchange_outcome_c, _) = MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &XOR, - &TBCD, - SwapAmount::with_desired_input(amount_c.clone(), Balance::zero()), - ) - .unwrap(); - let tbcd_balance_c = Assets::free_balance(&TBCD, &alice()).unwrap(); - let xor_balance_c = Assets::free_balance(&XOR, &alice()).unwrap(); - assert_eq!(quote_outcome_c.amount, exchange_outcome_c.amount); - assert_eq!(val_balance_b + exchange_outcome_c.amount, tbcd_balance_c); - assert_eq!(tbcd_balance_b - amount_c.clone(), xor_balance_c.clone()); - - // Sell with desired output - let amount_d: Balance = balance!(10); - let (quote_outcome_d, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &TBCD, - &XOR, - QuoteAmount::with_desired_output(amount_d.clone()), - true, - ) - .unwrap(); - let (exchange_outcome_d, _) = MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &TBCD, - &XOR, - SwapAmount::with_desired_output(amount_d.clone(), Balance::max_value()), - ) - .unwrap(); - let tbcd_balance_d = Assets::free_balance(&TBCD, &alice()).unwrap(); - let xor_balance_d = Assets::free_balance(&XOR, &alice()).unwrap(); - assert_eq!(quote_outcome_d.amount, exchange_outcome_d.amount); - assert_eq!(tbcd_balance_c - quote_outcome_d.amount, tbcd_balance_d); - assert_eq!(xor_balance_c + amount_d.clone(), xor_balance_d); - }); - } - - #[test] - fn should_receive_pswap_reward() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - balance!(700000), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(2000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - DAI, - balance!(200000), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - PSWAP, - balance!(0), - AssetSymbol(b"PSWAP".to_vec()), - AssetName(b"Polkaswap".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - DAI, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - MBCPool::initialize_pool_unchecked(DAI, false).expect("Failed to initialize pool."); - - MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_input(balance!(2000), Balance::zero()), - ) - .unwrap(); - - // no reward for non-incentived asset - VAL - let (limit, owned) = MBCPool::rewards(&alice()); - assert!(limit.is_zero()); - assert!(owned.is_zero()); - - MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, - &XOR, - SwapAmount::with_desired_input(balance!(1000), Balance::zero()), - ) - .unwrap(); - - let (limit, owned) = MBCPool::rewards(&alice()); - assert!(limit.is_zero()); - assert_eq!(owned, balance!(6099.239593179625249492)); - }); - } - - #[test] - fn should_calculate_ideal_reserves() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(2000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - - // calculate buy amount from zero to total supply of XOR - let xor_supply = Assets::total_issuance(&XOR).unwrap(); - let initial_state = MBCPool::buy_function( - &XOR, - &VAL, - PriceVariant::Buy, - (fixed_wrapper!(0) - FixedWrapper::from(xor_supply)) - .get() - .unwrap(), - ) - .unwrap(); - let current_state = - MBCPool::buy_function(&XOR, &VAL, PriceVariant::Buy, Fixed::ZERO).unwrap(); - let buy_amount: Balance = ((FixedWrapper::from(initial_state) - + FixedWrapper::from(current_state)) - / fixed_wrapper!(2) - * FixedWrapper::from(xor_supply)) - .try_into_balance() - .unwrap(); - - // get ideal reserves - let ideal_reserves = - MBCPool::ideal_reserves_reference_price(&VAL, PriceVariant::Buy, Fixed::ZERO) - .unwrap(); - - // actual amount should match to 80% of buy amount - assert_eq!(buy_amount, ideal_reserves); - }); - } - - #[test] - fn should_calculate_actual_reserves() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(2000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - DAI, - balance!(200000), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - PSWAP, - balance!(0), - AssetSymbol(b"PSWAP".to_vec()), - AssetName(b"Polkaswap".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - DAI, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - MBCPool::initialize_pool_unchecked(DAI, false).expect("Failed to initialize pool."); - MBCPool::set_reference_asset(RuntimeOrigin::signed(alice()), DAI).unwrap(); - - let val_amount: Balance = balance!(2000); - let dai_amount: Balance = balance!(200000); - - MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - SwapAmount::with_desired_input(val_amount.clone(), Balance::zero()), - ) - .unwrap(); - - MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, - &XOR, - SwapAmount::with_desired_input(dai_amount.clone(), Balance::zero()), - ) - .unwrap(); - - let val_actual_reserves = MBCPool::actual_reserves_reference_price( - &crate::mock::get_pool_reserves_account_id(), - &VAL, - PriceVariant::Buy, - ) - .unwrap(); - let dai_actual_reserves = MBCPool::actual_reserves_reference_price( - &crate::mock::get_pool_reserves_account_id(), - &DAI, - PriceVariant::Buy, - ) - .unwrap(); - let val_supposed_price = MockDEXApi::quote( - DEXId::Polkaswap, - &VAL, - &DAI, - QuoteAmount::with_desired_input(val_amount), - LiquiditySourceFilter::empty(DEXId::Polkaswap.into()), - true, - ) - .unwrap() - .amount; - let dai_supposed_price = dai_amount; +use crate::{ + mock::*, DistributionAccount, DistributionAccountData, DistributionAccounts, Error, Pallet, + RETRY_DISTRIBUTION_FREQUENCY, +}; +use common::assert_approx_eq; +use common::{ + self, balance, fixed, fixed_wrapper, + fixnum::ops::One as _, + fixnum::ops::Zero as _, + prelude::{Balance, FixedWrapper, QuoteAmount, SwapAmount, SwapOutcome}, + AssetInfoProvider, AssetName, AssetSymbol, DEXId, Fixed, LiquidityProxyTrait, LiquiditySource, + LiquiditySourceFilter, PriceVariant, TechPurpose, DAI, DEFAULT_BALANCE_PRECISION, PSWAP, TBCD, + USDT, VAL, XOR, XST, XSTUSD, +}; +use frame_support::assert_err; +use frame_support::assert_noop; +use frame_support::storage::{with_transaction, TransactionOutcome}; +use frame_support::traits::OnInitialize; +use sp_arithmetic::traits::Zero; +use sp_runtime::DispatchError; + +type MBCPool = Pallet; + +fn assert_swap_outcome( + left: SwapOutcome, + right: SwapOutcome, + tolerance: Balance, +) { + assert_approx_eq!(left.amount, right.amount, tolerance); + assert_approx_eq!(left.fee, right.fee, tolerance); +} - // compare values, also deduce 20% which are distributed and not stored in reserves - assert_eq!( - val_actual_reserves, - (FixedWrapper::from(val_supposed_price) * fixed_wrapper!(0.8)).into_balance() - ); - assert_eq!( - dai_actual_reserves, - (FixedWrapper::from(dai_supposed_price) * fixed_wrapper!(0.8)).into_balance() - ); - }); +fn ensure_distribution_accounts_balances( + distribution_accounts: DistributionAccounts< + DistributionAccountData>, + >, + balances: Vec, +) { + let distribution_accounts_array = distribution_accounts.xor_distribution_accounts_as_array(); + for (account, balance) in distribution_accounts_array.iter().copied().zip(balances) { + match account { + DistributionAccount::Account(account_id) => { + assert_eq!(Assets::total_balance(&XOR, account_id).unwrap(), balance,); + } + DistributionAccount::TechAccount(account_id) => { + assert_eq!(Technical::total_balance(&XOR, account_id).unwrap(), balance,); + } + } } +} - #[test] - fn fees_for_equivalent_trades_should_match() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - DAI, - balance!(0), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(2000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); +#[test] +fn should_calculate_price() { + let mut ext = ExtBuilder::default().build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), + // base case for buy + assert_eq!( + MBCPool::buy_function(&XOR, &VAL, PriceVariant::Buy, Fixed::ZERO) + .expect("failed to calculate buy price"), + fixed!(536.574420344053851907) + ); + assert_eq!( + MBCPool::buy_price( + &XOR, &VAL, + QuoteAmount::with_desired_output(balance!(100000)) + ) + .expect("failed to calculate buy assets price"), + fixed!(1151397.348365215316854563) + ); + assert_eq!( + MBCPool::buy_price( &XOR, - SwapAmount::with_desired_input(balance!(1000), Balance::zero()), + &VAL, + QuoteAmount::with_desired_input(balance!(1151397.348365215316854563)) ) - .unwrap(); + .expect("failed to calculate buy assets price"), + fixed!(99999.99999999999998516) // TODO: try to improve precision + ); - // Buy - let (price_a, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, + // base case for sell with empty reserves + assert_eq!( + MBCPool::sell_function(&XOR, &VAL, Fixed::ZERO) + .expect("failed to calculate sell price"), + fixed!(429.259536275243081525) + ); + assert_noop!( + MBCPool::sell_price( &XOR, - QuoteAmount::with_desired_input(balance!(100)), - true, - ) - .unwrap(); - let (price_b, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), &VAL, + QuoteAmount::with_desired_output(balance!(100000)) + ), + Error::::NotEnoughReserves, + ); + assert_noop!( + MBCPool::sell_price( &XOR, - QuoteAmount::with_desired_output(price_a.amount.clone()), - true, - ) - .unwrap(); - assert_eq!(price_a.fee, price_b.fee); - assert_eq!(price_a.fee, balance!(0.054394410184082514)); + &VAL, + QuoteAmount::with_desired_input(balance!(100000)) + ), + Error::::NotEnoughReserves, + ); - // Sell - let (price_c, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), + // base case for sell with some reserves + MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_input(balance!(100000), 0), + ) + .expect("Failed to buy XOR."); + assert_eq!( + MBCPool::sell_price( &XOR, &VAL, - QuoteAmount::with_desired_output(balance!(100)), - true, + QuoteAmount::with_desired_output(balance!(50000)) ) - .unwrap(); - let (price_d, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), + .expect("failed to calculate buy assets price"), + fixed!(15287.903511880099065775) + ); + assert_eq!( + MBCPool::sell_price( &XOR, &VAL, - QuoteAmount::with_desired_input(price_c.amount.clone()), - true, + QuoteAmount::with_desired_input(balance!(15287.903511880099065528)) ) - .unwrap(); - assert_eq!(price_c.fee, price_d.fee); - assert_eq!(price_c.fee, balance!(2.655958896716961113)); - }); - } + .expect("failed to calculate buy assets price"), + fixed!(49999.999999999999999697) // TODO: improve precision + ); + }); +} + +#[test] +fn should_calculate_tbcd_price() { + let mut ext = ExtBuilder::default().with_tbcd().build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + TBCD, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(TBCD, false).expect("Failed to initialize pool."); - #[test] - fn check_sell_penalty_based_on_collateralized_fraction() { + // base case for buy assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0)), - fixed!(0.09) + MBCPool::buy_function(&XOR, &TBCD, PriceVariant::Buy, Fixed::ZERO) + .expect("failed to calculate buy price"), + fixed!(100.7), ); assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.03)), - fixed!(0.09) + MBCPool::buy_price( + &XOR, + &TBCD, + QuoteAmount::with_desired_output(balance!(1000)) + ) + .expect("failed to calculate buy assets price"), + fixed!(100700.0), ); assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.05)), - fixed!(0.06) + MBCPool::buy_price( + &XOR, + &TBCD, + QuoteAmount::with_desired_input(balance!(100700.0)) + ) + .expect("failed to calculate buy assets price"), + fixed!(1000.0), ); + assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.075)), - fixed!(0.06) + MBCPool::buy_price( + &XOR, + &TBCD, + QuoteAmount::with_desired_output(balance!(100000)) + ) + .expect("failed to calculate buy assets price"), + fixed!(10070000.0), ); assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.1)), - fixed!(0.03) + MBCPool::buy_price( + &XOR, + &TBCD, + QuoteAmount::with_desired_input(balance!(10070000.0)) + ) + .expect("failed to calculate buy assets price"), + fixed!(100000.0), ); + + // base case for sell with empty reserves assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.15)), - fixed!(0.03) + MBCPool::sell_function(&XOR, &TBCD, Fixed::ZERO) + .expect("failed to calculate sell price"), + fixed!(80.56) ); - assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.2)), - fixed!(0.01) + assert_noop!( + MBCPool::sell_price( + &XOR, + &TBCD, + QuoteAmount::with_desired_output(balance!(100000)) + ), + Error::::NotEnoughReserves, ); - assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.25)), - fixed!(0.01) + assert_noop!( + MBCPool::sell_price( + &XOR, + &TBCD, + QuoteAmount::with_desired_input(balance!(100000)) + ), + Error::::NotEnoughReserves, ); + + // base case for sell with some reserves + MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, + &TBCD, + &XOR, + SwapAmount::with_desired_input(balance!(100000), 0), + ) + .expect("Failed to buy XOR."); assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.3)), - fixed!(0) + MBCPool::sell_price( + &XOR, + &TBCD, + QuoteAmount::with_desired_output(balance!(50000)) + ) + .expect("failed to calculate buy assets price"), + fixed!(1655.081098973849718635), ); assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.35)), - fixed!(0) + MBCPool::sell_price( + &XOR, + &TBCD, + QuoteAmount::with_desired_input(balance!(1655.081098973849718635)) + ) + .expect("failed to calculate buy assets price"), + fixed!(50000), ); - assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.5)), - fixed!(0) + }); +} + +#[test] +fn calculate_price_for_boundary_values() { + let mut ext = ExtBuilder::default().build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + // add some reserves + MBCPool::exchange( + &alice, + &alice, + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_input(balance!(1), 0), + ) + .expect("Failed to buy XOR."); + + assert_noop!( + MBCPool::sell_price( + &XOR, + &VAL, + QuoteAmount::with_desired_input(Balance::max_value()), + ), + Error::::PriceCalculationFailed, ); - assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(1)), - fixed!(0) + assert_noop!( + MBCPool::sell_price( + &XOR, + &VAL, + QuoteAmount::with_desired_output(Balance::max_value()), + ), + Error::::NotEnoughReserves, ); assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(2)), - fixed!(0) + MBCPool::sell_price(&XOR, &VAL, QuoteAmount::with_desired_input(Balance::zero()),), + Ok(fixed!(0)), ); assert_eq!( - MBCPool::map_collateralized_fraction_to_penalty(fixed!(10)), - fixed!(0) + MBCPool::sell_price( + &XOR, + &VAL, + QuoteAmount::with_desired_output(Balance::zero()), + ), + Ok(fixed!(0)), ); - } - #[test] - fn fee_penalties_should_be_applied() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(2000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - DAI, - balance!(20000000), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - PSWAP, - balance!(0), - AssetSymbol(b"PSWAP".to_vec()), - AssetName(b"Polkaswap".to_vec()), - DEFAULT_BALANCE_PRECISION, + assert_noop!( + MBCPool::buy_price( + &XOR, + &VAL, + QuoteAmount::with_desired_input(Balance::max_value()), ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, + Error::::PriceCalculationFailed, + ); + assert_noop!( + MBCPool::buy_price( + &XOR, + &VAL, + QuoteAmount::with_desired_output(Balance::max_value()), ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - DAI, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(DAI, false).expect("Failed to initialize pool."); - MBCPool::set_reference_asset(RuntimeOrigin::signed(alice()), DAI).unwrap(); - - let xor_supply = Assets::total_issuance(&XOR).unwrap(); - assert_eq!(xor_supply, balance!(100000)); - - // Depositing collateral #1: under 5% collateralized - MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, + Error::::PriceCalculationFailed, + ); + assert_eq!( + MBCPool::buy_price(&XOR, &VAL, QuoteAmount::with_desired_input(Balance::zero()),), + Ok(fixed!(0)), + ); + assert_eq!( + MBCPool::buy_price( &XOR, - SwapAmount::with_desired_input(balance!(200000), Balance::zero()), - ) - .unwrap(); - let xor_supply = Assets::total_issuance(&XOR).unwrap(); - assert_eq!(xor_supply, balance!(100724.916324262414168899)); + &VAL, + QuoteAmount::with_desired_output(Balance::zero()), + ), + Ok(fixed!(0)), + ); + }); +} - let (sell_price, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &XOR, - &DAI, - QuoteAmount::with_desired_input(balance!(100)), - true, - ) - .unwrap(); - assert_eq!(sell_price.fee, balance!(9.3)); +#[allow(clippy::type_complexity)] +fn bonding_curve_pool_init( + initial_reserves: Vec<(AssetId, Balance)>, +) -> Result< + DistributionAccounts< + DistributionAccountData< + DistributionAccount< + ::AccountId, + ::TechAccountId, + >, + >, + >, + DispatchError, +> { + let bonding_curve_tech_account_id = TechAccountId::Pure( + DEXId::Polkaswap, + TechPurpose::Identifier(b"bonding_curve_tech_account_id".to_vec()), + ); + Technical::register_tech_account_id(bonding_curve_tech_account_id.clone())?; + MBCPool::set_reserves_account_id(bonding_curve_tech_account_id.clone())?; + for (asset_id, balance) in initial_reserves { + Technical::mint(&asset_id, &bonding_curve_tech_account_id, balance)?; + } + let initial_price: Fixed = fixed!(200); + crate::InitialPrice::::put(initial_price); + + let val_holders_coefficient = fixed_wrapper!(0.5); + let val_holders_xor_alloc_coeff = val_holders_coefficient.clone() * fixed_wrapper!(0.9); + let val_holders_buy_back_coefficient = val_holders_coefficient.clone() * fixed_wrapper!(0.1); + let projects_coefficient: FixedWrapper = fixed_wrapper!(1) - val_holders_coefficient; + let projects_sora_citizens_coeff: FixedWrapper = + projects_coefficient.clone() * fixed_wrapper!(0.01); + let projects_stores_and_shops_coeff: FixedWrapper = + projects_coefficient.clone() * fixed_wrapper!(0.04); + let projects_parliament_and_development_coeff: FixedWrapper = + projects_coefficient.clone() * fixed_wrapper!(0.05); + let projects_other_coeff: FixedWrapper = projects_coefficient * fixed_wrapper!(0.9); + + debug_assert_eq!( + Fixed::ONE, + (val_holders_xor_alloc_coeff.clone() + + projects_sora_citizens_coeff.clone() + + projects_stores_and_shops_coeff.clone() + + projects_parliament_and_development_coeff + + projects_other_coeff.clone() + + val_holders_buy_back_coefficient.clone()) + .get() + .unwrap() + ); + + let xor_allocation = DistributionAccountData::new( + DistributionAccount::TechAccount(TechAccountId::Pure( + DEXId::Polkaswap, + TechPurpose::Identifier(b"xor_allocation".to_vec()), + )), + val_holders_xor_alloc_coeff.get().unwrap(), + ); + let sora_citizens = DistributionAccountData::new( + DistributionAccount::TechAccount(TechAccountId::Pure( + DEXId::Polkaswap, + TechPurpose::Identifier(b"sora_citizens".to_vec()), + )), + projects_sora_citizens_coeff.get().unwrap(), + ); + let stores_and_shops = DistributionAccountData::new( + DistributionAccount::TechAccount(TechAccountId::Pure( + DEXId::Polkaswap, + TechPurpose::Identifier(b"stores_and_shops".to_vec()), + )), + projects_stores_and_shops_coeff.get().unwrap(), + ); + let projects = DistributionAccountData::new( + DistributionAccount::TechAccount(TechAccountId::Pure( + DEXId::Polkaswap, + TechPurpose::Identifier(b"projects".to_vec()), + )), + projects_other_coeff.get().unwrap(), + ); + let val_holders = DistributionAccountData::new( + DistributionAccount::TechAccount(TechAccountId::Pure( + DEXId::Polkaswap, + TechPurpose::Identifier(b"val_holders".to_vec()), + )), + val_holders_buy_back_coefficient.get().unwrap(), + ); + let accounts = DistributionAccounts::<_> { + xor_allocation, + sora_citizens, + stores_and_shops, + projects, + val_holders, + }; + for account in &accounts.xor_distribution_accounts_as_array() { + match account { + DistributionAccount::Account(_) => continue, + DistributionAccount::TechAccount(account) => { + Technical::register_tech_account_id(account.clone())?; + } + } + } + MBCPool::set_distribution_accounts(accounts.clone()); + Ok(accounts) +} - // Depositing collateral #2: under 10% collateralized +#[test] +fn should_exchange_with_empty_reserves() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + balance!(10000), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + 0, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(205), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, - &XOR, - SwapAmount::with_desired_input(balance!(2000000), Balance::zero()), - ) - .unwrap(); - let xor_supply = Assets::total_issuance(&XOR).unwrap(); - assert_eq!(xor_supply, balance!(107896.889465954935399866)); - - let (sell_price, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), + alice, + alice, + &DEXId::Polkaswap, + &VAL, &XOR, - &DAI, - QuoteAmount::with_desired_input(balance!(100)), - true, + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); - assert_eq!(sell_price.fee, balance!(6.3)); - - // Depositing collateral #3: under 20% collateralized + .unwrap() + .0, + SwapOutcome::new( + balance!(5.529018162388484076), + balance!(0.003009027081243731), + ), + balance!(0.0001), + ); + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, - &XOR, - SwapAmount::with_desired_input(balance!(2000000), Balance::zero()), - ) - .unwrap(); - let xor_supply = Assets::total_issuance(&XOR).unwrap(); - assert_eq!(xor_supply, balance!(114934.359190755661026458)); - - let (sell_price, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), + alice, + alice, + &DEXId::Polkaswap, &XOR, - &DAI, - QuoteAmount::with_desired_input(balance!(100)), - true, + &VAL, + SwapAmount::with_desired_input(balance!(1), Balance::zero()), ) - .unwrap(); - assert_eq!(sell_price.fee, balance!(3.3)); + .unwrap() + .0, + SwapOutcome::new(balance!(2.100439516374830873), balance!(0.093)), + balance!(0.0001), + ); + }); +} - // Depositing collateral #4: under 30% collateralized +#[test] +fn should_exchange_tbcd_with_empty_reserves() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + 0, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + TBCD, + balance!(205), + AssetSymbol(b"TBCD".to_vec()), + AssetName(b"SORA TBC Dollar".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + TBCD, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(TBCD, false).expect("Failed to initialize pool."); + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, - &XOR, - SwapAmount::with_desired_input(balance!(4000000), Balance::zero()), - ) - .unwrap(); - let xor_supply = Assets::total_issuance(&XOR).unwrap(); - assert_eq!(xor_supply, balance!(128633.975165230400000080)); - - let (sell_price, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), + alice, + alice, + &DEXId::Polkaswap, + &TBCD, &XOR, - &DAI, - QuoteAmount::with_desired_input(balance!(100)), - true, + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); - assert_eq!(sell_price.fee, balance!(1.3)); - - // Depositing collateral #5: over 30% collateralized + .unwrap() + .0, + SwapOutcome::new( + balance!(101.003009027081243711), + balance!(0.003009027081243731), + ), + balance!(0.0001), + ); + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, - &XOR, - SwapAmount::with_desired_input(balance!(7000000), Balance::zero()), - ) - .unwrap(); - let xor_supply = Assets::total_issuance(&XOR).unwrap(); - assert_eq!(xor_supply, balance!(151530.994236602104619871)); - - let (sell_price, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), + alice, + alice, + &DEXId::Polkaswap, &XOR, - &DAI, - QuoteAmount::with_desired_input(balance!(100)), - true, + &TBCD, + SwapAmount::with_desired_input(balance!(1), Balance::zero()), ) - .unwrap(); - assert_eq!(sell_price.fee, balance!(0.3)); - }); - } + .unwrap() + .0, + SwapOutcome::new(balance!(38.370385852073146860), balance!(0.093)), + balance!(0.0001), + ); + }); +} - #[test] - fn sequential_rewards_adequacy_check() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - XOR, - balance!(250000), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(2000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - DAI, - balance!(2000000), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - PSWAP, - balance!(0), - AssetSymbol(b"PSWAP".to_vec()), - AssetName(b"Polkaswap".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - DAI, - ) +#[test] +fn should_exchange_with_nearly_full_reserves() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + balance!(10), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(10000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + balance!(10000), + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let initial_price: Fixed = fixed!(200); + crate::InitialPrice::::put(initial_price); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - MBCPool::initialize_pool_unchecked(DAI, false).expect("Failed to initialize pool."); - - // XOR total supply in network is 350000 - let xor_total_supply: FixedWrapper = Assets::total_issuance(&XOR).unwrap().into(); - assert_eq!(xor_total_supply.clone().into_balance(), balance!(350000)); - // initial XOR price is $264 - let xor_ideal_reserves: FixedWrapper = MBCPool::ideal_reserves_reference_price( + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + let total_issuance = Assets::total_issuance(&XOR).unwrap(); + let reserve_amount_expected = FixedWrapper::from(total_issuance) + * MBCPool::sell_function(&XOR, &VAL, Fixed::ZERO).unwrap(); + let pool_reference_amount = reserve_amount_expected + - FixedWrapper::from( + MBCPool::buy_function(&XOR, &VAL, PriceVariant::Buy, Fixed::ZERO).unwrap(), + ) / balance!(2); + let pool_reference_amount = pool_reference_amount.into_balance(); + let pool_val_amount = MockDEXApi::quote( + DEXId::Polkaswap, + &USDT, + &VAL, + QuoteAmount::with_desired_input(pool_reference_amount), + LiquiditySourceFilter::empty(DEXId::Polkaswap), + true, + ) + .unwrap(); + let distribution_accounts = + bonding_curve_pool_init(vec![(VAL, pool_val_amount.amount)]).unwrap(); + let alice = &alice(); + assert_swap_outcome( + MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, &VAL, - PriceVariant::Buy, - Default::default(), + &XOR, + SwapAmount::with_desired_output(balance!(1000), Balance::max_value()), ) .unwrap() - .into(); - assert_eq!( - (xor_ideal_reserves / xor_total_supply).into_balance(), - balance!(330.890052356020942408) - ); - // pswap price is $10 on mock secondary market - assert_eq!( - MockDEXApi::quote( - DEXId::Polkaswap, - &PSWAP, - &DAI, - QuoteAmount::with_desired_input(balance!(1)), - MBCPool::self_excluding_filter(), - true - ) - .unwrap() - .amount, - balance!(10.173469387755102041) - ); - + .0, + SwapOutcome::new( + balance!(5536.708257819426729513), + balance!(3.009027081243731193), + ), + balance!(0.0001), + ); + ensure_distribution_accounts_balances( + distribution_accounts, + vec![ + balance!(2.760049066522984224), + balance!(11.040196266091936898), + balance!(248.404415987068580219), + ], + ); + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, + alice, + alice, + &DEXId::Polkaswap, &XOR, + &VAL, SwapAmount::with_desired_input(balance!(1000), Balance::zero()), ) - .unwrap(); - - let (limit, owned_1) = MBCPool::rewards(&alice()); - assert!(limit.is_zero()); - assert_eq!(owned_1, balance!(21036.472370353787480367)); + .unwrap() + .0, + SwapOutcome::new( + balance!(4365.335149368998667748), + balance!(3.000000000000000000), + ), + balance!(0.0001), + ); + }); +} +#[test] +fn should_exchange_with_full_reserves() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + balance!(10), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(10000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + balance!(10000), + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let initial_price: Fixed = fixed!(200); + crate::InitialPrice::::put(initial_price); + let total_issuance = Assets::total_issuance(&XOR).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) + .expect("Failed to register trading pair."); + TradingPair::register( + RuntimeOrigin::signed(alice()), + DEXId::Polkaswap, + XOR, + XSTUSD, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + let pool_reference_amount = FixedWrapper::from(total_issuance) + * MBCPool::sell_function(&XOR, &VAL, Fixed::ZERO).unwrap(); + let pool_reference_amount = pool_reference_amount.into_balance(); + let pool_val_amount = MockDEXApi::quote( + DEXId::Polkaswap, + &USDT, + &VAL, + QuoteAmount::with_desired_input(pool_reference_amount), + LiquiditySourceFilter::empty(DEXId::Polkaswap), + true, + ) + .unwrap(); + + let distribution_accounts = + bonding_curve_pool_init(vec![(VAL, pool_val_amount.amount)]).unwrap(); + let alice = &alice(); + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, + alice, + alice, + &DEXId::Polkaswap, + &VAL, &XOR, - SwapAmount::with_desired_input(balance!(10000), Balance::zero()), + SwapAmount::with_desired_output(balance!(1000), Balance::max_value()), ) - .unwrap(); - - let (limit, owned_2) = MBCPool::rewards(&alice()); - assert!(limit.is_zero()); - assert_eq!(owned_2 - owned_1, balance!(210336.209418679523304856)); - + .unwrap() + .0, + SwapOutcome::new( + balance!(5536.708257819426729513), + balance!(3.009027081243731193), + ), + balance!(0.0001), + ); + ensure_distribution_accounts_balances( + distribution_accounts, + vec![ + balance!(2.760049066522984224), + balance!(11.040196266091936898), + balance!(248.404415987068580219), + ], + ); + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &DAI, + alice, + alice, + &DEXId::Polkaswap, &XOR, - SwapAmount::with_desired_input(balance!(1000000), Balance::zero()), - ) - .unwrap(); - - let (limit, owned_3) = MBCPool::rewards(&alice()); - assert!(limit.is_zero()); - assert_eq!(owned_3 - owned_2, balance!(20769070.485987076318293437)); - }); - } - - #[test] - fn distribution_passes_on_first_attempt() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - balance!(10000), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - 0, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - 0, - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XST, - 0, - AssetSymbol(b"XST".to_vec()), - AssetName(b"XST".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - // secondary market is initialized with enough funds - MockDEXApi::init().unwrap(); - let distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - USDT, + &VAL, + SwapAmount::with_desired_input(balance!(1000), Balance::zero()), ) + .unwrap() + .0, + SwapOutcome::new( + balance!(4365.335415603766574971), + balance!(3.000000000000000000), + ), + balance!(0.0001), + ); + }); +} + +#[test] +fn should_not_sell_without_reserves() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + 0, + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + balance!(1), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + 0, + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .with_tbcd() + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, TBCD) .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + MBCPool::initialize_pool_unchecked(TBCD, false).expect("Failed to initialize pool."); + let alice = &alice(); + + assert_err!( + MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, + &XOR, + &VAL, + SwapAmount::with_desired_input(balance!(1), Balance::zero()), + ), + Error::::NotEnoughReserves + ); - // check pending list and reserves before trade - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!(MBCPool::pending_free_reserves(), vec![]); - assert_eq!(free_reserves_balance, balance!(0)); + assert_err!( + MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, + &XOR, + &TBCD, + SwapAmount::with_desired_input(balance!(1), Balance::zero()), + ), + Error::::NotEnoughReserves + ); + }); +} - ensure_distribution_accounts_balances( - distribution_accounts.clone(), - vec![balance!(0), balance!(0), balance!(0)], +#[test] +fn swaps_should_be_additive() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + 0, + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + 0, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(10000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let alice = &alice(); + let _ = bonding_curve_pool_init(Vec::new()).unwrap(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + let amount = balance!(100); // TODO: investigate strange precision error dependency on value + let parts = 5; + + let whole_outcome = with_transaction(|| { + let whole_outcome = MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_output(amount, Balance::max_value()), ); + TransactionOutcome::Rollback(whole_outcome) + }); - // perform buy on tbc - assert_eq!( + let cumulative_outcome = (0..parts) + .map(|_i| { MBCPool::exchange( alice, alice, - &DEXId::Polkaswap.into(), - &USDT, + &DEXId::Polkaswap, + &VAL, &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), + SwapAmount::with_desired_output(amount / parts, Balance::max_value()), ) .unwrap() - .0, - SwapOutcome::new( - balance!(275.621555395065931189), - balance!(0.003009027081243731) - ) - ); - - // check pending list and free reserves account - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!(MBCPool::pending_free_reserves(), vec![]); - assert_eq!(free_reserves_balance, balance!(0)); - - ensure_distribution_accounts_balances( - distribution_accounts, - vec![ - balance!(0.002747946907288807), - balance!(0.010991787629155229), - balance!(0.247315221655992660), - ], - ); - }) - } + }) + .fold( + SwapOutcome::new(Balance::zero(), Balance::zero()), + |acc, x| SwapOutcome { + amount: acc.amount + x.0.amount, + fee: acc.fee + x.0.fee, + }, + ); + assert_swap_outcome( + whole_outcome.unwrap().0, + cumulative_outcome, + balance!(0.001), + ); + // TODO: improve precision if possible + }); +} - #[test] - fn distribution_fails_on_first_attempt() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - balance!(10000), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - 350000, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - 0, - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XST, - 0, - AssetSymbol(b"XST".to_vec()), - AssetName(b"XST".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - // secondary market is initialized without funds - MockDEXApi::init_without_reserves().unwrap(); - let distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - USDT, - ) - .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) +#[test] +fn should_set_new_reference_token() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + DAI, + balance!(0), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + balance!(1), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(0), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); - - // check pending list and reserves before trade - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!(MBCPool::pending_free_reserves(), vec![]); - assert_eq!(free_reserves_balance, balance!(0)); - - // perform buy on tbc - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(200.602181641794149028), - balance!(0.003009027081243731), - ), - balance!(0.0001), - ); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + let price_a = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(balance!(1)), + true, + ) + .unwrap(); + + MBCPool::set_reference_asset(RuntimeOrigin::signed(alice()), DAI) + .expect("Failed to set new reference asset."); + + let price_b = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(balance!(1)), + true, + ) + .unwrap(); + + assert_ne!(price_a, price_b); + }); +} - // check pending list and free reserves account - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, free_reserves_balance.clone())] - ); - assert_eq!(free_reserves_balance, balance!(40.120436328358829805)); - - // attempt for distribution, still not enough reserves - MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); - let free_reserves_balance_2 = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, free_reserves_balance.clone())] - ); - assert_eq!(free_reserves_balance_2, free_reserves_balance); - - // exchange becomes possible for stored free reserves - MockDEXApi::add_reserves(vec![ - (XOR, balance!(100000)), - (VAL, balance!(100000)), - (USDT, balance!(1000000)), - (XST, balance!(1000000)), - ]) - .unwrap(); - - // actual accounts check before distribution - ensure_distribution_accounts_balances( - distribution_accounts.clone(), - vec![balance!(0), balance!(0), balance!(0)], - ); +#[test] +fn should_set_price_bias() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + DAI, + balance!(0), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + 18, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + 18, + ), + ( + alice(), + XOR, + balance!(1), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + 18, + ), + ( + alice(), + VAL, + balance!(0), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + 18, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + 18, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + let price_a = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(balance!(1)), + true, + ) + .unwrap(); + + MBCPool::set_price_bias(RuntimeOrigin::root(), balance!(123)) + .expect("Failed to set price bias"); + assert_eq!( + MBCPool::initial_price(), + FixedWrapper::from(balance!(123)).get().unwrap() + ); - // attempt for distribution before retry period - MBCPool::on_initialize((RETRY_DISTRIBUTION_FREQUENCY - 1).into()); - let free_reserves_balance_3 = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, free_reserves_balance.clone())] - ); - assert_eq!(free_reserves_balance_3, free_reserves_balance); - - // successful attempt for distribution - MBCPool::on_initialize((RETRY_DISTRIBUTION_FREQUENCY * 2).into()); - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!(MBCPool::pending_free_reserves(), vec![]); - assert_eq!(free_reserves_balance, balance!(0)); - - // actual accounts check after distribution - ensure_distribution_accounts_balances( - distribution_accounts, - vec![ - balance!(0.002000003750968687), - balance!(0.008000015003874750), - balance!(0.180000337587181890), - ], - ); - }) - } + let price_b = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(balance!(1)), + true, + ) + .unwrap(); + + assert_ne!(price_a, price_b); + }); +} - #[test] - fn multiple_pending_distributions_are_executed() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - balance!(10000), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - 350000, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - 0, - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XST, - 0, - AssetSymbol(b"XST".to_vec()), - AssetName(b"XST".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - // secondary market is initialized without funds - MockDEXApi::init_without_reserves().unwrap(); - let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - USDT, - ) - .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) +#[test] +fn should_set_price_change_config() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + DAI, + balance!(0), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + 18, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + 18, + ), + ( + alice(), + XOR, + balance!(1), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + 18, + ), + ( + alice(), + VAL, + balance!(0), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + 18, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + 18, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); - // check pending list and reserves before trade - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!(MBCPool::pending_free_reserves(), vec![]); - assert_eq!(free_reserves_balance, balance!(0)); + let price_a = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(balance!(1)), + true, + ) + .unwrap(); - // perform buy on tbc multiple times - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(200.602181641794149028), - balance!(0.003009027081243731), - ), - balance!(0.0001), - ); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(200.602931835531681746), - balance!(0.003009027081243731), - ), - balance!(0.0001), - ); - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(200.603682029269214463), - balance!(0.003009027081243731), - ), - balance!(0.0001), - ); + MBCPool::set_price_change_config(RuntimeOrigin::root(), balance!(12), balance!(2543)) + .expect("Failed to set price bias"); - // check pending list and reserves after trade - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - let expected_balances = [ - balance!(40.120436328358829805), - balance!(40.120586367106336349), - balance!(40.120736405853842892), - ]; - assert_eq!( - MBCPool::pending_free_reserves(), - vec![ - (USDT, expected_balances[0]), - (USDT, expected_balances[1]), - (USDT, expected_balances[2]) - ] - ); - assert_eq!( - free_reserves_balance, - expected_balances.iter().fold(balance!(0), |a, b| a + b) - ); + assert_eq!( + MBCPool::price_change_rate(), + FixedWrapper::from(balance!(12)).get().unwrap() + ); + assert_eq!( + MBCPool::price_change_step(), + FixedWrapper::from(balance!(2543)).get().unwrap() + ); - // exchange becomes available - MockDEXApi::add_reserves(vec![ - (XOR, balance!(100000)), - (VAL, balance!(100000)), - (USDT, balance!(1000000)), - (XST, balance!(1000000)), - ]) - .unwrap(); - MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!(MBCPool::pending_free_reserves(), vec![]); - assert_eq!(free_reserves_balance, balance!(0)); - }) - } + let price_b = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(balance!(1)), + true, + ) + .unwrap(); + + assert_ne!(price_a, price_b); + }); +} - #[test] - fn large_pending_amount_dont_interfere_new_trades() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - balance!(999999999999999), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - 0, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - 0, - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - USDT, - ) +#[test] +fn test_deducing_fee() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + DAI, + balance!(0), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(4000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); - - // perform large buy on tbc - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(100000000), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(3789817571942.618173119057163101), - balance!(300902.708124373119358074), - ), - balance!(0.0001), - ); - - // check that failed distribution was postponed - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, free_reserves_balance)] - ); - assert_eq!( - free_reserves_balance, - balance!(757963514388.523634623811432620) - ); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + let amount: Balance = balance!(2000); + let (quote_outcome_a, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_input(amount), + true, + ) + .unwrap(); + + assert_eq!(quote_outcome_a.amount, balance!(361.549938632002690452)); + assert_eq!(quote_outcome_a.fee, balance!(1.087913556565705186)); + + let (quote_outcome_b, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_input(amount), + false, + ) + .unwrap(); - // attempt for distribution - MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); - let free_reserves_balance_2 = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, free_reserves_balance_2)] - ); - assert_eq!(free_reserves_balance_2, free_reserves_balance); + assert_eq!( + quote_outcome_b.amount, + quote_outcome_a.amount + quote_outcome_a.fee + ); + assert_eq!(quote_outcome_b.fee, balance!(0)); + + let (quote_outcome_a, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(amount), + true, + ) + .unwrap(); + + assert_eq!(quote_outcome_a.amount, balance!(11088.209839932824950839)); + assert_eq!(quote_outcome_a.fee, balance!(6.018054162487462387)); + + let (quote_outcome_b, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(amount), + false, + ) + .unwrap(); + + assert_eq!(quote_outcome_b.amount, balance!(11054.854916282129860020)); + assert_eq!(quote_outcome_b.fee, balance!(0)); + }) +} - // another exchange with reasonable amount - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(100), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(7529503.255499584322288265), - balance!(0.300902708124373119), - ), - balance!(0.0001), - ); +#[test] +fn similar_returns_should_be_identical() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + DAI, + balance!(0), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(4000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + // Buy with desired input + let amount_a: Balance = balance!(2000); + let (quote_outcome_a, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_input(amount_a), + true, + ) + .unwrap(); + let (exchange_outcome_a, _) = MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_input(amount_a, Balance::zero()), + ) + .unwrap(); + let val_balance_a = Assets::free_balance(&VAL, &alice()).unwrap(); + let xor_balance_a = Assets::free_balance(&XOR, &alice()).unwrap(); + assert_eq!(quote_outcome_a.amount, exchange_outcome_a.amount); + assert_eq!(exchange_outcome_a.amount, xor_balance_a); + assert_eq!(val_balance_a, amount_a.clone()); + + // Buy with desired output + let amount_b: Balance = balance!(200); + let (quote_outcome_b, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(amount_b), + true, + ) + .unwrap(); + let (exchange_outcome_b, _) = MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_output(amount_b, Balance::max_value()), + ) + .unwrap(); + let val_balance_b = Assets::free_balance(&VAL, &alice()).unwrap(); + let xor_balance_b = Assets::free_balance(&XOR, &alice()).unwrap(); + assert_eq!(quote_outcome_b.amount, exchange_outcome_b.amount); + assert_eq!(xor_balance_a + amount_b, xor_balance_b); + assert_eq!(val_balance_b, amount_a - quote_outcome_b.amount); + + // Sell with desired input + let amount_c: Balance = balance!(300); + let (quote_outcome_c, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_input(amount_c), + true, + ) + .unwrap(); + let (exchange_outcome_c, _) = MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &XOR, + &VAL, + SwapAmount::with_desired_input(amount_c, Balance::zero()), + ) + .unwrap(); + let val_balance_c = Assets::free_balance(&VAL, &alice()).unwrap(); + let xor_balance_c = Assets::free_balance(&XOR, &alice()).unwrap(); + assert_eq!(quote_outcome_c.amount, exchange_outcome_c.amount); + assert_eq!(val_balance_b + exchange_outcome_c.amount, val_balance_c); + assert_eq!(xor_balance_b - amount_c, xor_balance_c.clone()); + + // Sell with desired output + let amount_d: Balance = balance!(100); + let (quote_outcome_d, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(amount_d), + true, + ) + .unwrap(); + let (exchange_outcome_d, _) = MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_output(amount_d, Balance::max_value()), + ) + .unwrap(); + let val_balance_d = Assets::free_balance(&VAL, &alice()).unwrap(); + let xor_balance_d = Assets::free_balance(&XOR, &alice()).unwrap(); + assert_eq!(quote_outcome_d.amount, exchange_outcome_d.amount); + assert_eq!(val_balance_c - quote_outcome_d.amount, val_balance_d); + assert_eq!(xor_balance_c + amount_d, xor_balance_d); + }); +} - // second distribution was successful, pending list didn't change - let free_reserves_balance_3 = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, free_reserves_balance_3)] - ); - assert_eq!(free_reserves_balance_3, free_reserves_balance_2); - }) - } +#[test] +fn similar_returns_should_be_identical_tbcd() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + TBCD, + balance!(4000), + AssetSymbol(b"TBCD".to_vec()), + AssetName(b"SORA TBC Dollar".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, TBCD) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(TBCD, false).expect("Failed to initialize pool."); + + // Buy with desired input + let amount_a: Balance = balance!(2000); + let (quote_outcome_a, _) = MBCPool::quote( + &DEXId::Polkaswap, + &TBCD, + &XOR, + QuoteAmount::with_desired_input(amount_a), + true, + ) + .unwrap(); + let (exchange_outcome_a, _) = MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &TBCD, + &XOR, + SwapAmount::with_desired_input(amount_a, Balance::zero()), + ) + .unwrap(); + let tbcd_balance_a = Assets::free_balance(&TBCD, &alice()).unwrap(); + let xor_balance_a = Assets::free_balance(&XOR, &alice()).unwrap(); + assert_eq!(quote_outcome_a.amount, exchange_outcome_a.amount); + assert_eq!(exchange_outcome_a.amount, xor_balance_a); + assert_eq!(tbcd_balance_a, amount_a.clone()); + + // Buy with desired output + let amount_b: Balance = balance!(10); + let (quote_outcome_b, _) = MBCPool::quote( + &DEXId::Polkaswap, + &TBCD, + &XOR, + QuoteAmount::with_desired_output(amount_b), + true, + ) + .unwrap(); + let (exchange_outcome_b, _) = MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &TBCD, + &XOR, + SwapAmount::with_desired_output(amount_b, Balance::max_value()), + ) + .unwrap(); + let val_balance_b = Assets::free_balance(&TBCD, &alice()).unwrap(); + let tbcd_balance_b = Assets::free_balance(&XOR, &alice()).unwrap(); + assert_eq!(quote_outcome_b.amount, exchange_outcome_b.amount); + assert_eq!(xor_balance_a + amount_b, tbcd_balance_b); + assert_eq!(val_balance_b, amount_a - quote_outcome_b.amount); + + // Sell with desired input + let amount_c: Balance = balance!(10); + let (quote_outcome_c, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &TBCD, + QuoteAmount::with_desired_input(amount_c), + true, + ) + .unwrap(); + let (exchange_outcome_c, _) = MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &XOR, + &TBCD, + SwapAmount::with_desired_input(amount_c, Balance::zero()), + ) + .unwrap(); + let tbcd_balance_c = Assets::free_balance(&TBCD, &alice()).unwrap(); + let xor_balance_c = Assets::free_balance(&XOR, &alice()).unwrap(); + assert_eq!(quote_outcome_c.amount, exchange_outcome_c.amount); + assert_eq!(val_balance_b + exchange_outcome_c.amount, tbcd_balance_c); + assert_eq!(tbcd_balance_b - amount_c, xor_balance_c.clone()); + + // Sell with desired output + let amount_d: Balance = balance!(10); + let (quote_outcome_d, _) = MBCPool::quote( + &DEXId::Polkaswap, + &TBCD, + &XOR, + QuoteAmount::with_desired_output(amount_d), + true, + ) + .unwrap(); + let (exchange_outcome_d, _) = MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &TBCD, + &XOR, + SwapAmount::with_desired_output(amount_d, Balance::max_value()), + ) + .unwrap(); + let tbcd_balance_d = Assets::free_balance(&TBCD, &alice()).unwrap(); + let xor_balance_d = Assets::free_balance(&XOR, &alice()).unwrap(); + assert_eq!(quote_outcome_d.amount, exchange_outcome_d.amount); + assert_eq!(tbcd_balance_c - quote_outcome_d.amount, tbcd_balance_d); + assert_eq!(xor_balance_c + amount_d, xor_balance_d); + }); +} - #[test] - fn multiple_pending_distributions_with_large_request_dont_interfere_when_exchange_becomes_available( - ) { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - balance!(999999999999999), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - 350000, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - 0, - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XST, - 0, - AssetSymbol(b"XST".to_vec()), - AssetName(b"XST".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - // secondary market is initialized without funds - MockDEXApi::init_without_reserves().unwrap(); - let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - USDT, - ) +#[test] +fn should_receive_pswap_reward() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + balance!(700000), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(2000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + DAI, + balance!(200000), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + PSWAP, + balance!(0), + AssetSymbol(b"PSWAP".to_vec()), + AssetName(b"Polkaswap".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, DAI) .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); - - // perform large buy on tbc - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(100000000), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(3782315634567.290994901504505143), - balance!(300902.708124373119358074), - ), - balance!(0.0001), - ); - - // another exchange with reasonable amount, still current market can't handle it - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(100), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(7522001.318124257144070739), - balance!(0.300902708124373119), - ), - balance!(0.0001), - ); - - // attempt for distribution - MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - let expected_balances = [ - balance!(756463126913.458198980300901028), - balance!(1504400.263624851428814147), - ]; - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, expected_balances[0]), (USDT, expected_balances[1])] - ); - assert_eq!( - free_reserves_balance, - expected_balances.iter().fold(balance!(0), |a, b| a + b) - ); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + MBCPool::initialize_pool_unchecked(DAI, false).expect("Failed to initialize pool."); + + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_input(balance!(2000), Balance::zero()), + ) + .unwrap(); + + // no reward for non-incentived asset - VAL + let (limit, owned) = MBCPool::rewards(alice()); + assert!(limit.is_zero()); + assert!(owned.is_zero()); + + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(1000), Balance::zero()), + ) + .unwrap(); + + let (limit, owned) = MBCPool::rewards(alice()); + assert!(limit.is_zero()); + assert_eq!(owned, balance!(6099.239593179625249492)); + }); +} - // funds are added and one of exchanges becomes available, unavailable is left as pending - MockDEXApi::add_reserves(vec![ - (XOR, balance!(100000)), - (VAL, balance!(100000)), - (USDT, balance!(1000000)), - (XST, balance!(1000000)), - ]) - .unwrap(); - MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, expected_balances[0])] - ); - assert_eq!(free_reserves_balance, expected_balances[0]); - }) - } +#[test] +fn should_calculate_ideal_reserves() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(2000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + // calculate buy amount from zero to total supply of XOR + let xor_supply = Assets::total_issuance(&XOR).unwrap(); + let initial_state = MBCPool::buy_function( + &XOR, + &VAL, + PriceVariant::Buy, + (fixed_wrapper!(0) - FixedWrapper::from(xor_supply)) + .get() + .unwrap(), + ) + .unwrap(); + let current_state = + MBCPool::buy_function(&XOR, &VAL, PriceVariant::Buy, Fixed::ZERO).unwrap(); + let buy_amount: Balance = ((FixedWrapper::from(initial_state) + + FixedWrapper::from(current_state)) + / fixed_wrapper!(2) + * FixedWrapper::from(xor_supply)) + .try_into_balance() + .unwrap(); + + // get ideal reserves + let ideal_reserves = + MBCPool::ideal_reserves_reference_price(&VAL, PriceVariant::Buy, Fixed::ZERO).unwrap(); + + // actual amount should match to 80% of buy amount + assert_eq!(buy_amount, ideal_reserves); + }); +} - #[test] - fn xor_exchange_passes_but_val_exchange_fails_reserves_are_reverted() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - balance!(10000), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - 350000, - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - 0, - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XST, - 0, - AssetSymbol(b"XST".to_vec()), - AssetName(b"XST".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - // secondary market is initialized without funds - MockDEXApi::init_without_reserves().unwrap(); - let distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - USDT, - ) +#[test] +fn should_calculate_actual_reserves() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(2000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + DAI, + balance!(200000), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + PSWAP, + balance!(0), + AssetSymbol(b"PSWAP".to_vec()), + AssetName(b"Polkaswap".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, DAI) .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); - - // perform buy on tbc - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(200.602181641794149028), - balance!(0.003009027081243731), - ), - balance!(0.0001), - ); - - // check pending list and free reserves account - let free_reserves_balance = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, free_reserves_balance.clone())] - ); - assert_eq!(free_reserves_balance, balance!(40.120436328358829805)); - - // exchange becomes possible, but not for val, so second part of distribution fails - MockDEXApi::add_reserves(vec![ - (XOR, balance!(100000)), - (VAL, balance!(0)), - (USDT, balance!(1000000)), - ]) - .unwrap(); - - // check pending list - MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); - let free_reserves_balance_2 = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, free_reserves_balance.clone())] - ); - - // val buy back and burn failed so exchanged xor is reverted - assert_eq!(free_reserves_balance_2, free_reserves_balance); - ensure_distribution_accounts_balances( - distribution_accounts.clone(), - vec![balance!(0), balance!(0), balance!(0)], - ); - - // another buy is performed - assert_swap_outcome( - MBCPool::exchange( - alice, - alice, - &DEXId::Polkaswap.into(), - &USDT, - &XOR, - SwapAmount::with_desired_output(balance!(1), Balance::max_value()), - ) - .unwrap() - .0, - SwapOutcome::new( - balance!(275.622305588803464169), - balance!(0.003009027081243731), - ), - balance!(0.0001), - ); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + MBCPool::initialize_pool_unchecked(DAI, false).expect("Failed to initialize pool."); + MBCPool::set_reference_asset(RuntimeOrigin::signed(alice()), DAI).unwrap(); + + let val_amount: Balance = balance!(2000); + let dai_amount: Balance = balance!(200000); + + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_input(val_amount, Balance::zero()), + ) + .unwrap(); + + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(dai_amount, Balance::zero()), + ) + .unwrap(); + + let val_actual_reserves = MBCPool::actual_reserves_reference_price( + &crate::mock::get_pool_reserves_account_id(), + &VAL, + PriceVariant::Buy, + ) + .unwrap(); + let dai_actual_reserves = MBCPool::actual_reserves_reference_price( + &crate::mock::get_pool_reserves_account_id(), + &DAI, + PriceVariant::Buy, + ) + .unwrap(); + let val_supposed_price = MockDEXApi::quote( + DEXId::Polkaswap, + &VAL, + &DAI, + QuoteAmount::with_desired_input(val_amount), + LiquiditySourceFilter::empty(DEXId::Polkaswap), + true, + ) + .unwrap() + .amount; + let dai_supposed_price = dai_amount; + + // compare values, also deduce 20% which are distributed and not stored in reserves + assert_eq!( + val_actual_reserves, + (FixedWrapper::from(val_supposed_price) * fixed_wrapper!(0.8)).into_balance() + ); + assert_eq!( + dai_actual_reserves, + (FixedWrapper::from(dai_supposed_price) * fixed_wrapper!(0.8)).into_balance() + ); + }); +} - // there are two pending distributions - let free_reserves_balance_3 = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - let second_pending_balance = balance!(55.124461117760692833); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![ - (USDT, free_reserves_balance), - (USDT, second_pending_balance) - ] - ); - assert_eq!( - free_reserves_balance_3, - free_reserves_balance + second_pending_balance - ); +#[test] +fn fees_for_equivalent_trades_should_match() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + DAI, + balance!(0), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(2000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_input(balance!(1000), Balance::zero()), + ) + .unwrap(); + + // Buy + let (price_a, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_input(balance!(100)), + true, + ) + .unwrap(); + let (price_b, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(price_a.amount), + true, + ) + .unwrap(); + assert_eq!(price_a.fee, price_b.fee); + assert_eq!(price_a.fee, balance!(0.054394410184082514)); + + // Sell + let (price_c, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_output(balance!(100)), + true, + ) + .unwrap(); + let (price_d, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_input(price_c.amount), + true, + ) + .unwrap(); + assert_eq!(price_c.fee, price_d.fee); + assert_eq!(price_c.fee, balance!(2.655958896716961113)); + }); +} - // exchange becomes possible, but val is enough only to fulfill one of pending distributions - MockDEXApi::add_reserves(vec![(VAL, balance!(0.4))]).unwrap(); - MockDEXApi::add_reserves(vec![(XST, balance!(0.4))]).unwrap(); - - // val is not enough for one of distributions, it's still present - MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); - let free_reserves_balance_4 = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!( - MBCPool::pending_free_reserves(), - vec![(USDT, second_pending_balance)] - ); - assert_eq!(free_reserves_balance_4, second_pending_balance); - - // check distribution accounts - ensure_distribution_accounts_balances( - distribution_accounts.clone(), - vec![ - balance!(0.002000003750968687), - balance!(0.008000015003874750), - balance!(0.180000337587181890), - ], - ); +#[test] +fn check_sell_penalty_based_on_collateralized_fraction() { + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0)), + fixed!(0.09) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.03)), + fixed!(0.09) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.05)), + fixed!(0.06) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.075)), + fixed!(0.06) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.1)), + fixed!(0.03) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.15)), + fixed!(0.03) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.2)), + fixed!(0.01) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.25)), + fixed!(0.01) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.3)), + fixed!(0) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.35)), + fixed!(0) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(0.5)), + fixed!(0) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(1)), + fixed!(0) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(2)), + fixed!(0) + ); + assert_eq!( + MBCPool::map_collateralized_fraction_to_penalty(fixed!(10)), + fixed!(0) + ); +} - // enough val is added to fulfill second exchange - MockDEXApi::add_reserves(vec![(VAL, balance!(1))]).unwrap(); - - // second pending distribution is performed - MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); - let free_reserves_balance_5 = - Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); - assert_eq!(MBCPool::pending_free_reserves(), vec![]); - assert_eq!(free_reserves_balance_5, balance!(0)); - - // check distribution accounts - ensure_distribution_accounts_balances( - distribution_accounts, - vec![ - balance!(0.004747958137689057), - balance!(0.018991832550756232), - balance!(0.427316232392015238), - ], - ); - }) - } +#[test] +fn fee_penalties_should_be_applied() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(2000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + DAI, + balance!(20000000), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + PSWAP, + balance!(0), + AssetSymbol(b"PSWAP".to_vec()), + AssetName(b"Polkaswap".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, DAI) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(DAI, false).expect("Failed to initialize pool."); + MBCPool::set_reference_asset(RuntimeOrigin::signed(alice()), DAI).unwrap(); + + let xor_supply = Assets::total_issuance(&XOR).unwrap(); + assert_eq!(xor_supply, balance!(100000)); + + // Depositing collateral #1: under 5% collateralized + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(200000), Balance::zero()), + ) + .unwrap(); + let xor_supply = Assets::total_issuance(&XOR).unwrap(); + assert_eq!(xor_supply, balance!(100724.916324262414168899)); + + let (sell_price, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &DAI, + QuoteAmount::with_desired_input(balance!(100)), + true, + ) + .unwrap(); + assert_eq!(sell_price.fee, balance!(9.3)); + + // Depositing collateral #2: under 10% collateralized + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(2000000), Balance::zero()), + ) + .unwrap(); + let xor_supply = Assets::total_issuance(&XOR).unwrap(); + assert_eq!(xor_supply, balance!(107896.889465954935399866)); + + let (sell_price, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &DAI, + QuoteAmount::with_desired_input(balance!(100)), + true, + ) + .unwrap(); + assert_eq!(sell_price.fee, balance!(6.3)); + + // Depositing collateral #3: under 20% collateralized + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(2000000), Balance::zero()), + ) + .unwrap(); + let xor_supply = Assets::total_issuance(&XOR).unwrap(); + assert_eq!(xor_supply, balance!(114934.359190755661026458)); + + let (sell_price, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &DAI, + QuoteAmount::with_desired_input(balance!(100)), + true, + ) + .unwrap(); + assert_eq!(sell_price.fee, balance!(3.3)); + + // Depositing collateral #4: under 30% collateralized + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(4000000), Balance::zero()), + ) + .unwrap(); + let xor_supply = Assets::total_issuance(&XOR).unwrap(); + assert_eq!(xor_supply, balance!(128633.975165230400000080)); + + let (sell_price, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &DAI, + QuoteAmount::with_desired_input(balance!(100)), + true, + ) + .unwrap(); + assert_eq!(sell_price.fee, balance!(1.3)); + + // Depositing collateral #5: over 30% collateralized + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(7000000), Balance::zero()), + ) + .unwrap(); + let xor_supply = Assets::total_issuance(&XOR).unwrap(); + assert_eq!(xor_supply, balance!(151530.994236602104619871)); + + let (sell_price, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &DAI, + QuoteAmount::with_desired_input(balance!(100)), + true, + ) + .unwrap(); + assert_eq!(sell_price.fee, balance!(0.3)); + }); +} - #[test] - fn rewards_for_small_values() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - balance!(6000000000), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - 0, - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init_without_reserves().unwrap(); - let _ = bonding_curve_pool_init(Vec::new()).unwrap(); - let alice = &alice(); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - USDT, - ) +#[test] +fn sequential_rewards_adequacy_check() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + XOR, + balance!(250000), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(2000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + DAI, + balance!(2000000), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + PSWAP, + balance!(0), + AssetSymbol(b"PSWAP".to_vec()), + AssetName(b"Polkaswap".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) .expect("Failed to register trading pair."); - TradingPair::register( - RuntimeOrigin::signed(alice.clone()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, DAI) .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); - let reward = MBCPool::calculate_buy_reward( - alice, - &USDT, - balance!(0.000000002499999999), - balance!(0.000000000000001), - ); - assert_eq!(reward.unwrap(), balance!(0.000000002499999999)); - let reward = MBCPool::calculate_buy_reward( - alice, - &USDT, - balance!(0.000000002499999999), - balance!(0.000000000000000001), - ); - assert_eq!(reward.unwrap(), balance!(0.000000002499999999)); - }) - } - - #[test] - fn price_without_impact_small_amount() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - DAI, - balance!(0), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(4000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + MBCPool::initialize_pool_unchecked(DAI, false).expect("Failed to initialize pool."); + + // XOR total supply in network is 350000 + let xor_total_supply: FixedWrapper = Assets::total_issuance(&XOR).unwrap().into(); + assert_eq!(xor_total_supply.clone().into_balance(), balance!(350000)); + // initial XOR price is $264 + let xor_ideal_reserves: FixedWrapper = + MBCPool::ideal_reserves_reference_price(&VAL, PriceVariant::Buy, Default::default()) + .unwrap() + .into(); + assert_eq!( + (xor_ideal_reserves / xor_total_supply).into_balance(), + balance!(330.890052356020942408) + ); + // pswap price is $10 on mock secondary market + assert_eq!( + MockDEXApi::quote( + DEXId::Polkaswap, + &PSWAP, + &DAI, + QuoteAmount::with_desired_input(balance!(1)), + MBCPool::self_excluding_filter(), + true ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + .unwrap() + .amount, + balance!(10.173469387755102041) + ); + + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(1000), Balance::zero()), + ) + .unwrap(); + + let (limit, owned_1) = MBCPool::rewards(alice()); + assert!(limit.is_zero()); + assert_eq!(owned_1, balance!(21036.472370353787480367)); + + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(10000), Balance::zero()), + ) + .unwrap(); + + let (limit, owned_2) = MBCPool::rewards(alice()); + assert!(limit.is_zero()); + assert_eq!(owned_2 - owned_1, balance!(210336.209418679523304856)); + + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &DAI, + &XOR, + SwapAmount::with_desired_input(balance!(1000000), Balance::zero()), + ) + .unwrap(); + + let (limit, owned_3) = MBCPool::rewards(alice()); + assert!(limit.is_zero()); + assert_eq!(owned_3 - owned_2, balance!(20769070.485987076318293437)); + }); +} + +#[test] +fn distribution_passes_on_first_attempt() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + balance!(10000), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + 0, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + 0, + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XST, + 0, + AssetSymbol(b"XST".to_vec()), + AssetName(b"XST".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + // secondary market is initialized with enough funds + MockDEXApi::init().unwrap(); + let distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + USDT, + ) + .expect("Failed to register trading pair."); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + + // check pending list and reserves before trade + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!(MBCPool::pending_free_reserves(), vec![]); + assert_eq!(free_reserves_balance, balance!(0)); + + ensure_distribution_accounts_balances( + distribution_accounts.clone(), + vec![balance!(0), balance!(0), balance!(0)], + ); - // Buy with desired input - let amount_a: Balance = balance!(2000); - let (quote_outcome_a, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, + // perform buy on tbc + assert_eq!( + MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - QuoteAmount::with_desired_input(amount_a.clone()), - true, + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); - let quote_without_impact_a = MBCPool::quote_without_impact( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_input(amount_a.clone()), - true, + .unwrap() + .0, + SwapOutcome::new( + balance!(275.621555395065931189), + balance!(0.003009027081243731) ) - .unwrap(); + ); + + // check pending list and free reserves account + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!(MBCPool::pending_free_reserves(), vec![]); + assert_eq!(free_reserves_balance, balance!(0)); + + ensure_distribution_accounts_balances( + distribution_accounts, + vec![ + balance!(0.002747946907288807), + balance!(0.010991787629155229), + balance!(0.247315221655992660), + ], + ); + }) +} + +#[test] +fn distribution_fails_on_first_attempt() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + balance!(10000), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + 350000, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + 0, + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XST, + 0, + AssetSymbol(b"XST".to_vec()), + AssetName(b"XST".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + // secondary market is initialized without funds + MockDEXApi::init_without_reserves().unwrap(); + let distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + USDT, + ) + .expect("Failed to register trading pair."); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + + // check pending list and reserves before trade + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!(MBCPool::pending_free_reserves(), vec![]); + assert_eq!(free_reserves_balance, balance!(0)); + + // perform buy on tbc + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - SwapAmount::with_desired_input(amount_a.clone(), Balance::zero()), + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); - assert_eq!(quote_outcome_a.amount, balance!(361.549938632002690452)); - assert_eq!( - quote_without_impact_a.amount, - balance!(361.728370440936309235) - ); - assert!(quote_outcome_a.amount < quote_without_impact_a.amount); + .unwrap() + .0, + SwapOutcome::new( + balance!(200.602181641794149028), + balance!(0.003009027081243731), + ), + balance!(0.0001), + ); - // Buy with desired output - let amount_b: Balance = balance!(200); - let (quote_outcome_b, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, + // check pending list and free reserves account + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, free_reserves_balance)] + ); + assert_eq!(free_reserves_balance, balance!(40.120436328358829805)); + + // attempt for distribution, still not enough reserves + MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); + let free_reserves_balance_2 = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, free_reserves_balance)] + ); + assert_eq!(free_reserves_balance_2, free_reserves_balance); + + // exchange becomes possible for stored free reserves + MockDEXApi::add_reserves(vec![ + (XOR, balance!(100000)), + (VAL, balance!(100000)), + (USDT, balance!(1000000)), + (XST, balance!(1000000)), + ]) + .unwrap(); + + // actual accounts check before distribution + ensure_distribution_accounts_balances( + distribution_accounts.clone(), + vec![balance!(0), balance!(0), balance!(0)], + ); + + // attempt for distribution before retry period + MBCPool::on_initialize((RETRY_DISTRIBUTION_FREQUENCY - 1).into()); + let free_reserves_balance_3 = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, free_reserves_balance)] + ); + assert_eq!(free_reserves_balance_3, free_reserves_balance); + + // successful attempt for distribution + MBCPool::on_initialize((RETRY_DISTRIBUTION_FREQUENCY * 2).into()); + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!(MBCPool::pending_free_reserves(), vec![]); + assert_eq!(free_reserves_balance, balance!(0)); + + // actual accounts check after distribution + ensure_distribution_accounts_balances( + distribution_accounts, + vec![ + balance!(0.002000003750968687), + balance!(0.008000015003874750), + balance!(0.180000337587181890), + ], + ); + }) +} + +#[test] +fn multiple_pending_distributions_are_executed() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + balance!(10000), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + 350000, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + 0, + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XST, + 0, + AssetSymbol(b"XST".to_vec()), + AssetName(b"XST".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + // secondary market is initialized without funds + MockDEXApi::init_without_reserves().unwrap(); + let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + USDT, + ) + .expect("Failed to register trading pair."); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + + // check pending list and reserves before trade + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!(MBCPool::pending_free_reserves(), vec![]); + assert_eq!(free_reserves_balance, balance!(0)); + + // perform buy on tbc multiple times + assert_swap_outcome( + MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - QuoteAmount::with_desired_output(amount_b.clone()), - true, + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); - let quote_without_impact_b = MBCPool::quote_without_impact( - &DEXId::Polkaswap.into(), - &VAL, + .unwrap() + .0, + SwapOutcome::new( + balance!(200.602181641794149028), + balance!(0.003009027081243731), + ), + balance!(0.0001), + ); + assert_swap_outcome( + MBCPool::exchange( + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - QuoteAmount::with_desired_output(amount_b.clone()), - true, + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); + .unwrap() + .0, + SwapOutcome::new( + balance!(200.602931835531681746), + balance!(0.003009027081243731), + ), + balance!(0.0001), + ); + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - SwapAmount::with_desired_output(amount_b.clone(), Balance::max_value()), + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); - assert_eq!(quote_outcome_b.amount, balance!(1107.192203724646374562)); - assert_eq!( - quote_without_impact_b.amount, - balance!(1106.890317630040503506) - ); - assert!(quote_outcome_b.amount > quote_without_impact_b.amount); + .unwrap() + .0, + SwapOutcome::new( + balance!(200.603682029269214463), + balance!(0.003009027081243731), + ), + balance!(0.0001), + ); - // Sell with desired input - let amount_c: Balance = balance!(1); - let (quote_outcome_c, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_input(amount_c.clone()), - true, - ) - .unwrap(); - let quote_without_impact_c = MBCPool::quote_without_impact( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_input(amount_c.clone()), - true, - ) - .unwrap(); + // check pending list and reserves after trade + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + let expected_balances = [ + balance!(40.120436328358829805), + balance!(40.120586367106336349), + balance!(40.120736405853842892), + ]; + assert_eq!( + MBCPool::pending_free_reserves(), + vec![ + (USDT, expected_balances[0]), + (USDT, expected_balances[1]), + (USDT, expected_balances[2]) + ] + ); + assert_eq!( + free_reserves_balance, + expected_balances.iter().fold(balance!(0), |a, b| a + b) + ); + + // exchange becomes available + MockDEXApi::add_reserves(vec![ + (XOR, balance!(100000)), + (VAL, balance!(100000)), + (USDT, balance!(1000000)), + (XST, balance!(1000000)), + ]) + .unwrap(); + MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!(MBCPool::pending_free_reserves(), vec![]); + assert_eq!(free_reserves_balance, balance!(0)); + }) +} + +#[test] +fn large_pending_amount_dont_interfere_new_trades() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + balance!(999999999999999), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + 0, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + 0, + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + USDT, + ) + .expect("Failed to register trading pair."); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + + // perform large buy on tbc + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - &VAL, - SwapAmount::with_desired_input(amount_c.clone(), Balance::zero()), + SwapAmount::with_desired_output(balance!(100000000), Balance::max_value()), ) - .unwrap(); - assert_eq!(quote_outcome_c.amount, balance!(3.999482655569353236)); - assert_eq!( - quote_without_impact_c.amount, - balance!(4.005928040448516546) - ); - assert!(quote_outcome_c.amount < quote_without_impact_c.amount); + .unwrap() + .0, + SwapOutcome::new( + balance!(3789817571942.618173119057163101), + balance!(300902.708124373119358074), + ), + balance!(0.0001), + ); - // Sell with desired output - let amount_d: Balance = balance!(1); - let (quote_outcome_d, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_output(amount_d.clone()), - true, - ) - .unwrap(); - let quote_without_impact_d = MBCPool::quote_without_impact( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_output(amount_d.clone()), - true, - ) - .unwrap(); + // check that failed distribution was postponed + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, free_reserves_balance)] + ); + assert_eq!( + free_reserves_balance, + balance!(757963514388.523634623811432620) + ); + + // attempt for distribution + MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); + let free_reserves_balance_2 = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, free_reserves_balance_2)] + ); + assert_eq!(free_reserves_balance_2, free_reserves_balance); + + // another exchange with reasonable amount + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - &VAL, - SwapAmount::with_desired_output(amount_d.clone(), Balance::max_value()), + SwapAmount::with_desired_output(balance!(100), Balance::max_value()), ) - .unwrap(); - assert_eq!(quote_outcome_d.amount, balance!(0.249731351108007183)); - assert_eq!( - quote_without_impact_d.amount, - balance!(0.249630724163152921) - ); - assert!(quote_outcome_d.amount > quote_without_impact_d.amount); - }); - } - - #[test] - fn price_without_impact_large_amount() { - let mut ext = ExtBuilder::new(vec![ - ( - alice(), - DAI, - balance!(0), - AssetSymbol(b"DAI".to_vec()), - AssetName(b"DAI".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - USDT, - balance!(0), - AssetSymbol(b"USDT".to_vec()), - AssetName(b"Tether USD".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XOR, - balance!(0), - AssetSymbol(b"XOR".to_vec()), - AssetName(b"SORA".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - VAL, - balance!(200000), - AssetSymbol(b"VAL".to_vec()), - AssetName(b"SORA Validator Token".to_vec()), - DEFAULT_BALANCE_PRECISION, - ), - ( - alice(), - XSTUSD, - 0, - AssetSymbol(b"XSTUSD".to_vec()), - AssetName(b"SORA Synthetic USD".to_vec()), - DEFAULT_BALANCE_PRECISION, + .unwrap() + .0, + SwapOutcome::new( + balance!(7529503.255499584322288265), + balance!(0.300902708124373119), ), - ]) - .build(); - ext.execute_with(|| { - MockDEXApi::init().unwrap(); - let _ = bonding_curve_pool_init(vec![]).unwrap(); - TradingPair::register( - RuntimeOrigin::signed(alice()), - DEXId::Polkaswap.into(), - XOR, - VAL, - ) - .expect("Failed to register trading pair."); - MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + balance!(0.0001), + ); - // Buy with desired input - let amount_a: Balance = balance!(70000); - let (quote_outcome_a, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_input(amount_a.clone()), - true, - ) - .unwrap(); - let quote_without_impact_a = MBCPool::quote_without_impact( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_input(amount_a.clone()), - true, - ) - .unwrap(); + // second distribution was successful, pending list didn't change + let free_reserves_balance_3 = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, free_reserves_balance_3)] + ); + assert_eq!(free_reserves_balance_3, free_reserves_balance_2); + }) +} + +#[test] +fn multiple_pending_distributions_with_large_request_dont_interfere_when_exchange_becomes_available( +) { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + balance!(999999999999999), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + 350000, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + 0, + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XST, + 0, + AssetSymbol(b"XST".to_vec()), + AssetName(b"XST".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + // secondary market is initialized without funds + MockDEXApi::init_without_reserves().unwrap(); + let _distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + USDT, + ) + .expect("Failed to register trading pair."); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + + // perform large buy on tbc + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - SwapAmount::with_desired_input(amount_a.clone(), Balance::zero()), + SwapAmount::with_desired_output(balance!(100000000), Balance::max_value()), ) - .unwrap(); - assert_eq!(quote_outcome_a.amount, balance!(12448.948798121038068728)); - assert_eq!( - quote_without_impact_a.amount, - balance!(12660.492965432770823211) - ); - assert!(quote_outcome_a.amount < quote_without_impact_a.amount); + .unwrap() + .0, + SwapOutcome::new( + balance!(3782315634567.290994901504505143), + balance!(300902.708124373119358074), + ), + balance!(0.0001), + ); - // Buy with desired output - let amount_b: Balance = balance!(14000); - let (quote_outcome_b, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(amount_b.clone()), - true, - ) - .unwrap(); - let quote_without_impact_b = MBCPool::quote_without_impact( - &DEXId::Polkaswap.into(), - &VAL, - &XOR, - QuoteAmount::with_desired_output(amount_b.clone()), - true, - ) - .unwrap(); + // another exchange with reasonable amount, still current market can't handle it + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), - &VAL, + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - SwapAmount::with_desired_output(amount_b.clone(), Balance::max_value()), + SwapAmount::with_desired_output(balance!(100), Balance::max_value()), ) - .unwrap(); - assert_eq!(quote_outcome_b.amount, balance!(81508.213505580992097736)); - assert_eq!( - quote_without_impact_b.amount, - balance!(80028.971642012224670009) - ); - assert!(quote_outcome_b.amount > quote_without_impact_b.amount); + .unwrap() + .0, + SwapOutcome::new( + balance!(7522001.318124257144070739), + balance!(0.300902708124373119), + ), + balance!(0.0001), + ); - // Sell with desired input - let amount_c: Balance = balance!(7000); - let (quote_outcome_c, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_input(amount_c.clone()), - true, - ) - .unwrap(); - let quote_without_impact_c = MBCPool::quote_without_impact( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_input(amount_c.clone()), - true, - ) - .unwrap(); + // attempt for distribution + MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + let expected_balances = [ + balance!(756463126913.458198980300901028), + balance!(1504400.263624851428814147), + ]; + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, expected_balances[0]), (USDT, expected_balances[1])] + ); + assert_eq!( + free_reserves_balance, + expected_balances.iter().fold(balance!(0), |a, b| a + b) + ); + + // funds are added and one of exchanges becomes available, unavailable is left as pending + MockDEXApi::add_reserves(vec![ + (XOR, balance!(100000)), + (VAL, balance!(100000)), + (USDT, balance!(1000000)), + (XST, balance!(1000000)), + ]) + .unwrap(); + MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, expected_balances[0])] + ); + assert_eq!(free_reserves_balance, expected_balances[0]); + }) +} + +#[test] +fn xor_exchange_passes_but_val_exchange_fails_reserves_are_reverted() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + balance!(10000), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + 350000, + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + 0, + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XST, + 0, + AssetSymbol(b"XST".to_vec()), + AssetName(b"XST".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + // secondary market is initialized without funds + MockDEXApi::init_without_reserves().unwrap(); + let distribution_accounts = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + USDT, + ) + .expect("Failed to register trading pair."); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + + // perform buy on tbc + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - &VAL, - SwapAmount::with_desired_input(amount_c.clone(), Balance::zero()), + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); - assert_eq!(quote_outcome_c.amount, balance!(25316.104888559067750898)); - assert_eq!( - quote_without_impact_c.amount, - balance!(31999.826368133346115316) - ); - assert!(quote_outcome_c.amount < quote_without_impact_c.amount); + .unwrap() + .0, + SwapOutcome::new( + balance!(200.602181641794149028), + balance!(0.003009027081243731), + ), + balance!(0.0001), + ); - // Sell with desired output - let amount_d: Balance = balance!(7000); - let (quote_outcome_d, _) = MBCPool::quote( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_output(amount_d.clone()), - true, - ) - .unwrap(); - let quote_without_impact_d = MBCPool::quote_without_impact( - &DEXId::Polkaswap.into(), - &XOR, - &VAL, - QuoteAmount::with_desired_output(amount_d.clone()), - true, - ) - .unwrap(); + // check pending list and free reserves account + let free_reserves_balance = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, free_reserves_balance)] + ); + assert_eq!(free_reserves_balance, balance!(40.120436328358829805)); + + // exchange becomes possible, but not for val, so second part of distribution fails + MockDEXApi::add_reserves(vec![ + (XOR, balance!(100000)), + (VAL, balance!(0)), + (USDT, balance!(1000000)), + ]) + .unwrap(); + + // check pending list + MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); + let free_reserves_balance_2 = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, free_reserves_balance)] + ); + + // val buy back and burn failed so exchanged xor is reverted + assert_eq!(free_reserves_balance_2, free_reserves_balance); + ensure_distribution_accounts_balances( + distribution_accounts.clone(), + vec![balance!(0), balance!(0), balance!(0)], + ); + + // another buy is performed + assert_swap_outcome( MBCPool::exchange( - &alice(), - &alice(), - &DEXId::Polkaswap.into(), + alice, + alice, + &DEXId::Polkaswap, + &USDT, &XOR, - &VAL, - SwapAmount::with_desired_output(amount_d.clone(), Balance::max_value()), + SwapAmount::with_desired_output(balance!(1), Balance::max_value()), ) - .unwrap(); - assert_eq!(quote_outcome_d.amount, balance!(1681.732720328623106924)); - assert_eq!( - quote_without_impact_d.amount, - balance!(1558.966302104893601417) - ); - assert!(quote_outcome_d.amount > quote_without_impact_d.amount); - }); - } + .unwrap() + .0, + SwapOutcome::new( + balance!(275.622305588803464169), + balance!(0.003009027081243731), + ), + balance!(0.0001), + ); + + // there are two pending distributions + let free_reserves_balance_3 = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + let second_pending_balance = balance!(55.124461117760692833); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![ + (USDT, free_reserves_balance), + (USDT, second_pending_balance) + ] + ); + assert_eq!( + free_reserves_balance_3, + free_reserves_balance + second_pending_balance + ); + + // exchange becomes possible, but val is enough only to fulfill one of pending distributions + MockDEXApi::add_reserves(vec![(VAL, balance!(0.4))]).unwrap(); + MockDEXApi::add_reserves(vec![(XST, balance!(0.4))]).unwrap(); + + // val is not enough for one of distributions, it's still present + MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); + let free_reserves_balance_4 = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!( + MBCPool::pending_free_reserves(), + vec![(USDT, second_pending_balance)] + ); + assert_eq!(free_reserves_balance_4, second_pending_balance); + + // check distribution accounts + ensure_distribution_accounts_balances( + distribution_accounts.clone(), + vec![ + balance!(0.002000003750968687), + balance!(0.008000015003874750), + balance!(0.180000337587181890), + ], + ); + + // enough val is added to fulfill second exchange + MockDEXApi::add_reserves(vec![(VAL, balance!(1))]).unwrap(); + + // second pending distribution is performed + MBCPool::on_initialize(RETRY_DISTRIBUTION_FREQUENCY.into()); + let free_reserves_balance_5 = + Assets::free_balance(&USDT, &MBCPool::free_reserves_account_id().unwrap()).unwrap(); + assert_eq!(MBCPool::pending_free_reserves(), vec![]); + assert_eq!(free_reserves_balance_5, balance!(0)); + + // check distribution accounts + ensure_distribution_accounts_balances( + distribution_accounts, + vec![ + balance!(0.004747958137689057), + balance!(0.018991832550756232), + balance!(0.427316232392015238), + ], + ); + }) +} + +#[test] +fn rewards_for_small_values() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + balance!(6000000000), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + 0, + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init_without_reserves().unwrap(); + let _ = bonding_curve_pool_init(Vec::new()).unwrap(); + let alice = &alice(); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + USDT, + ) + .expect("Failed to register trading pair."); + TradingPair::register( + RuntimeOrigin::signed(alice.clone()), + DEXId::Polkaswap, + XOR, + VAL, + ) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(USDT, false).expect("Failed to initialize pool."); + let reward = MBCPool::calculate_buy_reward( + alice, + &USDT, + balance!(0.000000002499999999), + balance!(0.000000000000001), + ); + assert_eq!(reward.unwrap(), balance!(0.000000002499999999)); + let reward = MBCPool::calculate_buy_reward( + alice, + &USDT, + balance!(0.000000002499999999), + balance!(0.000000000000000001), + ); + assert_eq!(reward.unwrap(), balance!(0.000000002499999999)); + }) +} + +#[test] +fn price_without_impact_small_amount() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + DAI, + balance!(0), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(4000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + // Buy with desired input + let amount_a: Balance = balance!(2000); + let (quote_outcome_a, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_input(amount_a), + true, + ) + .unwrap(); + let quote_without_impact_a = MBCPool::quote_without_impact( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_input(amount_a), + true, + ) + .unwrap(); + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_input(amount_a, Balance::zero()), + ) + .unwrap(); + assert_eq!(quote_outcome_a.amount, balance!(361.549938632002690452)); + assert_eq!( + quote_without_impact_a.amount, + balance!(361.728370440936309235) + ); + assert!(quote_outcome_a.amount < quote_without_impact_a.amount); + + // Buy with desired output + let amount_b: Balance = balance!(200); + let (quote_outcome_b, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(amount_b), + true, + ) + .unwrap(); + let quote_without_impact_b = MBCPool::quote_without_impact( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(amount_b), + true, + ) + .unwrap(); + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_output(amount_b, Balance::max_value()), + ) + .unwrap(); + assert_eq!(quote_outcome_b.amount, balance!(1107.192203724646374562)); + assert_eq!( + quote_without_impact_b.amount, + balance!(1106.890317630040503506) + ); + assert!(quote_outcome_b.amount > quote_without_impact_b.amount); + + // Sell with desired input + let amount_c: Balance = balance!(1); + let (quote_outcome_c, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_input(amount_c), + true, + ) + .unwrap(); + let quote_without_impact_c = MBCPool::quote_without_impact( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_input(amount_c), + true, + ) + .unwrap(); + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &XOR, + &VAL, + SwapAmount::with_desired_input(amount_c, Balance::zero()), + ) + .unwrap(); + assert_eq!(quote_outcome_c.amount, balance!(3.999482655569353236)); + assert_eq!( + quote_without_impact_c.amount, + balance!(4.005928040448516546) + ); + assert!(quote_outcome_c.amount < quote_without_impact_c.amount); + + // Sell with desired output + let amount_d: Balance = balance!(1); + let (quote_outcome_d, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_output(amount_d), + true, + ) + .unwrap(); + let quote_without_impact_d = MBCPool::quote_without_impact( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_output(amount_d), + true, + ) + .unwrap(); + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &XOR, + &VAL, + SwapAmount::with_desired_output(amount_d, Balance::max_value()), + ) + .unwrap(); + assert_eq!(quote_outcome_d.amount, balance!(0.249731351108007183)); + assert_eq!( + quote_without_impact_d.amount, + balance!(0.249630724163152921) + ); + assert!(quote_outcome_d.amount > quote_without_impact_d.amount); + }); +} + +#[test] +fn price_without_impact_large_amount() { + let mut ext = ExtBuilder::new(vec![ + ( + alice(), + DAI, + balance!(0), + AssetSymbol(b"DAI".to_vec()), + AssetName(b"DAI".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + USDT, + balance!(0), + AssetSymbol(b"USDT".to_vec()), + AssetName(b"Tether USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XOR, + balance!(0), + AssetSymbol(b"XOR".to_vec()), + AssetName(b"SORA".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + VAL, + balance!(200000), + AssetSymbol(b"VAL".to_vec()), + AssetName(b"SORA Validator Token".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ( + alice(), + XSTUSD, + 0, + AssetSymbol(b"XSTUSD".to_vec()), + AssetName(b"SORA Synthetic USD".to_vec()), + DEFAULT_BALANCE_PRECISION, + ), + ]) + .build(); + ext.execute_with(|| { + MockDEXApi::init().unwrap(); + let _ = bonding_curve_pool_init(vec![]).unwrap(); + TradingPair::register(RuntimeOrigin::signed(alice()), DEXId::Polkaswap, XOR, VAL) + .expect("Failed to register trading pair."); + MBCPool::initialize_pool_unchecked(VAL, false).expect("Failed to initialize pool."); + + // Buy with desired input + let amount_a: Balance = balance!(70000); + let (quote_outcome_a, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_input(amount_a), + true, + ) + .unwrap(); + let quote_without_impact_a = MBCPool::quote_without_impact( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_input(amount_a), + true, + ) + .unwrap(); + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_input(amount_a, Balance::zero()), + ) + .unwrap(); + assert_eq!(quote_outcome_a.amount, balance!(12448.948798121038068728)); + assert_eq!( + quote_without_impact_a.amount, + balance!(12660.492965432770823211) + ); + assert!(quote_outcome_a.amount < quote_without_impact_a.amount); + + // Buy with desired output + let amount_b: Balance = balance!(14000); + let (quote_outcome_b, _) = MBCPool::quote( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(amount_b), + true, + ) + .unwrap(); + let quote_without_impact_b = MBCPool::quote_without_impact( + &DEXId::Polkaswap, + &VAL, + &XOR, + QuoteAmount::with_desired_output(amount_b), + true, + ) + .unwrap(); + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &VAL, + &XOR, + SwapAmount::with_desired_output(amount_b, Balance::max_value()), + ) + .unwrap(); + assert_eq!(quote_outcome_b.amount, balance!(81508.213505580992097736)); + assert_eq!( + quote_without_impact_b.amount, + balance!(80028.971642012224670009) + ); + assert!(quote_outcome_b.amount > quote_without_impact_b.amount); + + // Sell with desired input + let amount_c: Balance = balance!(7000); + let (quote_outcome_c, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_input(amount_c), + true, + ) + .unwrap(); + let quote_without_impact_c = MBCPool::quote_without_impact( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_input(amount_c), + true, + ) + .unwrap(); + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &XOR, + &VAL, + SwapAmount::with_desired_input(amount_c, Balance::zero()), + ) + .unwrap(); + assert_eq!(quote_outcome_c.amount, balance!(25316.104888559067750898)); + assert_eq!( + quote_without_impact_c.amount, + balance!(31999.826368133346115316) + ); + assert!(quote_outcome_c.amount < quote_without_impact_c.amount); + + // Sell with desired output + let amount_d: Balance = balance!(7000); + let (quote_outcome_d, _) = MBCPool::quote( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_output(amount_d), + true, + ) + .unwrap(); + let quote_without_impact_d = MBCPool::quote_without_impact( + &DEXId::Polkaswap, + &XOR, + &VAL, + QuoteAmount::with_desired_output(amount_d), + true, + ) + .unwrap(); + MBCPool::exchange( + &alice(), + &alice(), + &DEXId::Polkaswap, + &XOR, + &VAL, + SwapAmount::with_desired_output(amount_d, Balance::max_value()), + ) + .unwrap(); + assert_eq!(quote_outcome_d.amount, balance!(1681.732720328623106924)); + assert_eq!( + quote_without_impact_d.amount, + balance!(1558.966302104893601417) + ); + assert!(quote_outcome_d.amount > quote_without_impact_d.amount); + }); } From 5647400ca002204040e8674d325210d7087ce335 Mon Sep 17 00:00:00 2001 From: pakrentos Date: Mon, 30 Oct 2023 11:28:26 +0200 Subject: [PATCH 09/11] oracle-proxy clippy fixes --- pallets/oracle-proxy/src/benchmarking.rs | 8 ++++---- pallets/oracle-proxy/src/lib.rs | 19 +++++-------------- pallets/oracle-proxy/src/mock.rs | 2 +- pallets/oracle-proxy/src/tests.rs | 14 ++++++-------- 4 files changed, 16 insertions(+), 27 deletions(-) diff --git a/pallets/oracle-proxy/src/benchmarking.rs b/pallets/oracle-proxy/src/benchmarking.rs index 3872352c0c..29d1ee2d5f 100644 --- a/pallets/oracle-proxy/src/benchmarking.rs +++ b/pallets/oracle-proxy/src/benchmarking.rs @@ -41,15 +41,15 @@ use sp_std::prelude::*; benchmarks! { enable_oracle { let oracle = Oracle::BandChainFeed; - }: _(RawOrigin::Root, oracle.clone()) + }: _(RawOrigin::Root, oracle) verify { - assert_eq!(OracleProxy::::enabled_oracles(), BTreeSet::from([oracle.clone()])); + assert_eq!(OracleProxy::::enabled_oracles(), BTreeSet::from([oracle])); } disable_oracle { let oracle = Oracle::BandChainFeed; - OracleProxy::::enable_oracle(RawOrigin::Root.into(), oracle.clone())?; - }: _(RawOrigin::Root, oracle.clone()) + OracleProxy::::enable_oracle(RawOrigin::Root.into(), oracle)?; + }: _(RawOrigin::Root, oracle) verify { assert_eq!(OracleProxy::::enabled_oracles(), BTreeSet::new()); } diff --git a/pallets/oracle-proxy/src/lib.rs b/pallets/oracle-proxy/src/lib.rs index 231933fe7d..a0f8ed2d42 100644 --- a/pallets/oracle-proxy/src/lib.rs +++ b/pallets/oracle-proxy/src/lib.rs @@ -29,11 +29,9 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] use common::{DataFeed, OnNewSymbolsRelayed, Oracle, Rate}; -use frame_support; + use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use sp_std::{collections::btree_set::BTreeSet, vec::Vec}; @@ -57,7 +55,7 @@ impl DataFeed for Pallet { Self::enabled_symbols(symbol) .into_iter() - .filter(|oracle| enabled_oracles.contains(&oracle)) + .filter(|oracle| enabled_oracles.contains(oracle)) .map(|oracle| match oracle { Oracle::BandChainFeed => T::BandChainOracle::quote(symbol), }) @@ -83,7 +81,7 @@ impl DataFeed for Pallet { Self::enabled_symbols(symbol) .into_iter() - .filter(|oracle| enabled_oracles.contains(&oracle)) + .filter(|oracle| enabled_oracles.contains(oracle)) .map(|oracle| match oracle { Oracle::BandChainFeed => T::BandChainOracle::quote_unchecked(symbol), }) @@ -167,7 +165,7 @@ pub mod pallet { Error::::OracleAlreadyEnabled ); - EnabledOracles::::mutate(|enabled_oracles| enabled_oracles.insert(oracle.clone())); + EnabledOracles::::mutate(|enabled_oracles| enabled_oracles.insert(oracle)); Self::deposit_event(Event::OracleEnabled(oracle)); @@ -198,19 +196,12 @@ pub mod pallet { } #[pallet::genesis_config] + #[derive(Default)] pub struct GenesisConfig { pub enabled_oracles: BTreeSet, } #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - enabled_oracles: Default::default(), - } - } - } - #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/pallets/oracle-proxy/src/mock.rs b/pallets/oracle-proxy/src/mock.rs index 5d806dd3c7..07d7a3e1aa 100644 --- a/pallets/oracle-proxy/src/mock.rs +++ b/pallets/oracle-proxy/src/mock.rs @@ -29,7 +29,7 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use crate::{self as oracle_proxy, Config}; -use band; + use frame_support::traits::{ConstU16, ConstU64}; use frame_system as system; use sp_core::H256; diff --git a/pallets/oracle-proxy/src/tests.rs b/pallets/oracle-proxy/src/tests.rs index 984de4c237..930fc9db99 100644 --- a/pallets/oracle-proxy/src/tests.rs +++ b/pallets/oracle-proxy/src/tests.rs @@ -61,13 +61,12 @@ fn enable_and_disable_oracles_should_work() { assert!(OracleProxy::enabled_oracles().is_empty()); let oracle = Oracle::BandChainFeed; - OracleProxy::enable_oracle(RuntimeOrigin::root(), oracle.clone()) - .expect("Failed to enable oracle"); + OracleProxy::enable_oracle(RuntimeOrigin::root(), oracle).expect("Failed to enable oracle"); let enabled_oracles = OracleProxy::enabled_oracles(); assert!(enabled_oracles.contains(&oracle)); - OracleProxy::disable_oracle(RuntimeOrigin::root(), oracle.clone()) + OracleProxy::disable_oracle(RuntimeOrigin::root(), oracle) .expect("Failed to disable oracle"); assert!(!OracleProxy::enabled_oracles().contains(&oracle)); @@ -79,14 +78,14 @@ fn enable_and_disable_oracles_should_forbid_non_root_call() { new_test_ext().execute_with(|| { let oracle = Oracle::BandChainFeed; assert_err!( - OracleProxy::enable_oracle(RuntimeOrigin::signed(1), oracle.clone()), + OracleProxy::enable_oracle(RuntimeOrigin::signed(1), oracle), BadOrigin ); assert!(OracleProxy::enabled_oracles().is_empty()); assert_err!( - OracleProxy::disable_oracle(RuntimeOrigin::signed(2), oracle.clone()), + OracleProxy::disable_oracle(RuntimeOrigin::signed(2), oracle), BadOrigin ); }); @@ -98,8 +97,7 @@ fn quote_and_list_enabled_symbols_should_work() { relay_symbols(); let oracle = Oracle::BandChainFeed; - OracleProxy::enable_oracle(RuntimeOrigin::root(), oracle.clone()) - .expect("Failed to enable oracle"); + OracleProxy::enable_oracle(RuntimeOrigin::root(), oracle).expect("Failed to enable oracle"); let symbols = vec!["USD".to_owned(), "RUB".to_owned(), "YEN".to_owned()]; let rates = vec![1, 2, 3]; @@ -110,7 +108,7 @@ fn quote_and_list_enabled_symbols_should_work() { .zip(rates.iter()) .for_each(|(symbol, value)| { let rate = Rate { - value: Band::raw_rate_into_balance(value.clone()) + value: Band::raw_rate_into_balance(*value) .expect("failed to convert rate into Balance"), last_updated: resolve_time, dynamic_fee: fixed!(0), From 0e705514b1f6d761aa4a5868e69ac53b1e9ae350 Mon Sep 17 00:00:00 2001 From: pakrentos Date: Mon, 30 Oct 2023 11:37:12 +0200 Subject: [PATCH 10/11] permissions clippy fixes --- pallets/permissions/src/lib.rs | 14 ++++++-------- pallets/permissions/src/mock.rs | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/pallets/permissions/src/lib.rs b/pallets/permissions/src/lib.rs index f079e42b89..23f769a8ee 100644 --- a/pallets/permissions/src/lib.rs +++ b/pallets/permissions/src/lib.rs @@ -45,8 +45,6 @@ variant_size_differences )] #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] use frame_support::codec::{Decode, Encode}; use frame_support::{ensure, RuntimeDebug}; @@ -126,7 +124,7 @@ impl Pallet { scope: Scope, ) -> Result<(), Error> { let (permission_found, owns_permission) = { - let owners = Owners::::get(permission_id, &scope); + let owners = Owners::::get(permission_id, scope); if owners.contains(&who) { (true, true) } else if scope != Scope::Unlimited { @@ -141,7 +139,7 @@ impl Pallet { frame_system::Pallet::::inc_consumers(&account_id) .map_err(|_| Error::::IncRefError)?; } - Permissions::::mutate(&account_id, &scope, |permissions| { + Permissions::::mutate(&account_id, scope, |permissions| { if let Err(index) = permissions.binary_search(&permission_id) { permissions.insert(index, permission_id); } @@ -222,11 +220,11 @@ impl Pallet { false } }); - if Permissions::::iter_prefix_values(&holder_id).count() == 0 { - frame_system::Pallet::::inc_consumers(&holder_id) + if Permissions::::iter_prefix_values(holder_id).count() == 0 { + frame_system::Pallet::::inc_consumers(holder_id) .map_err(|_| Error::::IncRefError)?; } - let granted_permission = Permissions::::mutate(&holder_id, scope, |permissions| { + let granted_permission = Permissions::::mutate(holder_id, scope, |permissions| { if let Err(index) = permissions.binary_search(&permission_id) { permissions.insert(index, permission_id); true @@ -363,7 +361,7 @@ pub mod pallet { .for_each(|(holder_id, scope, permissions)| { let mut permissions = permissions.clone(); permissions.sort(); - frame_system::Pallet::::inc_consumers(&holder_id).unwrap(); + frame_system::Pallet::::inc_consumers(holder_id).unwrap(); Permissions::::insert(holder_id, scope, permissions); }); } diff --git a/pallets/permissions/src/mock.rs b/pallets/permissions/src/mock.rs index 588c1057da..567a48ac2a 100644 --- a/pallets/permissions/src/mock.rs +++ b/pallets/permissions/src/mock.rs @@ -32,7 +32,7 @@ use crate::{self as permissions, Config, Scope, BURN, INIT_DEX, MINT, SLASH}; use frame_support::traits::{Everything, GenesisBuild}; use frame_support::weights::Weight; use frame_support::{construct_runtime, parameter_types}; -use frame_system; + use sp_core::H256; use sp_runtime::testing::Header; use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; From f795064e0592b6fc43fa246b6d954cac5c3be614 Mon Sep 17 00:00:00 2001 From: pakrentos Date: Mon, 30 Oct 2023 11:54:31 +0200 Subject: [PATCH 11/11] pool-xyk clippy fixes --- .../pool-xyk/src/action_deposit_liquidity.rs | 31 ++--- pallets/pool-xyk/src/action_pair_swap.rs | 35 +++--- .../pool-xyk/src/action_withdraw_liquidity.rs | 30 ++--- pallets/pool-xyk/src/lib.rs | 52 ++++---- pallets/pool-xyk/src/math.rs | 22 ++-- pallets/pool-xyk/src/migrations/v1_1.rs | 48 ++++---- pallets/pool-xyk/src/migrations/v1_2.rs | 38 +++--- pallets/pool-xyk/src/migrations/v2.rs | 18 +-- pallets/pool-xyk/src/migrations/v3.rs | 18 +-- pallets/pool-xyk/src/mock.rs | 12 +- pallets/pool-xyk/src/tests.rs | 115 +++++++++--------- pallets/pool-xyk/src/utils.rs | 12 +- 12 files changed, 201 insertions(+), 230 deletions(-) diff --git a/pallets/pool-xyk/src/action_deposit_liquidity.rs b/pallets/pool-xyk/src/action_deposit_liquidity.rs index 8fab83b120..80dbd1e7e0 100644 --- a/pallets/pool-xyk/src/action_deposit_liquidity.rs +++ b/pallets/pool-xyk/src/action_deposit_liquidity.rs @@ -77,12 +77,9 @@ impl common::SwapRulesValidation, TechAccountIdOf, // Dealing with receiver account, for example case then not swapping to self, but to // other account. - match &self.receiver_account { + if self.receiver_account.is_none() { // Just use `client_account` as same account, swapping to self. - None => { - self.receiver_account = self.client_account.clone(); - } - _ => (), + self.receiver_account = self.client_account.clone(); } } @@ -99,16 +96,16 @@ impl common::SwapRulesValidation, TechAccountIdOf, ( Some(>::free_balance( &self.source.0.asset, - &source, + source, )?), Some(>::free_balance( &self.source.1.asset, - &source, + source, )?), ) }; - if !abstract_checking && (balance_bs.unwrap() <= 0 || balance_ts.unwrap() <= 0) { + if !abstract_checking && (balance_bs.unwrap() == 0 || balance_ts.unwrap() == 0) { Err(Error::::AccountBalanceIsInvalid)?; } @@ -122,9 +119,7 @@ impl common::SwapRulesValidation, TechAccountIdOf, let mut empty_pool = false; if balance_bp == 0 && balance_tp == 0 { empty_pool = true; - } else if balance_bp == 0 { - Err(Error::::PoolIsInvalid)?; - } else if balance_tp == 0 { + } else if balance_bp == 0 || balance_tp == 0 { Err(Error::::PoolIsInvalid)?; } @@ -159,18 +154,16 @@ impl common::SwapRulesValidation, TechAccountIdOf, let fxw_init_y = to_fixed_wrapper!(init_y); let fxw_value = fxw_init_x.multiply_and_sqrt(&fxw_init_y); ensure!( - !((fxw_value.clone() * fxw_init_x.clone()) - .try_into_balance() - .is_err() + !((fxw_value.clone() * fxw_init_x).try_into_balance().is_err() || (fxw_value.clone() * fxw_init_y).try_into_balance().is_err()), Error::::CalculatedValueIsOutOfDesiredBounds ); - let value = to_balance!(fxw_value.clone()); + let value = to_balance!(fxw_value); Some(value) } } else { let fxw_value: FixedWrapper = fxw_balance_bp.multiply_and_sqrt(&fxw_balance_tp); - let value = to_balance!(fxw_value.clone()); + let value = to_balance!(fxw_value); Some(value) } }; @@ -293,13 +286,13 @@ impl common::SwapAction, TechAccountIdOf, AssetIdOf technical::Pallet::::tech_account_id_to_account_id(&self.pool_account)?; technical::Pallet::::transfer_in( &self.source.0.asset, - &source, + source, &self.pool_account, self.source.0.amount.unwrap(), )?; technical::Pallet::::transfer_in( &self.source.1.asset, - &source, + source, &self.pool_account, self.source.1.amount.unwrap(), )?; @@ -315,7 +308,7 @@ impl common::SwapAction, TechAccountIdOf, AssetIdOf &self.source.0.asset, &self.source.1.asset, )?; - AccountPools::::mutate(receiver_account, &pair.base_asset_id, |set| { + AccountPools::::mutate(receiver_account, pair.base_asset_id, |set| { set.insert(pair.target_asset_id) }); } diff --git a/pallets/pool-xyk/src/action_pair_swap.rs b/pallets/pool-xyk/src/action_pair_swap.rs index 7745de0d8b..4db9403e15 100644 --- a/pallets/pool-xyk/src/action_pair_swap.rs +++ b/pallets/pool-xyk/src/action_pair_swap.rs @@ -85,12 +85,9 @@ impl common::SwapRulesValidation, TechAccountIdOf, // Dealing with receiver account, for example case then not swapping to self, but to // other account. - match &self.receiver_account { + if self.receiver_account.is_none() { // Just use `client_account` as same account, swapping to self. - None => { - self.receiver_account = self.client_account.clone(); - } - _ => (), + self.receiver_account = self.client_account.clone(); } } @@ -105,7 +102,7 @@ impl common::SwapRulesValidation, TechAccountIdOf, } else { Some(>::free_balance( &self.source.asset, - &source_opt.unwrap(), + source_opt.unwrap(), )?) }; // Source balance of technical account. @@ -119,20 +116,17 @@ impl common::SwapRulesValidation, TechAccountIdOf, } if balance_st == 0 && balance_tt == 0 { Err(Error::::PoolIsEmpty)?; - } else if balance_st <= 0 || balance_tt <= 0 { + } else if balance_st == 0 || balance_tt == 0 { Err(Error::::PoolIsInvalid)?; } - match self.get_fee_from_destination { - None => { - let is_fee_from_d = Pallet::::decide_is_fee_from_destination( - base_asset_id, - &self.source.asset, - &self.destination.asset, - )?; - self.get_fee_from_destination = Some(is_fee_from_d); - } - _ => (), + if self.get_fee_from_destination.is_none() { + let is_fee_from_d = Pallet::::decide_is_fee_from_destination( + base_asset_id, + &self.source.asset, + &self.destination.asset, + )?; + self.get_fee_from_destination = Some(is_fee_from_d); } // Recommended fee, will be used if fee is not specified or for checking if specified. @@ -258,6 +252,7 @@ impl common::SwapRulesValidation, TechAccountIdOf, if !abstract_checking { // Checking that balances if correct and large enouth for amounts. + #[allow(clippy::if_same_then_else)] if self.get_fee_from_destination.unwrap() { // For source account balance must be not smaller than required with fee. if balance_ss.unwrap() < source_amount { @@ -353,7 +348,7 @@ impl common::SwapAction, TechAccountIdOf, AssetIdOf if self.get_fee_from_destination.unwrap() { technical::Pallet::::transfer_in( &self.source.asset, - &source, + source, &self.pool_account, self.source.amount.unwrap(), )?; @@ -372,13 +367,13 @@ impl common::SwapAction, TechAccountIdOf, AssetIdOf } else { technical::Pallet::::transfer_in( &self.source.asset, - &source, + source, &self.pool_account, self.source.amount.unwrap() - self.fee.unwrap(), )?; technical::Pallet::::transfer_in( &self.source.asset, - &source, + source, self.fee_account.as_ref().unwrap(), self.fee.unwrap(), )?; diff --git a/pallets/pool-xyk/src/action_withdraw_liquidity.rs b/pallets/pool-xyk/src/action_withdraw_liquidity.rs index a4894843ca..dbf9e8d215 100644 --- a/pallets/pool-xyk/src/action_withdraw_liquidity.rs +++ b/pallets/pool-xyk/src/action_withdraw_liquidity.rs @@ -76,19 +76,13 @@ impl common::SwapRulesValidation, TechAccountIdOf, // Dealing with receiver account, for example case then not swapping to self, but to // other account. - match &self.receiver_account_a { + if self.receiver_account_a.is_none() { // Just use `client_account` as same account, swapping to self. - None => { - self.receiver_account_a = self.client_account.clone(); - } - _ => (), + self.receiver_account_a = self.client_account.clone(); } - match &self.receiver_account_b { + if self.receiver_account_b.is_none() { // Just use `client_account` as same account, swapping to self. - None => { - self.receiver_account_b = self.client_account.clone(); - } - _ => (), + self.receiver_account_b = self.client_account.clone(); } let pool_account_repr_sys = technical::Pallet::::tech_account_id_to_account_id(&self.pool_account)?; @@ -96,8 +90,8 @@ impl common::SwapRulesValidation, TechAccountIdOf, Pallet::::is_pool_account_valid_for(self.destination.0.asset, &self.pool_account)?; // Balance of source account for k value. - let balance_ks = PoolProviders::::get(&pool_account_repr_sys, &source).unwrap_or(0); - if balance_ks <= 0 { + let balance_ks = PoolProviders::::get(&pool_account_repr_sys, source).unwrap_or(0); + if balance_ks == 0 { Err(Error::::AccountBalanceIsInvalid)?; } @@ -110,9 +104,7 @@ impl common::SwapRulesValidation, TechAccountIdOf, if balance_bp == 0 && balance_tp == 0 { Err(Error::::PoolIsEmpty)?; - } else if balance_bp <= 0 { - Err(Error::::PoolIsInvalid)?; - } else if balance_tp <= 0 { + } else if balance_bp == 0 || balance_tp == 0 { Err(Error::::PoolIsInvalid)?; } @@ -126,13 +118,13 @@ impl common::SwapRulesValidation, TechAccountIdOf, let has_enough_unlocked_liquidity = ceres_liquidity_locker::Pallet::::check_if_has_enough_unlocked_liquidity( - &source, + source, self.destination.0.asset, self.destination.1.asset, self.pool_tokens, ); ensure!( - has_enough_unlocked_liquidity == true, + has_enough_unlocked_liquidity, Error::::NotEnoughUnlockedLiquidity ); @@ -144,7 +136,7 @@ impl common::SwapRulesValidation, TechAccountIdOf, self.pool_tokens, ); ensure!( - has_enough_liquidity_out_of_farming == true, + has_enough_liquidity_out_of_farming, Error::::NotEnoughLiquidityOutOfFarming ); @@ -255,7 +247,7 @@ impl common::SwapAction, TechAccountIdOf, AssetIdOf &self.destination.0.asset, &self.destination.1.asset, )?; - AccountPools::::mutate(source, &pair.base_asset_id, |set| { + AccountPools::::mutate(source, pair.base_asset_id, |set| { set.remove(&pair.target_asset_id) }); } diff --git a/pallets/pool-xyk/src/lib.rs b/pallets/pool-xyk/src/lib.rs index 5ca647ea25..77ea100f17 100644 --- a/pallets/pool-xyk/src/lib.rs +++ b/pallets/pool-xyk/src/lib.rs @@ -29,8 +29,6 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #![cfg_attr(not(feature = "std"), no_std)] -// TODO #167: fix clippy warnings -#![allow(clippy::all)] use frame_support::dispatch::{DispatchError, DispatchResult}; use frame_support::storage::PrefixIterator; @@ -132,7 +130,7 @@ impl PoolXykPallet for Pallet { let new_balance = old_balance .checked_sub(pool_tokens) .ok_or(Error::::AccountBalanceIsInvalid)?; - *balance = (new_balance != 0).then(|| new_balance); + *balance = (new_balance != 0).then_some(new_balance); Ok(()) }); result?; @@ -144,13 +142,13 @@ impl PoolXykPallet for Pallet { && !pool_tokens.is_zero() { let pair = Pallet::::strict_sort_pair(&asset_a.clone(), &asset_a, &asset_b)?; - AccountPools::::mutate(target_account_id.clone(), &pair.base_asset_id, |set| { + AccountPools::::mutate(target_account_id.clone(), pair.base_asset_id, |set| { set.insert(pair.target_asset_id) }); } // Add lp_tokens to target_account - result = PoolProviders::::mutate(pool_account.clone(), target_account_id, |balance| { + result = PoolProviders::::mutate(pool_account, target_account_id, |balance| { *balance = Some(balance.unwrap_or(0) + pool_tokens); Ok(()) }); @@ -220,6 +218,7 @@ impl Pallet { } } + #[allow(clippy::type_complexity)] pub fn initialize_pool_unchecked( _source: AccountIdOf, dex_id: DEXIdOf, @@ -259,6 +258,7 @@ impl Pallet { Ok((trading_pair, tech_acc_id, fee_acc_id)) } + #[allow(clippy::too_many_arguments)] pub fn deposit_liquidity_unchecked( source: AccountIdOf, dex_id: DEXIdOf, @@ -367,7 +367,7 @@ impl LiquiditySource::contains_key(&dex_info.base_asset_id, &target_asset_id) + Properties::::contains_key(dex_info.base_asset_id, target_asset_id) } else { false } @@ -390,13 +390,13 @@ impl LiquiditySource::tech_account_id_to_account_id(&tech_acc_id)?; // Get actual pool reserves. - let reserve_input = >::free_balance(&input_asset_id, &pool_acc_id)?; - let reserve_output = >::free_balance(&output_asset_id, &pool_acc_id)?; + let reserve_input = >::free_balance(input_asset_id, &pool_acc_id)?; + let reserve_output = >::free_balance(output_asset_id, &pool_acc_id)?; // Check reserves validity. if reserve_input == 0 && reserve_output == 0 { fail!(Error::::PoolIsEmpty); - } else if reserve_input <= 0 || reserve_output <= 0 { + } else if reserve_input == 0 || reserve_output == 0 { fail!(Error::::PoolIsInvalid); } @@ -442,14 +442,14 @@ impl LiquiditySource, ) -> Result<(SwapOutcome, Weight), DispatchError> { - let dex_info = T::DexInfoProvider::get_dex_info(&dex_id)?; + let dex_info = T::DexInfoProvider::get_dex_info(dex_id)?; let (_, tech_acc_id) = Pallet::::tech_account_from_dex_and_asset_pair( *dex_id, *input_asset_id, *output_asset_id, )?; let (source_amount, destination_amount) = - Pallet::::get_bounds_from_swap_amount(swap_amount.clone())?; + Pallet::::get_bounds_from_swap_amount(swap_amount)?; let mut action = PolySwapActionStructOf::::PairSwap(PairSwapActionOf:: { client_account: None, receiver_account: Some(receiver.clone()), @@ -493,10 +493,9 @@ impl LiquiditySource::create_swap_unchecked( sender.clone(), - &mut action, + &action.into(), &dex_info.base_asset_id, )?; @@ -531,13 +530,13 @@ impl LiquiditySource::tech_account_id_to_account_id(&tech_acc_id)?; // Get actual pool reserves. - let reserve_input = >::free_balance(&input_asset_id, &pool_acc_id)?; - let reserve_output = >::free_balance(&output_asset_id, &pool_acc_id)?; + let reserve_input = >::free_balance(input_asset_id, &pool_acc_id)?; + let reserve_output = >::free_balance(output_asset_id, &pool_acc_id)?; // Check reserves validity. if reserve_input == 0 && reserve_output == 0 { fail!(Error::::PoolIsEmpty); - } else if reserve_input <= 0 || reserve_output <= 0 { + } else if reserve_input == 0 || reserve_output == 0 { fail!(Error::::PoolIsInvalid); } @@ -562,16 +561,15 @@ impl LiquiditySource LiquiditySource GetPoolReserves for Pallet { pub use pallet::*; use sp_runtime::traits::Zero; +#[allow(clippy::too_many_arguments)] #[frame_support::pallet] pub mod pallet { use super::*; @@ -811,15 +810,10 @@ pub mod pallet { ); let (trading_pair, tech_account_id, fees_account_id) = - Pallet::::initialize_pool_unchecked( - source.clone(), - dex_id, - asset_a, - asset_b, - )?; + Pallet::::initialize_pool_unchecked(source, dex_id, asset_a, asset_b)?; Pallet::::ensure_trading_pair_is_not_restricted( - &trading_pair.map(|a| Into::::into(a)), + &trading_pair.map(Into::::into), )?; let ta_repr = diff --git a/pallets/pool-xyk/src/math.rs b/pallets/pool-xyk/src/math.rs index a3b9f23ae5..bf8ca7cf1e 100644 --- a/pallets/pool-xyk/src/math.rs +++ b/pallets/pool-xyk/src/math.rs @@ -133,9 +133,9 @@ impl Pallet { x_in: &Balance, deduce_fee: bool, ) -> Result<(Balance, Balance), DispatchError> { - let fxw_x = FixedWrapper::from(x.clone()); - let fxw_y = FixedWrapper::from(y.clone()); - let fxw_x_in = FixedWrapper::from(x_in.clone()); + let fxw_x = FixedWrapper::from(*x); + let fxw_y = FixedWrapper::from(*y); + let fxw_x_in = FixedWrapper::from(*x_in); if get_fee_from_destination { // output token is xor, user indicates desired input amount // y_1 = (x_in * y) / (x + x_in) @@ -178,14 +178,14 @@ impl Pallet { y_out: &Balance, deduce_fee: bool, ) -> Result<(Balance, Balance), DispatchError> { - let fxw_x = FixedWrapper::from(x.clone()); - let fxw_y = FixedWrapper::from(y.clone()); - let fxw_y_out = FixedWrapper::from(y_out.clone()); + let fxw_x = FixedWrapper::from(*x); + let fxw_y = FixedWrapper::from(*y); + let fxw_y_out = FixedWrapper::from(*y_out); if get_fee_from_destination { // output token is xor, user indicates desired output amount: // y_1 = y_out / (1 - fee) // x_in = (x * y_1) / (y - y_1) - let fxw_y_out = fxw_y_out.clone() + Fixed::from_bits(1); // by 1 correction to overestimate required input + let fxw_y_out = fxw_y_out + Fixed::from_bits(1); // by 1 correction to overestimate required input let y_out_with_fee = if deduce_fee { fxw_y_out.clone() / (fixed_wrapper!(1) - fee_fraction) } else { @@ -198,7 +198,7 @@ impl Pallet { } else { // input token is xor, user indicates desired output amount: // x_in * (1 - fee) = (x * y_out) / (y - y_out) - let fxw_y_out = fxw_y_out.clone() + Fixed::from_bits(1); // by 1 correction to overestimate required input + let fxw_y_out = fxw_y_out + Fixed::from_bits(1); // by 1 correction to overestimate required input let nominator = fxw_x * fxw_y_out.clone(); let denominator = fxw_y - fxw_y_out; let x_in_without_fee = nominator / denominator; @@ -219,10 +219,8 @@ impl Pallet { trading_pair: &TradingPair>, liq_amount: Balance, ) -> Result { - let b_in_pool = - assets::Pallet::::free_balance(&trading_pair.base_asset_id.into(), pool_acc)?; - let t_in_pool = - assets::Pallet::::free_balance(&trading_pair.target_asset_id.into(), pool_acc)?; + let b_in_pool = assets::Pallet::::free_balance(&trading_pair.base_asset_id, pool_acc)?; + let t_in_pool = assets::Pallet::::free_balance(&trading_pair.target_asset_id, pool_acc)?; let fxw_liq_in_pool = to_fixed_wrapper!(b_in_pool).multiply_and_sqrt(&to_fixed_wrapper!(t_in_pool)); let fxw_piece = fxw_liq_in_pool / to_fixed_wrapper!(liq_amount); diff --git a/pallets/pool-xyk/src/migrations/v1_1.rs b/pallets/pool-xyk/src/migrations/v1_1.rs index c36945c040..3247e64949 100644 --- a/pallets/pool-xyk/src/migrations/v1_1.rs +++ b/pallets/pool-xyk/src/migrations/v1_1.rs @@ -20,7 +20,7 @@ pub fn migrate() -> Weight { let mut acc_asset_currs = Vec::new(); Properties::::translate::<(T::AccountId, T::AccountId, T::AssetId), _>( |_ba, _ta, (reserves_acc, fee_acc, marker_asset)| { - let currency: ::CurrencyId = marker_asset.clone().into(); + let currency: ::CurrencyId = marker_asset.into(); acc_asset_currs.push((reserves_acc.clone(), marker_asset, currency)); Some((reserves_acc, fee_acc)) }, @@ -42,7 +42,7 @@ pub fn migrate() -> Weight { .find(|(_, _, probe_currency)| probe_currency == ¤cy) { let balance: u128 = data.free.unique_saturated_into(); - PoolProviders::::insert(&pool_acc, account, balance); + PoolProviders::::insert(pool_acc, account, balance); None } else { Some(data) @@ -82,40 +82,40 @@ mod tests { #[test] fn test() { ExtBuilder::default().build().execute_with(|| { - let asset1 = AssetId::from_bytes( - hex!("0200000700000000000000000000000000000000000000000000000000000000").into(), - ); - let asset2 = AssetId::from_bytes( - hex!("0200010700000000000000000000000000000000000000000000000000000000").into(), - ); - let asset3 = AssetId::from_bytes( - hex!("0200020700000000000000000000000000000000000000000000000000000000").into(), - ); - let asset4 = AssetId::from_bytes( - hex!("0200030700000000000000000000000000000000000000000000000000000000").into(), - ); - let asset5 = AssetId::from_bytes( - hex!("0200040700000000000000000000000000000000000000000000000000000000").into(), - ); - let asset6 = AssetId::from_bytes( - hex!("0200050700000000000000000000000000000000000000000000000000000000").into(), - ); + let asset1 = AssetId::from_bytes(hex!( + "0200000700000000000000000000000000000000000000000000000000000000" + )); + let asset2 = AssetId::from_bytes(hex!( + "0200010700000000000000000000000000000000000000000000000000000000" + )); + let asset3 = AssetId::from_bytes(hex!( + "0200020700000000000000000000000000000000000000000000000000000000" + )); + let asset4 = AssetId::from_bytes(hex!( + "0200030700000000000000000000000000000000000000000000000000000000" + )); + let asset5 = AssetId::from_bytes(hex!( + "0200040700000000000000000000000000000000000000000000000000000000" + )); + let asset6 = AssetId::from_bytes(hex!( + "0200050700000000000000000000000000000000000000000000000000000000" + )); let set: BTreeSet = vec![asset1, asset2, asset3].into_iter().collect(); OldMarkerTokensIndex::::put(set); OldProperties::::insert::<_, _, (AccountId, AccountId, AssetId)>( &asset1, &asset2, - (ALICE(), ALICE(), asset3.clone()), + (ALICE(), ALICE(), asset3), ); OldProperties::::insert::<_, _, (AccountId, AccountId, AssetId)>( &asset4, &asset5, - (BOB(), BOB(), asset6.clone()), + (BOB(), BOB(), asset6), ); assets::Pallet::::register_asset_id( ALICE(), - asset3.clone(), + asset3, AssetSymbol(b"A".to_vec()), AssetName(b"B".to_vec()), DEFAULT_BALANCE_PRECISION, @@ -131,7 +131,7 @@ mod tests { assets::Pallet::::register_asset_id( BOB(), - asset6.clone(), + asset6, AssetSymbol(b"C".to_vec()), AssetName(b"D".to_vec()), DEFAULT_BALANCE_PRECISION, diff --git a/pallets/pool-xyk/src/migrations/v1_2.rs b/pallets/pool-xyk/src/migrations/v1_2.rs index fbeb757a19..dc657c286d 100644 --- a/pallets/pool-xyk/src/migrations/v1_2.rs +++ b/pallets/pool-xyk/src/migrations/v1_2.rs @@ -6,7 +6,7 @@ use crate::{AccountPools, Config, PoolProviders, Properties}; pub fn migrate() -> Weight { for (base_asset_id, target_asset, (pool_account, _)) in Properties::::iter() { for (user_account, _pool_tokens_balance) in PoolProviders::::iter_prefix(pool_account) { - AccountPools::::mutate(user_account, &base_asset_id, |set| set.insert(target_asset)); + AccountPools::::mutate(user_account, base_asset_id, |set| set.insert(target_asset)); } } T::BlockWeights::get().max_block @@ -25,19 +25,19 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let base_asset = GetBaseAssetId::get(); let dex_id = DEX_A_ID; - let target_asset_a = AssetId::from_bytes( - hex!("0200000700000000000000000000000000000000000000000000000000000000").into(), - ); - let target_asset_b = AssetId::from_bytes( - hex!("0200010700000000000000000000000000000000000000000000000000000000").into(), - ); - let target_asset_c = AssetId::from_bytes( - hex!("0200020700000000000000000000000000000000000000000000000000000000").into(), - ); + let target_asset_a = AssetId::from_bytes(hex!( + "0200000700000000000000000000000000000000000000000000000000000000" + )); + let target_asset_b = AssetId::from_bytes(hex!( + "0200010700000000000000000000000000000000000000000000000000000000" + )); + let target_asset_c = AssetId::from_bytes(hex!( + "0200020700000000000000000000000000000000000000000000000000000000" + )); assets::Pallet::::register_asset_id( ALICE(), - base_asset.clone(), + base_asset, AssetSymbol(b"BASE".to_vec()), AssetName(b"BASE".to_vec()), DEFAULT_BALANCE_PRECISION, @@ -50,7 +50,7 @@ mod tests { for target_asset in [target_asset_a, target_asset_b, target_asset_c].iter() { assets::Pallet::::register_asset_id( ALICE(), - target_asset.clone(), + *target_asset, AssetSymbol(b"A".to_vec()), AssetName(b"B".to_vec()), DEFAULT_BALANCE_PRECISION, @@ -63,22 +63,22 @@ mod tests { trading_pair::Pallet::::register( RuntimeOrigin::signed(ALICE()), dex_id, - base_asset.clone(), - target_asset.clone(), + base_asset, + *target_asset, ) .unwrap(); crate::Pallet::::initialize_pool( RuntimeOrigin::signed(ALICE()), dex_id, - base_asset.clone(), - target_asset.clone(), + base_asset, + *target_asset, ) .unwrap(); let (_, tech_account) = PoolXYK::tech_account_from_dex_and_asset_pair( dex_id, - base_asset.clone(), - target_asset.clone(), + base_asset, + *target_asset, ) .unwrap(); let pool_account = Technical::tech_account_id_to_account_id(&tech_account).unwrap(); @@ -98,7 +98,7 @@ mod tests { for account in [ALICE(), BOB(), CHARLIE()].iter() { assert_eq!( - AccountPools::::get(account, &base_asset), + AccountPools::::get(account, base_asset), [target_asset_a, target_asset_b, target_asset_c] .iter() .cloned() diff --git a/pallets/pool-xyk/src/migrations/v2.rs b/pallets/pool-xyk/src/migrations/v2.rs index df228add28..af177b02ee 100644 --- a/pallets/pool-xyk/src/migrations/v2.rs +++ b/pallets/pool-xyk/src/migrations/v2.rs @@ -43,15 +43,15 @@ mod tests { #[test] fn test() { ExtBuilder::default().build().execute_with(|| { - let target_asset_a = AssetId::from_bytes( - hex!("0200000700000000000000000000000000000000000000000000000000000000").into(), - ); - let target_asset_b = AssetId::from_bytes( - hex!("0200010700000000000000000000000000000000000000000000000000000000").into(), - ); - let target_asset_c = AssetId::from_bytes( - hex!("0200020700000000000000000000000000000000000000000000000000000000").into(), - ); + let target_asset_a = AssetId::from_bytes(hex!( + "0200000700000000000000000000000000000000000000000000000000000000" + )); + let target_asset_b = AssetId::from_bytes(hex!( + "0200010700000000000000000000000000000000000000000000000000000000" + )); + let target_asset_c = AssetId::from_bytes(hex!( + "0200020700000000000000000000000000000000000000000000000000000000" + )); OldAccountPools::::insert( ALICE(), BTreeSet::from([target_asset_a, target_asset_b, target_asset_c]), diff --git a/pallets/pool-xyk/src/migrations/v3.rs b/pallets/pool-xyk/src/migrations/v3.rs index 9f82fa179e..0dcbda9906 100644 --- a/pallets/pool-xyk/src/migrations/v3.rs +++ b/pallets/pool-xyk/src/migrations/v3.rs @@ -71,7 +71,7 @@ where UserInfos::::mutate(&user_account, |user_infos| { for user_info in user_infos.iter_mut() { - if user_info.is_farm == true + if user_info.is_farm && user_info.base_asset == base_asset && user_info.pool_asset == target_asset { @@ -92,7 +92,7 @@ where }); Pallet::::withdraw_liquidity_unchecked( - user_account.clone(), + user_account, dex_id, base_asset, target_asset, @@ -119,11 +119,11 @@ where Pallet::::tech_account_from_dex_and_asset_pair(dex_id, base_asset, target_asset)?; let pair = TradingPair:: { - base_asset_id: base_asset.clone(), - target_asset_id: target_asset.clone(), + base_asset_id: base_asset, + target_asset_id: target_asset, }; - EnabledSources::::mutate(&dex_id, &pair, |opt_set| { + EnabledSources::::mutate(dex_id, pair, |opt_set| { if let Some(sources) = opt_set.as_mut() { sources.remove(&LiquiditySourceType::XYKPool); } @@ -137,7 +137,7 @@ where technical::Pallet::::deregister_tech_account_id(tech_acc_id)?; technical::Pallet::::deregister_tech_account_id(fee_acc_id)?; - Reserves::::remove(&base_asset, &target_asset); + Reserves::::remove(base_asset, target_asset); TotalIssuances::::remove(&pool_account); @@ -159,7 +159,7 @@ where weight_meter.check_accrue(T::DbWeight::get().reads(1)); let pool_account = - if let Some(pool_property) = Properties::::get(&base_asset, &target_asset) { + if let Some(pool_property) = Properties::::get(base_asset, target_asset) { pool_property.0 } else { info!( @@ -173,7 +173,7 @@ where "Pool with assets {:?} and {:?} reserves before liquidity withdrawal: {:?}", base_asset, target_asset, - Reserves::::get(&base_asset, &target_asset) + Reserves::::get(base_asset, target_asset) ); // `Self::pull_out_user_from_pool` triggers `withdraw_liquidity_unchecked` which modifies `PoolProviders` @@ -203,7 +203,7 @@ where "Pool with assets {:?} and {:?} reserves after liquidity withdrawal: {:?}", base_asset, target_asset, - Reserves::::get(&base_asset, &target_asset) + Reserves::::get(base_asset, target_asset) ); Self::remove_pool(weight_meter, dex_id, base_asset, target_asset, pool_account)?; diff --git a/pallets/pool-xyk/src/mock.rs b/pallets/pool-xyk/src/mock.rs index e8a99ecf62..1e893d41a8 100644 --- a/pallets/pool-xyk/src/mock.rs +++ b/pallets/pool-xyk/src/mock.rs @@ -36,7 +36,7 @@ use currencies::BasicCurrencyAdapter; use frame_support::traits::{Everything, GenesisBuild}; use frame_support::weights::Weight; use frame_support::{construct_runtime, parameter_types}; -use frame_system; + use hex_literal::hex; use orml_traits::parameter_type_with_key; use permissions::{Scope, MANAGE_DEX}; @@ -68,8 +68,8 @@ parameter_types! { pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); - pub GetBaseAssetId: AssetId = common::AssetId32::from_bytes(hex!("0200000000000000000000000000000000000000000000000000000000000000").into()); - pub GetIncentiveAssetId: AssetId = common::AssetId32::from_bytes(hex!("0200050000000000000000000000000000000000000000000000000000000000").into()); + pub GetBaseAssetId: AssetId = common::AssetId32::from_bytes(hex!("0200000000000000000000000000000000000000000000000000000000000000")); + pub GetIncentiveAssetId: AssetId = common::AssetId32::from_bytes(hex!("0200050000000000000000000000000000000000000000000000000000000000")); pub const ExistentialDeposit: u128 = 0; pub GetPswapDistributionAccountId: AccountId = AccountId32::from([3; 32]); pub const GetDefaultSubscriptionFrequency: BlockNumber = 10; @@ -271,11 +271,11 @@ impl demeter_farming_platform::Config for Runtime { parameter_types! { pub GetXSTPoolPermissionedTechAccountId: TechAccountId = { - let tech_account_id = TechAccountId::from_generic_pair( + + TechAccountId::from_generic_pair( xst::TECH_ACCOUNT_PREFIX.to_vec(), xst::TECH_ACCOUNT_PERMISSIONED.to_vec(), - ); - tech_account_id + ) }; pub GetSyntheticBaseAssetId: AssetId = BatteryForMusicPlayer.into(); pub const GetSyntheticBaseBuySellLimit: Balance = balance!(10000000000); diff --git a/pallets/pool-xyk/src/tests.rs b/pallets/pool-xyk/src/tests.rs index bac034bf8f..82f1c10158 100644 --- a/pallets/pool-xyk/src/tests.rs +++ b/pallets/pool-xyk/src/tests.rs @@ -52,8 +52,7 @@ type PresetFunction<'a> = Rc< crate::mock::TechAccountId, AccountId, AccountId, - ) -> () - + 'a, + ) + 'a, >; #[derive(Clone)] @@ -97,14 +96,14 @@ impl<'a> crate::Pallet { assert_ok!(trading_pair::Pallet::::register( RuntimeOrigin::signed(BOB()), - dex_id.clone(), + dex_id, GoldenTicket.into(), BlackPepper.into() )); assert_ok!(crate::Pallet::::initialize_pool( RuntimeOrigin::signed(BOB()), - dex_id.clone(), + dex_id, GoldenTicket.into(), BlackPepper.into(), )); @@ -121,13 +120,13 @@ impl<'a> crate::Pallet { let (tpair, tech_acc_id) = crate::Pallet::::tech_account_from_dex_and_asset_pair( - dex_id.clone(), + dex_id, GoldenTicket.into(), BlackPepper.into(), ) .unwrap(); - let fee_acc = tech_acc_id.clone().to_fee_account().unwrap(); + let fee_acc = tech_acc_id.to_fee_account().unwrap(); let repr: AccountId = technical::Pallet::::tech_account_id_to_account_id(&tech_acc_id).unwrap(); let fee_repr: AccountId = @@ -156,16 +155,16 @@ impl<'a> crate::Pallet { balance!(2000000) ); assert_eq!( - assets::Pallet::::free_balance(>, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &repr).unwrap(), 0 ); assert_eq!( - assets::Pallet::::free_balance(&bp, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &repr).unwrap(), 0 ); assert_eq!( - assets::Pallet::::free_balance(>, &fee_repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &fee_repr).unwrap(), 0 ); @@ -178,7 +177,7 @@ impl<'a> crate::Pallet { assert_eq!( pswap_distribution::Pallet::::subscribed_accounts(&fee_repr), Some(( - dex_id.clone(), + dex_id, repr.clone(), GetDefaultSubscriptionFrequency::get(), 0 @@ -187,10 +186,10 @@ impl<'a> crate::Pallet { for test in &tests { test( - dex_id.clone(), - gt.clone(), - bp.clone(), - tpair.clone(), + dex_id, + gt, + bp, + tpair, tech_acc_id.clone(), fee_acc.clone(), repr.clone(), @@ -215,7 +214,7 @@ impl<'a> crate::Pallet { )); assert_eq!( - PoolProviders::::get(pool_account, &ALICE()), + PoolProviders::::get(pool_account, ALICE()), Some(balance!(227683.9915321233119024)), ); //TODO: total supply check @@ -768,26 +767,26 @@ fn pool_is_already_initialized_and_other_after_depositliq() { crate::Pallet::::preset_deposited_pool(vec![Rc::new( |dex_id, gt, bp, _, _, _, repr: AccountId, fee_repr: AccountId| { assert_eq!( - assets::Pallet::::free_balance(&bp, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &repr).unwrap(), balance!(144000) ); assert_eq!( - assets::Pallet::::free_balance(>, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &repr).unwrap(), balance!(360000) ); assert_eq!( - assets::Pallet::::free_balance(&bp, &fee_repr.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &fee_repr).unwrap(), 0 ); assert_eq!( - assets::Pallet::::free_balance(>, &fee_repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &fee_repr).unwrap(), 0 ); assert_noop!( crate::Pallet::::initialize_pool( RuntimeOrigin::signed(BOB()), - dex_id.clone(), + dex_id, GoldenTicket.into(), BlackPepper.into(), ), @@ -821,15 +820,15 @@ fn exchange_desired_output_and_withdraw_cascade() { balance!(1889000) ); assert_eq!( - assets::Pallet::::free_balance(>, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &repr).unwrap(), balance!(467027.027027027027027031) ); assert_eq!( - assets::Pallet::::free_balance(&bp, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &repr).unwrap(), balance!(111000) ); assert_eq!( - assets::Pallet::::free_balance(>, &fee_repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &fee_repr).unwrap(), balance!(322.047222749329068285) ); @@ -887,15 +886,15 @@ fn exchange_desired_output_and_withdraw_cascade() { 1893282356407400019291402 ); assert_eq!( - assets::Pallet::::free_balance(>, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &repr).unwrap(), 449009223589025484939026 ); assert_eq!( - assets::Pallet::::free_balance(&bp, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &repr).unwrap(), 106717643592599980708598 ); assert_eq!( - assets::Pallet::::free_balance(>, &fee_repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &fee_repr).unwrap(), 322047222749329068285 ); @@ -920,15 +919,15 @@ fn exchange_desired_output_and_withdraw_cascade() { 1926282356407400019291402 ); assert_eq!( - assets::Pallet::::free_balance(>, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &repr).unwrap(), 650010010596347171825252 ); assert_eq!( - assets::Pallet::::free_balance(&bp, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &repr).unwrap(), 73717643592599980708598 ); assert_eq!( - assets::Pallet::::free_balance(>, &fee_repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &fee_repr).unwrap(), 926864034205663131132 ); }, @@ -959,15 +958,15 @@ fn exchange_desired_input() { balance!(1868058.365847885345163285) ); assert_eq!( - assets::Pallet::::free_balance(>, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &repr).unwrap(), balance!(392901) ); assert_eq!( - assets::Pallet::::free_balance(&bp, &repr.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &repr).unwrap(), balance!(131941.634152114654836715) ); assert_eq!( - assets::Pallet::::free_balance(>, &fee_repr.clone()).unwrap(), + assets::Pallet::::free_balance(>, &fee_repr).unwrap(), balance!(99) ); }, @@ -1046,7 +1045,7 @@ fn exchange_outcome_should_match_actual_desired_amount_in_with_input_base() { let new_account = AccountId32::from([33; 32]); assets::Pallet::::transfer( RuntimeOrigin::signed(ALICE()), - gt.clone(), + gt, new_account.clone(), balance!(100000), ) @@ -1079,19 +1078,19 @@ fn exchange_outcome_should_match_actual_desired_amount_in_with_input_base() { ) .expect("Failed to perform swap."); assert_eq!( - assets::Pallet::::free_balance(>, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(>, &new_account).unwrap(), 0, ); assert_eq!( - assets::Pallet::::free_balance(&bp, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &new_account).unwrap(), balance!(31230.802697411355231672), ); assert_eq!( - assets::Pallet::::free_balance(&bp, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &new_account).unwrap(), outcome.amount, ); assert_eq!( - assets::Pallet::::free_balance(&bp, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &new_account).unwrap(), quote_outcome.amount, ); }, @@ -1106,7 +1105,7 @@ fn exchange_outcome_should_match_actual_desired_amount_in_with_output_base() { let new_account = AccountId32::from([3; 32]); assets::Pallet::::transfer( RuntimeOrigin::signed(ALICE()), - bp.clone(), + bp, new_account.clone(), balance!(100000), ) @@ -1139,19 +1138,19 @@ fn exchange_outcome_should_match_actual_desired_amount_in_with_output_base() { ) .expect("Failed to perform swap."); assert_eq!( - assets::Pallet::::free_balance(&bp, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &new_account).unwrap(), 0, ); assert_eq!( - assets::Pallet::::free_balance(>, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(>, &new_account).unwrap(), balance!(147098.360655737704918032), ); assert_eq!( - assets::Pallet::::free_balance(>, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(>, &new_account).unwrap(), outcome.amount, ); assert_eq!( - assets::Pallet::::free_balance(>, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(>, &new_account).unwrap(), quote_outcome.amount, ); }, @@ -1166,7 +1165,7 @@ fn exchange_outcome_should_match_actual_desired_amount_out_with_input_base() { let new_account = AccountId32::from([3; 32]); assets::Pallet::::transfer( RuntimeOrigin::signed(ALICE()), - gt.clone(), + gt, new_account.clone(), balance!(100000), ) @@ -1200,11 +1199,11 @@ fn exchange_outcome_should_match_actual_desired_amount_out_with_input_base() { ) .expect("Failed to perform swap."); assert_eq!( - assets::Pallet::::free_balance(>, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(>, &new_account).unwrap(), 0, ); assert_eq!( - assets::Pallet::::free_balance(&bp, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &new_account).unwrap(), desired_out, ); assert_eq!(balance!(100000), quote_outcome.amount,); @@ -1221,7 +1220,7 @@ fn exchange_outcome_should_match_actual_desired_amount_out_with_output_base() { let new_account = AccountId32::from([3; 32]); assets::Pallet::::transfer( RuntimeOrigin::signed(ALICE()), - bp.clone(), + bp, new_account.clone(), balance!(100000), ) @@ -1255,11 +1254,11 @@ fn exchange_outcome_should_match_actual_desired_amount_out_with_output_base() { ) .expect("Failed to perform swap."); assert_eq!( - assets::Pallet::::free_balance(&bp, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(&bp, &new_account).unwrap(), 1, // TODO: still not enough overestimation due to duducing fee from output, find workaroud to improve precision ); assert_eq!( - assets::Pallet::::free_balance(>, &new_account.clone()).unwrap(), + assets::Pallet::::free_balance(>, &new_account).unwrap(), desired_out ); assert_eq!(balance!(100000) - 1, quote_outcome.amount); @@ -1289,7 +1288,7 @@ fn withdraw_all_liquidity() { ); assert_eq!( - PoolProviders::::get(&repr, &ALICE()).unwrap(), + PoolProviders::::get(&repr, ALICE()).unwrap(), balance!(227683.9915321233119024), ); @@ -1316,7 +1315,7 @@ fn withdraw_all_liquidity() { balance!(1), )); - assert_eq!(PoolProviders::::get(repr, &ALICE()), None); + assert_eq!(PoolProviders::::get(repr, ALICE()), None); assert_eq!( assets::Pallet::::free_balance(>, &ALICE()).unwrap(), @@ -1812,13 +1811,13 @@ fn depositing_and_withdrawing_liquidity_updates_user_pools() { )); assert_ok!(trading_pair::Pallet::::register( RuntimeOrigin::signed(ALICE()), - dex_id.clone(), + dex_id, base_asset, target_asset_b )); assert_ok!(crate::Pallet::::initialize_pool( RuntimeOrigin::signed(ALICE()), - dex_id.clone(), + dex_id, base_asset, target_asset_b )); @@ -2231,7 +2230,7 @@ fn initialize_pool_with_different_dex() { AssetSymbol(b"AT".to_vec()), AssetName(b"Apple Tree".to_vec()), DEFAULT_BALANCE_PRECISION, - Balance::from(balance!(10)), + balance!(10), true, None, None, @@ -2242,7 +2241,7 @@ fn initialize_pool_with_different_dex() { AssetSymbol(b"GT".to_vec()), AssetName(b"Golden Ticket".to_vec()), DEFAULT_BALANCE_PRECISION, - Balance::from(balance!(10)), + balance!(10), true, None, None, @@ -2281,7 +2280,7 @@ fn initialize_pool_with_synthetics() { AssetSymbol(b"GT".to_vec()), AssetName(b"Golden Ticket".to_vec()), DEFAULT_BALANCE_PRECISION, - Balance::from(balance!(10)), + balance!(10), true, None, None, @@ -2292,7 +2291,7 @@ fn initialize_pool_with_synthetics() { AssetSymbol(b"AP".to_vec()), AssetName(b"Apple".to_vec()), DEFAULT_BALANCE_PRECISION, - Balance::from(balance!(10)), + balance!(10), true, None, None, @@ -2303,7 +2302,7 @@ fn initialize_pool_with_synthetics() { AssetSymbol(b"BP".to_vec()), AssetName(b"BlackPepper".to_vec()), DEFAULT_BALANCE_PRECISION, - Balance::from(balance!(10)), + balance!(10), true, None, None, @@ -2350,7 +2349,7 @@ fn initialize_pool_with_synthetics() { assert_ok!(xst::Pallet::::enable_synthetic_asset( RuntimeOrigin::root(), Apple.into(), - euro.clone(), + euro, fixed!(0) )); diff --git a/pallets/pool-xyk/src/utils.rs b/pallets/pool-xyk/src/utils.rs index fb6e0b35a0..10731b23e1 100644 --- a/pallets/pool-xyk/src/utils.rs +++ b/pallets/pool-xyk/src/utils.rs @@ -156,7 +156,7 @@ impl Pallet { let new_balance = old_balance .checked_sub(pool_tokens) .ok_or(Error::::AccountBalanceIsInvalid)?; - *balance = (new_balance != 0).then(|| new_balance); + *balance = (new_balance != 0).then_some(new_balance); if balance.is_none() { // does not return anything, so we don't need to handle errors frame_system::Pallet::::dec_consumers(user_account) @@ -191,7 +191,7 @@ impl Pallet { Ok(()) }); result?; - let result: Result<_, Error> = TotalIssuances::::mutate(&pool_account, |issuance| { + let result: Result<_, Error> = TotalIssuances::::mutate(pool_account, |issuance| { let new_issuance = issuance .unwrap_or(0) .checked_add(pool_tokens) @@ -212,13 +212,13 @@ impl Pallet { ensure!(asset_a != asset_b, Error::::AssetsMustNotBeSame); if asset_a == base_asset_id { Ok(TradingPair { - base_asset_id: asset_a.clone(), - target_asset_id: asset_b.clone(), + base_asset_id: *asset_a, + target_asset_id: *asset_b, }) } else if asset_b == base_asset_id { Ok(TradingPair { - base_asset_id: asset_b.clone(), - target_asset_id: asset_a.clone(), + base_asset_id: *asset_b, + target_asset_id: *asset_a, }) } else { fail!(Error::::BaseAssetIsNotMatchedWithAnyAssetArguments)