From 3c0a0f052248e61458b9a85d16d031a8964971c1 Mon Sep 17 00:00:00 2001 From: Raphael Date: Mon, 4 Nov 2024 17:53:28 +0100 Subject: [PATCH 01/18] test: add first test for creating a pool --- pallets/pallet-bonded-coins/src/lib.rs | 4 +- pallets/pallet-bonded-coins/src/tests/mod.rs | 1 + .../src/tests/transactions/create_pool.rs | 92 +++++++++++++++++++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/lib.rs b/pallets/pallet-bonded-coins/src/lib.rs index 11489bc7ee..3ce9203d66 100644 --- a/pallets/pallet-bonded-coins/src/lib.rs +++ b/pallets/pallet-bonded-coins/src/lib.rs @@ -961,13 +961,13 @@ pub mod pallet { Ok((currency_array, start_id)) } - fn get_currencies_number(pool_details: &PoolDetailsOf) -> u32 { + pub(crate) fn get_currencies_number(pool_details: &PoolDetailsOf) -> u32 { // bonded_currencies is a BoundedVec with maximum length MaxCurrencies, which is // a u32; conversion to u32 must thus be lossless. pool_details.bonded_currencies.len().saturated_into() } - fn calculate_pool_deposit>>( + pub(crate) fn calculate_pool_deposit>>( n_currencies: N, ) -> DepositCurrencyBalanceOf { T::BaseDeposit::get() diff --git a/pallets/pallet-bonded-coins/src/tests/mod.rs b/pallets/pallet-bonded-coins/src/tests/mod.rs index 37b9348257..35baf87951 100644 --- a/pallets/pallet-bonded-coins/src/tests/mod.rs +++ b/pallets/pallet-bonded-coins/src/tests/mod.rs @@ -1 +1,2 @@ mod curves; +mod transactions; diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index 8b13789179..ca13015d46 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -1 +1,93 @@ +use core::ops::Sub; +use frame_support::assert_ok; +use frame_system::RawOrigin; +use pallet_assets::Event as AssetsPalletEvents; +use sp_runtime::BoundedVec; + +use crate::{ + mock::{calculate_pool_id, get_linear_bonding_curve_input, runtime::*, ACCOUNT_00, DEFAULT_COLLATERAL_CURRENCY_ID}, + types::PoolStatus, + Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, +}; + +#[test] +fn creates_pool() { + let initial_balance = 100_000_000_000_000_000u128; + ExtBuilder::default() + .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) + .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) + .build() + .execute_with(|| { + assert!(NextAssetId::::get() == 0); + assert_eq!(initial_balance, Balances::free_balance(ACCOUNT_00)); + + let origin = RawOrigin::Signed(ACCOUNT_00).into(); + let curve = get_linear_bonding_curve_input(); + + let bonded_token = TokenMetaOf:: { + name: BoundedVec::truncate_from(b"Bitcoin".to_vec()), + symbol: BoundedVec::truncate_from(b"btc".to_vec()), + min_balance: 1, + }; + + assert_ok!(BondingPallet::create_pool( + origin, + curve, + DEFAULT_COLLATERAL_CURRENCY_ID, + BoundedVec::truncate_from(vec![bonded_token]), + 10, + true + )); + + let pool_id = calculate_pool_id(vec![0]); + + let details = Pools::::get(&pool_id).unwrap(); + + assert!(details.is_owner(&ACCOUNT_00)); + assert!(details.is_manager(&ACCOUNT_00)); + assert!(details.transferable); + assert_eq!(details.state, PoolStatus::Locked(Default::default())); + assert_eq!(details.denomination, 10); + assert_eq!(details.collateral_id, DEFAULT_COLLATERAL_CURRENCY_ID); + assert_eq!(details.bonded_currencies.len(), 1); + assert_eq!(details.bonded_currencies[0], 0); + + assert!(NextAssetId::::get() == 1); + + assert!( + Balances::free_balance(ACCOUNT_00) == initial_balance.sub(BondingPallet::calculate_pool_deposit(1)) + ); + + System::assert_has_event(BondingPalletEvents::PoolCreated { id: pool_id.clone() }.into()); + + // TODO: check events or storage of linked pallets? + System::assert_has_event( + AssetsPalletEvents::ForceCreated { + asset_id: 0, + owner: pool_id.clone(), + } + .into(), + ); + + System::assert_has_event( + AssetsPalletEvents::MetadataSet { + asset_id: 0, + name: b"Bitcoin".into(), + symbol: b"btc".into(), + decimals: 10, + is_frozen: false, + } + .into(), + ); + + System::assert_has_event( + AssetsPalletEvents::Touched { + asset_id: DEFAULT_COLLATERAL_CURRENCY_ID, + who: pool_id.clone(), + depositor: ACCOUNT_00, + } + .into(), + ); + }); +} From 1b06c732bea55a9a98d43e61bec1b01aa040ef30 Mon Sep 17 00:00:00 2001 From: Raphael Date: Mon, 4 Nov 2024 18:27:34 +0100 Subject: [PATCH 02/18] test: test creation with multiple currencies --- .../src/tests/transactions/create_pool.rs | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index ca13015d46..ce74643ec1 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -12,7 +12,7 @@ use crate::{ }; #[test] -fn creates_pool() { +fn single_currency() { let initial_balance = 100_000_000_000_000_000u128; ExtBuilder::default() .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) @@ -91,3 +91,51 @@ fn creates_pool() { ); }); } + +#[test] +fn multi_currency() { + let initial_balance = 100_000_000_000_000_000u128; + ExtBuilder::default() + .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) + .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) + .build() + .execute_with(|| { + assert!(NextAssetId::::get() == 0); + assert_eq!(initial_balance, Balances::free_balance(ACCOUNT_00)); + + let origin = RawOrigin::Signed(ACCOUNT_00).into(); + let curve = get_linear_bonding_curve_input(); + + let bonded_token = TokenMetaOf:: { + name: BoundedVec::truncate_from(b"Bitcoin".to_vec()), + symbol: BoundedVec::truncate_from(b"btc".to_vec()), + min_balance: 1, + }; + + let bonded_tokens = vec![bonded_token; 3]; + + assert_eq!(bonded_tokens.len(), 3); + + assert_ok!(BondingPallet::create_pool( + origin, + curve, + DEFAULT_COLLATERAL_CURRENCY_ID, + BoundedVec::truncate_from(bonded_tokens), + 10, + true + )); + + assert!(NextAssetId::::get() == 3); + + let pool_id = calculate_pool_id(vec![0, 1, 2]); + + let details = Pools::::get(pool_id).unwrap(); + + assert_eq!(BondingPallet::get_currencies_number(&details), 3); + assert_eq!(details.bonded_currencies, vec![0, 1, 2]); + + assert!( + Balances::free_balance(ACCOUNT_00) == initial_balance.sub(BondingPallet::calculate_pool_deposit(3)) + ); + }); +} From ff01cd7a69514d37c2bd3b0b2dba4ca0b2f7acd9 Mon Sep 17 00:00:00 2001 From: Raphael Date: Mon, 4 Nov 2024 18:36:11 +0100 Subject: [PATCH 03/18] test: check for collateral --- .../src/tests/transactions/create_pool.rs | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index ce74643ec1..72de7ee344 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -1,8 +1,8 @@ use core::ops::Sub; -use frame_support::assert_ok; +use frame_support::{assert_err, assert_ok}; use frame_system::RawOrigin; -use pallet_assets::Event as AssetsPalletEvents; +use pallet_assets::{Error as AssetsPalletErrors, Event as AssetsPalletEvents}; use sp_runtime::BoundedVec; use crate::{ @@ -139,3 +139,32 @@ fn multi_currency() { ); }); } + +#[test] +fn fails_if_collateral_not_exists() { + ExtBuilder::default() + .with_native_balances(vec![(ACCOUNT_00, 100_000_000_000_000_000u128)]) + .build() + .execute_with(|| { + let origin = RawOrigin::Signed(ACCOUNT_00).into(); + let curve = get_linear_bonding_curve_input(); + + let bonded_token = TokenMetaOf:: { + name: BoundedVec::truncate_from(b"Bitcoin".to_vec()), + symbol: BoundedVec::truncate_from(b"btc".to_vec()), + min_balance: 1, + }; + + assert_err!( + BondingPallet::create_pool( + origin, + curve, + DEFAULT_COLLATERAL_CURRENCY_ID, + BoundedVec::truncate_from(vec![bonded_token]), + 10, + true + ), + AssetsPalletErrors::::Unknown + ); + }) +} From f146c301bb58acefa40af1edfe776ca7437decad Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 5 Nov 2024 11:01:33 +0100 Subject: [PATCH 04/18] test: can create identical pools --- .../src/tests/transactions/create_pool.rs | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index 72de7ee344..a8e152d6eb 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -1,7 +1,7 @@ use core::ops::Sub; use frame_support::{assert_err, assert_ok}; -use frame_system::RawOrigin; +use frame_system::{pallet_prelude::OriginFor, RawOrigin}; use pallet_assets::{Error as AssetsPalletErrors, Event as AssetsPalletEvents}; use sp_runtime::BoundedVec; @@ -140,6 +140,53 @@ fn multi_currency() { }); } +#[test] +fn can_create_identical_pools() { + let initial_balance = 100_000_000_000_000_000u128; + ExtBuilder::default() + .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) + .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) + .build() + .execute_with(|| { + assert_eq!(NextAssetId::::get(), 0); + + let origin: OriginFor = RawOrigin::Signed(ACCOUNT_00).into(); + let curve = get_linear_bonding_curve_input(); + + let bonded_token = TokenMetaOf:: { + name: BoundedVec::truncate_from(b"Bitcoin".to_vec()), + symbol: BoundedVec::truncate_from(b"btc".to_vec()), + min_balance: 1, + }; + + assert_ok!(BondingPallet::create_pool( + origin.clone(), + curve.clone(), + DEFAULT_COLLATERAL_CURRENCY_ID, + BoundedVec::truncate_from(vec![bonded_token.clone()]), + 10, + true + )); + + assert_ok!(BondingPallet::create_pool( + origin, + curve, + DEFAULT_COLLATERAL_CURRENCY_ID, + BoundedVec::truncate_from(vec![bonded_token]), + 10, + true + )); + + assert_eq!(NextAssetId::::get(), 2); + + let details1 = Pools::::get(calculate_pool_id(vec![0])).unwrap(); + let details2 = Pools::::get(calculate_pool_id(vec![1])).unwrap(); + + assert_eq!(details1.bonded_currencies, vec![0]); + assert_eq!(details2.bonded_currencies, vec![1]); + }); +} + #[test] fn fails_if_collateral_not_exists() { ExtBuilder::default() From dc115b781442d0ff30141264feb7ab48c2e45016 Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 5 Nov 2024 11:11:05 +0100 Subject: [PATCH 05/18] test: use assert_eq! --- .../src/tests/transactions/create_pool.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index a8e152d6eb..655509b05d 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -19,7 +19,7 @@ fn single_currency() { .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) .build() .execute_with(|| { - assert!(NextAssetId::::get() == 0); + assert_eq!(NextAssetId::::get(), 0); assert_eq!(initial_balance, Balances::free_balance(ACCOUNT_00)); let origin = RawOrigin::Signed(ACCOUNT_00).into(); @@ -53,10 +53,11 @@ fn single_currency() { assert_eq!(details.bonded_currencies.len(), 1); assert_eq!(details.bonded_currencies[0], 0); - assert!(NextAssetId::::get() == 1); + assert_eq!(NextAssetId::::get(), 1); - assert!( - Balances::free_balance(ACCOUNT_00) == initial_balance.sub(BondingPallet::calculate_pool_deposit(1)) + assert_eq!( + Balances::free_balance(ACCOUNT_00), + initial_balance.sub(BondingPallet::calculate_pool_deposit(1)) ); System::assert_has_event(BondingPalletEvents::PoolCreated { id: pool_id.clone() }.into()); @@ -100,7 +101,7 @@ fn multi_currency() { .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) .build() .execute_with(|| { - assert!(NextAssetId::::get() == 0); + assert_eq!(NextAssetId::::get(), 0); assert_eq!(initial_balance, Balances::free_balance(ACCOUNT_00)); let origin = RawOrigin::Signed(ACCOUNT_00).into(); @@ -125,7 +126,7 @@ fn multi_currency() { true )); - assert!(NextAssetId::::get() == 3); + assert_eq!(NextAssetId::::get(), 3); let pool_id = calculate_pool_id(vec![0, 1, 2]); @@ -134,8 +135,9 @@ fn multi_currency() { assert_eq!(BondingPallet::get_currencies_number(&details), 3); assert_eq!(details.bonded_currencies, vec![0, 1, 2]); - assert!( - Balances::free_balance(ACCOUNT_00) == initial_balance.sub(BondingPallet::calculate_pool_deposit(3)) + assert_eq!( + Balances::free_balance(ACCOUNT_00), + initial_balance.sub(BondingPallet::calculate_pool_deposit(3)) ); }); } From 22b9b01ea87b98fa3e3c103a813e24d782f3e789 Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 5 Nov 2024 13:36:09 +0100 Subject: [PATCH 06/18] test: reset pool manager --- .../src/tests/transactions/create_pool.rs | 94 ++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index 655509b05d..2e0058092c 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -6,9 +6,12 @@ use pallet_assets::{Error as AssetsPalletErrors, Event as AssetsPalletEvents}; use sp_runtime::BoundedVec; use crate::{ - mock::{calculate_pool_id, get_linear_bonding_curve_input, runtime::*, ACCOUNT_00, DEFAULT_COLLATERAL_CURRENCY_ID}, + mock::{ + calculate_pool_id, get_linear_bonding_curve, get_linear_bonding_curve_input, runtime::*, AccountId, ACCOUNT_00, + ACCOUNT_01, DEFAULT_COLLATERAL_CURRENCY_ID, + }, types::PoolStatus, - Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, + Error as BondingPalletErrors, Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, }; #[test] @@ -217,3 +220,90 @@ fn fails_if_collateral_not_exists() { ); }) } + +#[test] +fn changes_manager() { + let curve = get_linear_bonding_curve(); + + let pool_details = generate_pool_details( + vec![0], + curve, + None, + Some(PoolStatus::Active), + Some(ACCOUNT_00), + None, + None, + ); + let pool_id = calculate_pool_id(vec![0]); + ExtBuilder::default() + .with_pools(vec![(pool_id.clone(), pool_details.clone())]) + .build() + .execute_with(|| { + let origin = RawOrigin::Signed(ACCOUNT_00).into(); + assert_ok!(BondingPallet::reset_manager(origin, pool_id.clone(), Some(ACCOUNT_01))); + + System::assert_has_event( + BondingPalletEvents::ManagerUpdated { + id: pool_id.clone(), + manager: Some(ACCOUNT_01), + } + .into(), + ); + + let new_details = Pools::::get(&pool_id).unwrap(); + assert_eq!(new_details.manager, Some(ACCOUNT_01)); + assert_eq!(new_details.owner, pool_details.owner) + }) +} + +#[test] +fn only_manager_can_change_manager() { + let curve = get_linear_bonding_curve(); + + let manager = AccountId::new([10u8; 32]); + let pool_details = generate_pool_details( + vec![0], + curve, + None, + Some(PoolStatus::Active), + Some(manager.clone()), + None, + Some(ACCOUNT_00), + ); + let pool_id = calculate_pool_id(vec![0]); + ExtBuilder::default() + .with_pools(vec![(pool_id.clone(), pool_details.clone())]) + .build() + .execute_with(|| { + let owner_origin = RawOrigin::Signed(ACCOUNT_00).into(); + let other_origin = RawOrigin::Signed(ACCOUNT_01).into(); + + assert_err!( + BondingPallet::reset_manager(owner_origin, pool_id.clone(), Some(ACCOUNT_00)), + BondingPalletErrors::::NoPermission + ); + + assert_err!( + BondingPallet::reset_manager(other_origin, pool_id.clone(), Some(ACCOUNT_00)), + BondingPalletErrors::::NoPermission + ); + + let new_details = Pools::::get(&pool_id).unwrap(); + assert_eq!(new_details.manager, Some(manager)); + }) +} + +#[test] +fn cant_change_manager_if_pool_nonexistent() { + let pool_id = calculate_pool_id(vec![0]); + ExtBuilder::default().build().execute_with(|| { + let origin = RawOrigin::Signed(ACCOUNT_00).into(); + + assert!(Pools::::get(&pool_id).is_none()); + + assert_err!( + BondingPallet::reset_manager(origin, pool_id.clone(), Some(ACCOUNT_00)), + BondingPalletErrors::::PoolUnknown + ); + }) +} From 6d1ac6125a71a35c209bbcef32dd00f5f6121ebd Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 5 Nov 2024 14:02:04 +0100 Subject: [PATCH 07/18] test: asset id overflow --- .../src/tests/transactions/create_pool.rs | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index 2e0058092c..8b772cba53 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -1,9 +1,8 @@ -use core::ops::Sub; - use frame_support::{assert_err, assert_ok}; use frame_system::{pallet_prelude::OriginFor, RawOrigin}; use pallet_assets::{Error as AssetsPalletErrors, Event as AssetsPalletEvents}; -use sp_runtime::BoundedVec; +use sp_runtime::{ArithmeticError, BoundedVec}; +use sp_std::ops::Sub; use crate::{ mock::{ @@ -221,6 +220,39 @@ fn fails_if_collateral_not_exists() { }) } +#[test] +fn handles_asset_id_overflow() { + let initial_balance = 100_000_000_000_000_000u128; + ExtBuilder::default() + .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) + .with_collaterals(vec![0]) + .build() + .execute_with(|| { + NextAssetId::::set(u32::MAX); + + let origin = RawOrigin::Signed(ACCOUNT_00).into(); + let curve = get_linear_bonding_curve_input(); + + let bonded_token = TokenMetaOf:: { + name: BoundedVec::truncate_from(b"Bitcoin".to_vec()), + symbol: BoundedVec::truncate_from(b"btc".to_vec()), + min_balance: 1, + }; + + assert_err!( + BondingPallet::create_pool( + origin, + curve, + 0, + BoundedVec::truncate_from(vec![bonded_token; 2]), + 10, + true + ), + ArithmeticError::Overflow + ); + }); +} + #[test] fn changes_manager() { let curve = get_linear_bonding_curve(); From 23e32ceba3199714538ed91e0845858ffabee3d0 Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 5 Nov 2024 14:31:35 +0100 Subject: [PATCH 08/18] test: reset team --- .../src/tests/transactions/create_pool.rs | 170 +++++++++++++++++- 1 file changed, 169 insertions(+), 1 deletion(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index 8b772cba53..efe9a835eb 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -9,10 +9,12 @@ use crate::{ calculate_pool_id, get_linear_bonding_curve, get_linear_bonding_curve_input, runtime::*, AccountId, ACCOUNT_00, ACCOUNT_01, DEFAULT_COLLATERAL_CURRENCY_ID, }, - types::PoolStatus, + types::{PoolManagingTeam, PoolStatus}, Error as BondingPalletErrors, Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, }; +// create_pool tests + #[test] fn single_currency() { let initial_balance = 100_000_000_000_000_000u128; @@ -253,6 +255,8 @@ fn handles_asset_id_overflow() { }); } +// reset_manager tests + #[test] fn changes_manager() { let curve = get_linear_bonding_curve(); @@ -339,3 +343,167 @@ fn cant_change_manager_if_pool_nonexistent() { ); }) } + +// reset_team tests + +#[test] +fn resets_team() { + let pool_details = generate_pool_details( + vec![0], + get_linear_bonding_curve(), + None, + Some(PoolStatus::Active), + Some(ACCOUNT_00), + None, + None, + ); + let pool_id = calculate_pool_id(vec![0]); + + ExtBuilder::default() + .with_pools(vec![(pool_id.clone(), pool_details.clone())]) + .build() + .execute_with(|| { + let manager_origin = RawOrigin::Signed(ACCOUNT_00).into(); + + assert_ok!(BondingPallet::reset_team( + manager_origin, + pool_id.clone(), + PoolManagingTeam { + admin: ACCOUNT_00, + freezer: ACCOUNT_01, + }, + 0 + )); + + System::assert_has_event( + AssetsPalletEvents::::TeamChanged { + asset_id: 0, + issuer: pool_id, + admin: ACCOUNT_00, + freezer: ACCOUNT_01, + } + .into(), + ); + }) +} + +#[test] +fn does_not_change_team_when_not_live() { + let pool_details = generate_pool_details( + vec![0], + get_linear_bonding_curve(), + None, + Some(PoolStatus::Refunding), + Some(ACCOUNT_00), + None, + None, + ); + let pool_id = calculate_pool_id(vec![0]); + + ExtBuilder::default() + .with_pools(vec![(pool_id.clone(), pool_details.clone())]) + .build() + .execute_with(|| { + let manager_origin = RawOrigin::Signed(ACCOUNT_00).into(); + + assert_err!( + BondingPallet::reset_team( + manager_origin, + pool_id.clone(), + PoolManagingTeam { + admin: ACCOUNT_00, + freezer: ACCOUNT_00, + }, + 0 + ), + BondingPalletErrors::::PoolNotLive + ); + }) +} + +#[test] +fn only_manager_can_change_team() { + let curve = get_linear_bonding_curve(); + + let manager = AccountId::new([10u8; 32]); + let pool_details = generate_pool_details( + vec![0], + curve, + None, + Some(PoolStatus::Active), + Some(manager.clone()), + None, + Some(ACCOUNT_00), + ); + let pool_id = calculate_pool_id(vec![0]); + ExtBuilder::default() + .with_pools(vec![(pool_id.clone(), pool_details.clone())]) + .build() + .execute_with(|| { + let owner_origin = RawOrigin::Signed(ACCOUNT_00).into(); + let other_origin = RawOrigin::Signed(ACCOUNT_01).into(); + + assert_err!( + BondingPallet::reset_team( + owner_origin, + pool_id.clone(), + PoolManagingTeam { + admin: ACCOUNT_00, + freezer: ACCOUNT_00, + }, + 0 + ), + BondingPalletErrors::::NoPermission + ); + + assert_err!( + BondingPallet::reset_team( + other_origin, + pool_id.clone(), + PoolManagingTeam { + admin: ACCOUNT_00, + freezer: ACCOUNT_00, + }, + 0 + ), + BondingPalletErrors::::NoPermission + ); + + let new_details = Pools::::get(&pool_id).unwrap(); + assert_eq!(new_details.manager, Some(manager)); + }) +} + +#[test] +fn handles_currency_idx_out_of_bounds() { + let pool_details = generate_pool_details( + vec![0], + get_linear_bonding_curve(), + None, + Some(PoolStatus::Active), + Some(ACCOUNT_00), + None, + None, + ); + let pool_id = calculate_pool_id(vec![0]); + + ExtBuilder::default() + .with_pools(vec![(pool_id.clone(), pool_details.clone())]) + .build() + .execute_with(|| { + let manager_origin = RawOrigin::Signed(ACCOUNT_00).into(); + + assert_err!( + BondingPallet::reset_team( + manager_origin, + pool_id.clone(), + PoolManagingTeam { + admin: ACCOUNT_00, + freezer: ACCOUNT_00, + }, + 2 + ), + BondingPalletErrors::::IndexOutOfBounds + ); + }) +} From eabd5542edcc320645a5d9391b62f884e4ad03ee Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 5 Nov 2024 15:38:50 +0100 Subject: [PATCH 09/18] chore: fix tests after rebase --- .../src/tests/transactions/create_pool.rs | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index efe9a835eb..0ea56b4ef1 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -5,10 +5,8 @@ use sp_runtime::{ArithmeticError, BoundedVec}; use sp_std::ops::Sub; use crate::{ - mock::{ - calculate_pool_id, get_linear_bonding_curve, get_linear_bonding_curve_input, runtime::*, AccountId, ACCOUNT_00, - ACCOUNT_01, DEFAULT_COLLATERAL_CURRENCY_ID, - }, + mock::runtime::*, + mock::*, types::{PoolManagingTeam, PoolStatus}, Error as BondingPalletErrors, Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, }; @@ -44,7 +42,7 @@ fn single_currency() { true )); - let pool_id = calculate_pool_id(vec![0]); + let pool_id = calculate_pool_id(&[0]); let details = Pools::::get(&pool_id).unwrap(); @@ -132,7 +130,7 @@ fn multi_currency() { assert_eq!(NextAssetId::::get(), 3); - let pool_id = calculate_pool_id(vec![0, 1, 2]); + let pool_id = calculate_pool_id(&[0, 1, 2]); let details = Pools::::get(pool_id).unwrap(); @@ -185,8 +183,8 @@ fn can_create_identical_pools() { assert_eq!(NextAssetId::::get(), 2); - let details1 = Pools::::get(calculate_pool_id(vec![0])).unwrap(); - let details2 = Pools::::get(calculate_pool_id(vec![1])).unwrap(); + let details1 = Pools::::get(calculate_pool_id(&[0])).unwrap(); + let details2 = Pools::::get(calculate_pool_id(&[1])).unwrap(); assert_eq!(details1.bonded_currencies, vec![0]); assert_eq!(details2.bonded_currencies, vec![1]); @@ -264,13 +262,13 @@ fn changes_manager() { let pool_details = generate_pool_details( vec![0], curve, - None, + false, Some(PoolStatus::Active), Some(ACCOUNT_00), None, None, ); - let pool_id = calculate_pool_id(vec![0]); + let pool_id = calculate_pool_id(&[0]); ExtBuilder::default() .with_pools(vec![(pool_id.clone(), pool_details.clone())]) .build() @@ -300,13 +298,13 @@ fn only_manager_can_change_manager() { let pool_details = generate_pool_details( vec![0], curve, - None, + false, Some(PoolStatus::Active), Some(manager.clone()), None, Some(ACCOUNT_00), ); - let pool_id = calculate_pool_id(vec![0]); + let pool_id = calculate_pool_id(&[0]); ExtBuilder::default() .with_pools(vec![(pool_id.clone(), pool_details.clone())]) .build() @@ -331,7 +329,7 @@ fn only_manager_can_change_manager() { #[test] fn cant_change_manager_if_pool_nonexistent() { - let pool_id = calculate_pool_id(vec![0]); + let pool_id = calculate_pool_id(&[0]); ExtBuilder::default().build().execute_with(|| { let origin = RawOrigin::Signed(ACCOUNT_00).into(); @@ -351,13 +349,13 @@ fn resets_team() { let pool_details = generate_pool_details( vec![0], get_linear_bonding_curve(), - None, + false, Some(PoolStatus::Active), Some(ACCOUNT_00), None, None, ); - let pool_id = calculate_pool_id(vec![0]); + let pool_id = calculate_pool_id(&[0]); ExtBuilder::default() .with_pools(vec![(pool_id.clone(), pool_details.clone())]) @@ -392,13 +390,13 @@ fn does_not_change_team_when_not_live() { let pool_details = generate_pool_details( vec![0], get_linear_bonding_curve(), - None, + false, Some(PoolStatus::Refunding), Some(ACCOUNT_00), None, None, ); - let pool_id = calculate_pool_id(vec![0]); + let pool_id = calculate_pool_id(&[0]); ExtBuilder::default() .with_pools(vec![(pool_id.clone(), pool_details.clone())]) @@ -429,13 +427,13 @@ fn only_manager_can_change_team() { let pool_details = generate_pool_details( vec![0], curve, - None, + false, Some(PoolStatus::Active), Some(manager.clone()), None, Some(ACCOUNT_00), ); - let pool_id = calculate_pool_id(vec![0]); + let pool_id = calculate_pool_id(&[0]); ExtBuilder::default() .with_pools(vec![(pool_id.clone(), pool_details.clone())]) .build() @@ -479,13 +477,13 @@ fn handles_currency_idx_out_of_bounds() { let pool_details = generate_pool_details( vec![0], get_linear_bonding_curve(), - None, + false, Some(PoolStatus::Active), Some(ACCOUNT_00), None, None, ); - let pool_id = calculate_pool_id(vec![0]); + let pool_id = calculate_pool_id(&[0]); ExtBuilder::default() .with_pools(vec![(pool_id.clone(), pool_details.clone())]) From 85f02c4ea0446b4965decab51cc30ca202df8fbc Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 5 Nov 2024 16:25:17 +0100 Subject: [PATCH 10/18] chore: move reset_{manager,team} tests to their own files --- .../src/tests/transactions/create_pool.rs | 258 +----------------- .../src/tests/transactions/mod.rs | 1 - 2 files changed, 1 insertion(+), 258 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index 0ea56b4ef1..e099d5d450 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -5,10 +5,7 @@ use sp_runtime::{ArithmeticError, BoundedVec}; use sp_std::ops::Sub; use crate::{ - mock::runtime::*, - mock::*, - types::{PoolManagingTeam, PoolStatus}, - Error as BondingPalletErrors, Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, + mock::runtime::*, mock::*, types::PoolStatus, Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, }; // create_pool tests @@ -252,256 +249,3 @@ fn handles_asset_id_overflow() { ); }); } - -// reset_manager tests - -#[test] -fn changes_manager() { - let curve = get_linear_bonding_curve(); - - let pool_details = generate_pool_details( - vec![0], - curve, - false, - Some(PoolStatus::Active), - Some(ACCOUNT_00), - None, - None, - ); - let pool_id = calculate_pool_id(&[0]); - ExtBuilder::default() - .with_pools(vec![(pool_id.clone(), pool_details.clone())]) - .build() - .execute_with(|| { - let origin = RawOrigin::Signed(ACCOUNT_00).into(); - assert_ok!(BondingPallet::reset_manager(origin, pool_id.clone(), Some(ACCOUNT_01))); - - System::assert_has_event( - BondingPalletEvents::ManagerUpdated { - id: pool_id.clone(), - manager: Some(ACCOUNT_01), - } - .into(), - ); - - let new_details = Pools::::get(&pool_id).unwrap(); - assert_eq!(new_details.manager, Some(ACCOUNT_01)); - assert_eq!(new_details.owner, pool_details.owner) - }) -} - -#[test] -fn only_manager_can_change_manager() { - let curve = get_linear_bonding_curve(); - - let manager = AccountId::new([10u8; 32]); - let pool_details = generate_pool_details( - vec![0], - curve, - false, - Some(PoolStatus::Active), - Some(manager.clone()), - None, - Some(ACCOUNT_00), - ); - let pool_id = calculate_pool_id(&[0]); - ExtBuilder::default() - .with_pools(vec![(pool_id.clone(), pool_details.clone())]) - .build() - .execute_with(|| { - let owner_origin = RawOrigin::Signed(ACCOUNT_00).into(); - let other_origin = RawOrigin::Signed(ACCOUNT_01).into(); - - assert_err!( - BondingPallet::reset_manager(owner_origin, pool_id.clone(), Some(ACCOUNT_00)), - BondingPalletErrors::::NoPermission - ); - - assert_err!( - BondingPallet::reset_manager(other_origin, pool_id.clone(), Some(ACCOUNT_00)), - BondingPalletErrors::::NoPermission - ); - - let new_details = Pools::::get(&pool_id).unwrap(); - assert_eq!(new_details.manager, Some(manager)); - }) -} - -#[test] -fn cant_change_manager_if_pool_nonexistent() { - let pool_id = calculate_pool_id(&[0]); - ExtBuilder::default().build().execute_with(|| { - let origin = RawOrigin::Signed(ACCOUNT_00).into(); - - assert!(Pools::::get(&pool_id).is_none()); - - assert_err!( - BondingPallet::reset_manager(origin, pool_id.clone(), Some(ACCOUNT_00)), - BondingPalletErrors::::PoolUnknown - ); - }) -} - -// reset_team tests - -#[test] -fn resets_team() { - let pool_details = generate_pool_details( - vec![0], - get_linear_bonding_curve(), - false, - Some(PoolStatus::Active), - Some(ACCOUNT_00), - None, - None, - ); - let pool_id = calculate_pool_id(&[0]); - - ExtBuilder::default() - .with_pools(vec![(pool_id.clone(), pool_details.clone())]) - .build() - .execute_with(|| { - let manager_origin = RawOrigin::Signed(ACCOUNT_00).into(); - - assert_ok!(BondingPallet::reset_team( - manager_origin, - pool_id.clone(), - PoolManagingTeam { - admin: ACCOUNT_00, - freezer: ACCOUNT_01, - }, - 0 - )); - - System::assert_has_event( - AssetsPalletEvents::::TeamChanged { - asset_id: 0, - issuer: pool_id, - admin: ACCOUNT_00, - freezer: ACCOUNT_01, - } - .into(), - ); - }) -} - -#[test] -fn does_not_change_team_when_not_live() { - let pool_details = generate_pool_details( - vec![0], - get_linear_bonding_curve(), - false, - Some(PoolStatus::Refunding), - Some(ACCOUNT_00), - None, - None, - ); - let pool_id = calculate_pool_id(&[0]); - - ExtBuilder::default() - .with_pools(vec![(pool_id.clone(), pool_details.clone())]) - .build() - .execute_with(|| { - let manager_origin = RawOrigin::Signed(ACCOUNT_00).into(); - - assert_err!( - BondingPallet::reset_team( - manager_origin, - pool_id.clone(), - PoolManagingTeam { - admin: ACCOUNT_00, - freezer: ACCOUNT_00, - }, - 0 - ), - BondingPalletErrors::::PoolNotLive - ); - }) -} - -#[test] -fn only_manager_can_change_team() { - let curve = get_linear_bonding_curve(); - - let manager = AccountId::new([10u8; 32]); - let pool_details = generate_pool_details( - vec![0], - curve, - false, - Some(PoolStatus::Active), - Some(manager.clone()), - None, - Some(ACCOUNT_00), - ); - let pool_id = calculate_pool_id(&[0]); - ExtBuilder::default() - .with_pools(vec![(pool_id.clone(), pool_details.clone())]) - .build() - .execute_with(|| { - let owner_origin = RawOrigin::Signed(ACCOUNT_00).into(); - let other_origin = RawOrigin::Signed(ACCOUNT_01).into(); - - assert_err!( - BondingPallet::reset_team( - owner_origin, - pool_id.clone(), - PoolManagingTeam { - admin: ACCOUNT_00, - freezer: ACCOUNT_00, - }, - 0 - ), - BondingPalletErrors::::NoPermission - ); - - assert_err!( - BondingPallet::reset_team( - other_origin, - pool_id.clone(), - PoolManagingTeam { - admin: ACCOUNT_00, - freezer: ACCOUNT_00, - }, - 0 - ), - BondingPalletErrors::::NoPermission - ); - - let new_details = Pools::::get(&pool_id).unwrap(); - assert_eq!(new_details.manager, Some(manager)); - }) -} - -#[test] -fn handles_currency_idx_out_of_bounds() { - let pool_details = generate_pool_details( - vec![0], - get_linear_bonding_curve(), - false, - Some(PoolStatus::Active), - Some(ACCOUNT_00), - None, - None, - ); - let pool_id = calculate_pool_id(&[0]); - - ExtBuilder::default() - .with_pools(vec![(pool_id.clone(), pool_details.clone())]) - .build() - .execute_with(|| { - let manager_origin = RawOrigin::Signed(ACCOUNT_00).into(); - - assert_err!( - BondingPallet::reset_team( - manager_origin, - pool_id.clone(), - PoolManagingTeam { - admin: ACCOUNT_00, - freezer: ACCOUNT_00, - }, - 2 - ), - BondingPalletErrors::::IndexOutOfBounds - ); - }) -} diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/mod.rs b/pallets/pallet-bonded-coins/src/tests/transactions/mod.rs index 1e13361980..ca68349384 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/mod.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/mod.rs @@ -3,5 +3,4 @@ mod create_pool; mod mint_into; mod set_lock; mod swap_into; - mod unlock; From 9ac43a456db5e98a1b95b4c1dd5ee135bd5f42f5 Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 5 Nov 2024 17:28:04 +0100 Subject: [PATCH 11/18] chore: fmt --- pallets/pallet-bonded-coins/src/traits.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/traits.rs b/pallets/pallet-bonded-coins/src/traits.rs index 8f35477ff9..ee442f3823 100644 --- a/pallets/pallet-bonded-coins/src/traits.rs +++ b/pallets/pallet-bonded-coins/src/traits.rs @@ -13,7 +13,6 @@ pub trait FreezeAccounts { fn thaw(asset_id: &AssetId, who: &AccountId) -> Result<(), Self::Error>; } - type AssetIdOf = ::AssetId; impl FreezeAccounts, ::AssetId> for AssetsPallet @@ -39,9 +38,8 @@ where } } - /// Copy from the Polkadot SDK. once we are at version 1.13.0, we can remove -/// this. +/// this. pub trait ResetTeam: Inspect { /// Reset the team for the asset with the given `id`. /// From 0423e17f1e8d35574f3912fa72c38e21e4c9c745 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 6 Nov 2024 10:57:55 +0100 Subject: [PATCH 12/18] chore: do not use default value to check locks --- .../src/tests/transactions/create_pool.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index e099d5d450..911789e435 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -5,7 +5,9 @@ use sp_runtime::{ArithmeticError, BoundedVec}; use sp_std::ops::Sub; use crate::{ - mock::runtime::*, mock::*, types::PoolStatus, Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, + mock::{runtime::*, *}, + types::{Locks, PoolStatus}, + Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, }; // create_pool tests @@ -46,7 +48,14 @@ fn single_currency() { assert!(details.is_owner(&ACCOUNT_00)); assert!(details.is_manager(&ACCOUNT_00)); assert!(details.transferable); - assert_eq!(details.state, PoolStatus::Locked(Default::default())); + assert_eq!( + details.state, + PoolStatus::Locked(Locks { + allow_mint: false, + allow_burn: false, + allow_swap: false + }) + ); assert_eq!(details.denomination, 10); assert_eq!(details.collateral_id, DEFAULT_COLLATERAL_CURRENCY_ID); assert_eq!(details.bonded_currencies.len(), 1); From 63b1b43689fe3f7c95b21837e1975d7d8e07616e Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 6 Nov 2024 11:26:17 +0100 Subject: [PATCH 13/18] chore: remove initial state assertions --- .../src/tests/transactions/create_pool.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index 911789e435..db669d8993 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -20,9 +20,6 @@ fn single_currency() { .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) .build() .execute_with(|| { - assert_eq!(NextAssetId::::get(), 0); - assert_eq!(initial_balance, Balances::free_balance(ACCOUNT_00)); - let origin = RawOrigin::Signed(ACCOUNT_00).into(); let curve = get_linear_bonding_curve_input(); @@ -109,9 +106,6 @@ fn multi_currency() { .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) .build() .execute_with(|| { - assert_eq!(NextAssetId::::get(), 0); - assert_eq!(initial_balance, Balances::free_balance(ACCOUNT_00)); - let origin = RawOrigin::Signed(ACCOUNT_00).into(); let curve = get_linear_bonding_curve_input(); @@ -158,8 +152,6 @@ fn can_create_identical_pools() { .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) .build() .execute_with(|| { - assert_eq!(NextAssetId::::get(), 0); - let origin: OriginFor = RawOrigin::Signed(ACCOUNT_00).into(); let curve = get_linear_bonding_curve_input(); From 8ee167adec56509aba96a717c3905b20c366c34c Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 6 Nov 2024 12:25:19 +0100 Subject: [PATCH 14/18] test: make sure NextAssetId is set correctly in mocks --- pallets/pallet-bonded-coins/src/mock.rs | 35 ++++++++++------- .../src/tests/transactions/create_pool.rs | 39 +++++++++++-------- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/mock.rs b/pallets/pallet-bonded-coins/src/mock.rs index d1fcebd5ec..31280b097f 100644 --- a/pallets/pallet-bonded-coins/src/mock.rs +++ b/pallets/pallet-bonded-coins/src/mock.rs @@ -38,8 +38,8 @@ pub(crate) const ACCOUNT_00: AccountId = AccountId::new([0u8; 32]); pub(crate) const ACCOUNT_01: AccountId = AccountId::new([1u8; 32]); const ACCOUNT_99: AccountId = AccountId::new([99u8; 32]); // assets -pub(crate) const DEFAULT_BONDED_CURRENCY_ID: AssetId = 0; -pub(crate) const DEFAULT_COLLATERAL_CURRENCY_ID: AssetId = AssetId::MAX; +pub(crate) const DEFAULT_BONDED_CURRENCY_ID: AssetId = 1; +pub(crate) const DEFAULT_COLLATERAL_CURRENCY_ID: AssetId = 0; pub(crate) const DEFAULT_COLLATERAL_DENOMINATION: u8 = 10; pub(crate) const DEFAULT_BONDED_DENOMINATION: u8 = 10; @@ -276,19 +276,24 @@ pub mod runtime { let collateral_assets = self.collaterals.into_iter().map(|id| (id, ACCOUNT_99, false, 1)); - pallet_assets::GenesisConfig:: { - assets: self - .pools - .iter() - .flat_map(|(owner, pool)| { - pool.bonded_currencies - .iter() - .map(|id| (*id, owner.to_owned(), false, 1u128)) - .collect::>() - }) - .chain(collateral_assets) - .collect(), + let all_assets: Vec<_> = self + .pools + .iter() + .flat_map(|(owner, pool)| { + pool.bonded_currencies + .iter() + .map(|id| (*id, owner.to_owned(), false, 1u128)) + .collect::>() + }) + .chain(collateral_assets) + .collect(); + + // NextAssetId is set to the maximum value of all collateral/bonded currency ids, plus one. + // If no currencies are created, it's set to 0. + let next_asset_id = all_assets.iter().map(|(id, ..)| id).max().map_or(0, |id| id + 1); + pallet_assets::GenesisConfig:: { + assets: all_assets, accounts: self.bonded_balance, metadata: self .pools @@ -313,6 +318,8 @@ pub mod runtime { self.pools.into_iter().for_each(|(pool_id, pool)| { crate::Pools::::insert(pool_id, pool); }); + + crate::NextAssetId::::set(next_asset_id); }); ext diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index db669d8993..e277d8f861 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -29,6 +29,8 @@ fn single_currency() { min_balance: 1, }; + let new_asset_id = NextAssetId::::get(); + assert_ok!(BondingPallet::create_pool( origin, curve, @@ -38,7 +40,7 @@ fn single_currency() { true )); - let pool_id = calculate_pool_id(&[0]); + let pool_id = calculate_pool_id(&[new_asset_id]); let details = Pools::::get(&pool_id).unwrap(); @@ -55,10 +57,10 @@ fn single_currency() { ); assert_eq!(details.denomination, 10); assert_eq!(details.collateral_id, DEFAULT_COLLATERAL_CURRENCY_ID); - assert_eq!(details.bonded_currencies.len(), 1); - assert_eq!(details.bonded_currencies[0], 0); + assert_eq!(details.bonded_currencies, vec![new_asset_id]); - assert_eq!(NextAssetId::::get(), 1); + // collateral is id 0, new bonded currency should be 1, next is 2 + assert_eq!(NextAssetId::::get(), new_asset_id + 1); assert_eq!( Balances::free_balance(ACCOUNT_00), @@ -70,7 +72,7 @@ fn single_currency() { // TODO: check events or storage of linked pallets? System::assert_has_event( AssetsPalletEvents::ForceCreated { - asset_id: 0, + asset_id: new_asset_id, owner: pool_id.clone(), } .into(), @@ -78,7 +80,7 @@ fn single_currency() { System::assert_has_event( AssetsPalletEvents::MetadataSet { - asset_id: 0, + asset_id: new_asset_id, name: b"Bitcoin".into(), symbol: b"btc".into(), decimals: 10, @@ -117,7 +119,7 @@ fn multi_currency() { let bonded_tokens = vec![bonded_token; 3]; - assert_eq!(bonded_tokens.len(), 3); + let next_asset_id = NextAssetId::::get(); assert_ok!(BondingPallet::create_pool( origin, @@ -128,14 +130,15 @@ fn multi_currency() { true )); - assert_eq!(NextAssetId::::get(), 3); + assert_eq!(NextAssetId::::get(), next_asset_id + 3); - let pool_id = calculate_pool_id(&[0, 1, 2]); + let new_assets = Vec::from_iter(next_asset_id..next_asset_id + 3); + let pool_id = calculate_pool_id(&new_assets); let details = Pools::::get(pool_id).unwrap(); assert_eq!(BondingPallet::get_currencies_number(&details), 3); - assert_eq!(details.bonded_currencies, vec![0, 1, 2]); + assert_eq!(details.bonded_currencies, new_assets); assert_eq!( Balances::free_balance(ACCOUNT_00), @@ -161,6 +164,8 @@ fn can_create_identical_pools() { min_balance: 1, }; + let next_asset_id = NextAssetId::::get(); + assert_ok!(BondingPallet::create_pool( origin.clone(), curve.clone(), @@ -179,13 +184,13 @@ fn can_create_identical_pools() { true )); - assert_eq!(NextAssetId::::get(), 2); + assert_eq!(NextAssetId::::get(), next_asset_id + 2); - let details1 = Pools::::get(calculate_pool_id(&[0])).unwrap(); - let details2 = Pools::::get(calculate_pool_id(&[1])).unwrap(); + let details1 = Pools::::get(calculate_pool_id(&[next_asset_id])).unwrap(); + let details2 = Pools::::get(calculate_pool_id(&[next_asset_id + 1])).unwrap(); - assert_eq!(details1.bonded_currencies, vec![0]); - assert_eq!(details2.bonded_currencies, vec![1]); + assert_eq!(details1.bonded_currencies, vec![next_asset_id]); + assert_eq!(details2.bonded_currencies, vec![next_asset_id + 1]); }); } @@ -208,7 +213,7 @@ fn fails_if_collateral_not_exists() { BondingPallet::create_pool( origin, curve, - DEFAULT_COLLATERAL_CURRENCY_ID, + 100, BoundedVec::truncate_from(vec![bonded_token]), 10, true @@ -223,7 +228,7 @@ fn handles_asset_id_overflow() { let initial_balance = 100_000_000_000_000_000u128; ExtBuilder::default() .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) - .with_collaterals(vec![0]) + .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) .build() .execute_with(|| { NextAssetId::::set(u32::MAX); From cbcc85dfc2995a0ca31876c42bd3adf1bc4fb0c1 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 6 Nov 2024 12:25:54 +0100 Subject: [PATCH 15/18] test: circular pool creation --- .../src/tests/transactions/create_pool.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index e277d8f861..142dcd48d6 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -223,6 +223,38 @@ fn fails_if_collateral_not_exists() { }) } +#[test] +fn cannot_create_circular_pool() { + ExtBuilder::default() + .with_native_balances(vec![(ACCOUNT_00, 100_000_000_000_000_000u128)]) + .build() + .execute_with(|| { + let origin = RawOrigin::Signed(ACCOUNT_00).into(); + let curve = get_linear_bonding_curve_input(); + + let bonded_token = TokenMetaOf:: { + name: BoundedVec::truncate_from(b"Bitcoin".to_vec()), + symbol: BoundedVec::truncate_from(b"btc".to_vec()), + min_balance: 1, + }; + + let next_asset_id = NextAssetId::::get(); + + assert_err!( + BondingPallet::create_pool( + origin, + curve, + // try specifying the id of the currency to be created as collateral + next_asset_id, + BoundedVec::truncate_from(vec![bonded_token]), + 10, + true + ), + AssetsPalletErrors::::Unknown + ); + }) +} + #[test] fn handles_asset_id_overflow() { let initial_balance = 100_000_000_000_000_000u128; From 7c99b445f6cf6915593393c6402dcfc47e9d7b76 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 6 Nov 2024 13:09:23 +0100 Subject: [PATCH 16/18] fix: verify existence of collateral before creating currencies --- pallets/pallet-bonded-coins/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/lib.rs b/pallets/pallet-bonded-coins/src/lib.rs index 3ce9203d66..1ecf49bc0c 100644 --- a/pallets/pallet-bonded-coins/src/lib.rs +++ b/pallets/pallet-bonded-coins/src/lib.rs @@ -289,6 +289,10 @@ pub mod pallet { let pool_account = &pool_id.clone().into(); + // Touch the pool account in order to be able to transfer the collateral + // currency to it. This should also verify that the currency actually exists. + T::CollateralCurrencies::touch(collateral_id.clone(), pool_account, &who)?; + currencies .into_iter() .zip(currency_ids.iter()) @@ -313,10 +317,6 @@ pub mod pallet { Ok(()) })?; - // Touch the pool account in order to be able to transfer the collateral - // currency to it. This should also verify that the currency actually exists. - T::CollateralCurrencies::touch(collateral_id.clone(), pool_account, &who)?; - Pools::::set( &pool_id, Some(PoolDetails::new( From 48108b53a3998ae5b8e6bdb24fa561418428690b Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 6 Nov 2024 13:56:43 +0100 Subject: [PATCH 17/18] refactor: use fungibles trait instead of pallet events --- .../src/tests/transactions/create_pool.rs | 67 +++++++++++-------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index 142dcd48d6..eb442add1d 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -1,6 +1,11 @@ -use frame_support::{assert_err, assert_ok}; +use frame_support::{ + assert_err, assert_ok, + traits::fungibles::{ + metadata::Inspect as InspectMetadata, roles::Inspect as InspectRoles, Inspect as InspectFungibles, + }, +}; use frame_system::{pallet_prelude::OriginFor, RawOrigin}; -use pallet_assets::{Error as AssetsPalletErrors, Event as AssetsPalletEvents}; +use pallet_assets::Error as AssetsPalletErrors; use sp_runtime::{ArithmeticError, BoundedVec}; use sp_std::ops::Sub; @@ -69,34 +74,29 @@ fn single_currency() { System::assert_has_event(BondingPalletEvents::PoolCreated { id: pool_id.clone() }.into()); - // TODO: check events or storage of linked pallets? - System::assert_has_event( - AssetsPalletEvents::ForceCreated { - asset_id: new_asset_id, - owner: pool_id.clone(), - } - .into(), + // Check creation + assert!(::Fungibles::asset_exists(new_asset_id)); + // Check team + assert_eq!( + ::Fungibles::owner(new_asset_id), + Some(pool_id.clone()) ); - - System::assert_has_event( - AssetsPalletEvents::MetadataSet { - asset_id: new_asset_id, - name: b"Bitcoin".into(), - symbol: b"btc".into(), - decimals: 10, - is_frozen: false, - } - .into(), + assert_eq!( + ::Fungibles::admin(new_asset_id), + Some(pool_id.clone()) ); - - System::assert_has_event( - AssetsPalletEvents::Touched { - asset_id: DEFAULT_COLLATERAL_CURRENCY_ID, - who: pool_id.clone(), - depositor: ACCOUNT_00, - } - .into(), + assert_eq!( + ::Fungibles::issuer(new_asset_id), + Some(pool_id.clone()) + ); + assert_eq!( + ::Fungibles::freezer(new_asset_id), + Some(pool_id.clone()) ); + // Check metadata + assert_eq!(::Fungibles::decimals(new_asset_id), 10); + assert_eq!(::Fungibles::name(new_asset_id), b"Bitcoin"); + assert_eq!(::Fungibles::symbol(new_asset_id), b"btc"); }); } @@ -135,7 +135,7 @@ fn multi_currency() { let new_assets = Vec::from_iter(next_asset_id..next_asset_id + 3); let pool_id = calculate_pool_id(&new_assets); - let details = Pools::::get(pool_id).unwrap(); + let details = Pools::::get(pool_id.clone()).unwrap(); assert_eq!(BondingPallet::get_currencies_number(&details), 3); assert_eq!(details.bonded_currencies, new_assets); @@ -144,6 +144,14 @@ fn multi_currency() { Balances::free_balance(ACCOUNT_00), initial_balance.sub(BondingPallet::calculate_pool_deposit(3)) ); + + for new_asset_id in new_assets { + assert!(::Fungibles::asset_exists(new_asset_id)); + assert_eq!( + ::Fungibles::owner(new_asset_id), + Some(pool_id.clone()) + ); + } }); } @@ -191,6 +199,9 @@ fn can_create_identical_pools() { assert_eq!(details1.bonded_currencies, vec![next_asset_id]); assert_eq!(details2.bonded_currencies, vec![next_asset_id + 1]); + + assert!(::Fungibles::asset_exists(next_asset_id)); + assert!(::Fungibles::asset_exists(next_asset_id + 1)); }); } From e458d8cd9aa2fd655b0db4d9921942d66e89af37 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 6 Nov 2024 14:09:55 +0100 Subject: [PATCH 18/18] chore: use mock constants --- pallets/pallet-bonded-coins/src/mock.rs | 3 +- .../src/tests/transactions/create_pool.rs | 33 ++++++++++--------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/pallets/pallet-bonded-coins/src/mock.rs b/pallets/pallet-bonded-coins/src/mock.rs index 31280b097f..df56db37be 100644 --- a/pallets/pallet-bonded-coins/src/mock.rs +++ b/pallets/pallet-bonded-coins/src/mock.rs @@ -42,6 +42,7 @@ pub(crate) const DEFAULT_BONDED_CURRENCY_ID: AssetId = 1; pub(crate) const DEFAULT_COLLATERAL_CURRENCY_ID: AssetId = 0; pub(crate) const DEFAULT_COLLATERAL_DENOMINATION: u8 = 10; pub(crate) const DEFAULT_BONDED_DENOMINATION: u8 = 10; +pub(crate) const ONE_HUNDRED_KILT: u128 = 100_000_000_000_000_000; // helper functions pub fn assert_relative_eq(target: Float, expected: Float, epsilon: Float) { @@ -98,7 +99,7 @@ pub mod runtime { bonded_currencies, state, collateral_id, - denomination: 10, + denomination: DEFAULT_BONDED_DENOMINATION, owner, } } diff --git a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs index eb442add1d..bc1d3adb2e 100644 --- a/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs +++ b/pallets/pallet-bonded-coins/src/tests/transactions/create_pool.rs @@ -15,11 +15,9 @@ use crate::{ Event as BondingPalletEvents, NextAssetId, Pools, TokenMetaOf, }; -// create_pool tests - #[test] fn single_currency() { - let initial_balance = 100_000_000_000_000_000u128; + let initial_balance = ONE_HUNDRED_KILT; ExtBuilder::default() .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) @@ -41,7 +39,7 @@ fn single_currency() { curve, DEFAULT_COLLATERAL_CURRENCY_ID, BoundedVec::truncate_from(vec![bonded_token]), - 10, + DEFAULT_BONDED_DENOMINATION, true )); @@ -60,7 +58,7 @@ fn single_currency() { allow_swap: false }) ); - assert_eq!(details.denomination, 10); + assert_eq!(details.denomination, DEFAULT_BONDED_DENOMINATION); assert_eq!(details.collateral_id, DEFAULT_COLLATERAL_CURRENCY_ID); assert_eq!(details.bonded_currencies, vec![new_asset_id]); @@ -94,7 +92,10 @@ fn single_currency() { Some(pool_id.clone()) ); // Check metadata - assert_eq!(::Fungibles::decimals(new_asset_id), 10); + assert_eq!( + ::Fungibles::decimals(new_asset_id), + DEFAULT_BONDED_DENOMINATION + ); assert_eq!(::Fungibles::name(new_asset_id), b"Bitcoin"); assert_eq!(::Fungibles::symbol(new_asset_id), b"btc"); }); @@ -102,7 +103,7 @@ fn single_currency() { #[test] fn multi_currency() { - let initial_balance = 100_000_000_000_000_000u128; + let initial_balance = ONE_HUNDRED_KILT; ExtBuilder::default() .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) @@ -126,7 +127,7 @@ fn multi_currency() { curve, DEFAULT_COLLATERAL_CURRENCY_ID, BoundedVec::truncate_from(bonded_tokens), - 10, + DEFAULT_BONDED_DENOMINATION, true )); @@ -157,7 +158,7 @@ fn multi_currency() { #[test] fn can_create_identical_pools() { - let initial_balance = 100_000_000_000_000_000u128; + let initial_balance = ONE_HUNDRED_KILT; ExtBuilder::default() .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID]) @@ -179,7 +180,7 @@ fn can_create_identical_pools() { curve.clone(), DEFAULT_COLLATERAL_CURRENCY_ID, BoundedVec::truncate_from(vec![bonded_token.clone()]), - 10, + DEFAULT_BONDED_DENOMINATION, true )); @@ -188,7 +189,7 @@ fn can_create_identical_pools() { curve, DEFAULT_COLLATERAL_CURRENCY_ID, BoundedVec::truncate_from(vec![bonded_token]), - 10, + DEFAULT_BONDED_DENOMINATION, true )); @@ -208,7 +209,7 @@ fn can_create_identical_pools() { #[test] fn fails_if_collateral_not_exists() { ExtBuilder::default() - .with_native_balances(vec![(ACCOUNT_00, 100_000_000_000_000_000u128)]) + .with_native_balances(vec![(ACCOUNT_00, ONE_HUNDRED_KILT)]) .build() .execute_with(|| { let origin = RawOrigin::Signed(ACCOUNT_00).into(); @@ -226,7 +227,7 @@ fn fails_if_collateral_not_exists() { curve, 100, BoundedVec::truncate_from(vec![bonded_token]), - 10, + DEFAULT_BONDED_DENOMINATION, true ), AssetsPalletErrors::::Unknown @@ -237,7 +238,7 @@ fn fails_if_collateral_not_exists() { #[test] fn cannot_create_circular_pool() { ExtBuilder::default() - .with_native_balances(vec![(ACCOUNT_00, 100_000_000_000_000_000u128)]) + .with_native_balances(vec![(ACCOUNT_00, ONE_HUNDRED_KILT)]) .build() .execute_with(|| { let origin = RawOrigin::Signed(ACCOUNT_00).into(); @@ -258,7 +259,7 @@ fn cannot_create_circular_pool() { // try specifying the id of the currency to be created as collateral next_asset_id, BoundedVec::truncate_from(vec![bonded_token]), - 10, + DEFAULT_BONDED_DENOMINATION, true ), AssetsPalletErrors::::Unknown @@ -268,7 +269,7 @@ fn cannot_create_circular_pool() { #[test] fn handles_asset_id_overflow() { - let initial_balance = 100_000_000_000_000_000u128; + let initial_balance = ONE_HUNDRED_KILT; ExtBuilder::default() .with_native_balances(vec![(ACCOUNT_00, initial_balance)]) .with_collaterals(vec![DEFAULT_COLLATERAL_CURRENCY_ID])