diff --git a/pallets/liquidity-pools/src/lib.rs b/pallets/liquidity-pools/src/lib.rs index 7d78d97629..64181d46b9 100644 --- a/pallets/liquidity-pools/src/lib.rs +++ b/pallets/liquidity-pools/src/lib.rs @@ -769,11 +769,6 @@ pub mod pallet { ) -> DispatchResult { let who = ensure_signed(origin.clone())?; - ensure!( - T::PoolInspect::tranche_exists(pool_id, tranche_id), - Error::::TrancheNotFound - ); - let investment_id = Self::derive_invest_id(pool_id, tranche_id)?; let metadata = T::AssetRegistry::metadata(&investment_id.into()) .ok_or(Error::::TrancheMetadataNotFound)?; @@ -923,6 +918,10 @@ pub mod pallet { pub fn validate_investment_currency( currency_id: T::CurrencyId, ) -> Result<(u128, EVMChainId), DispatchError> { + let currency = Self::try_get_general_index(currency_id)?; + + let (chain_id, ..) = Self::try_get_wrapped_token(¤cy_id)?; + // Ensure the currency is enabled as pool_currency let metadata = T::AssetRegistry::metadata(¤cy_id).ok_or(Error::::AssetNotFound)?; @@ -931,10 +930,6 @@ pub mod pallet { Error::::AssetMetadataNotPoolCurrency ); - let currency = Self::try_get_general_index(currency_id)?; - - let (chain_id, ..) = Self::try_get_wrapped_token(¤cy_id)?; - Ok((currency, chain_id)) } diff --git a/pallets/liquidity-pools/src/tests.rs b/pallets/liquidity-pools/src/tests.rs index 2b3d462649..4f0da61ae5 100644 --- a/pallets/liquidity-pools/src/tests.rs +++ b/pallets/liquidity-pools/src/tests.rs @@ -80,6 +80,16 @@ mod util { } } + pub fn pool_locatable_transferable_metadata() -> AssetMetadata { + AssetMetadata { + additional: CustomMetadata { + pool_currency: true, + ..transferable_metadata().additional + }, + ..locatable_transferable_metadata() + } + } + pub fn currency_index(currency_id: CurrencyId) -> u128 { GeneralCurrencyIndexOf::::try_from(currency_id) .unwrap() @@ -623,6 +633,101 @@ mod add_tranche { } } +mod update_tranche_token_metadata { + use super::*; + + #[test] + fn success() { + System::externalities().execute_with(|| { + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, ALICE); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::UpdateTrancheTokenMetadata { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + token_name: vec_to_fixed_array(NAME), + token_symbol: vec_to_fixed_array(SYMBOL), + } + ); + Ok(()) + }); + + assert_ok!(LiquidityPools::update_tranche_token_metadata( + RuntimeOrigin::signed(ALICE), + POOL_ID, + TRANCHE_ID, + EVM_DOMAIN_ADDRESS.domain(), + )); + }) + } + + mod erroring_out { + use super::*; + + #[test] + fn with_wrong_pool() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + Pools::mock_pool_exists(|_| false); + + assert_noop!( + LiquidityPools::update_tranche_token_metadata( + RuntimeOrigin::signed(ALICE), + POOL_ID, + TRANCHE_ID, + EVM_DOMAIN_ADDRESS.domain(), + ), + Error::::PoolNotFound + ); + }) + } + + #[test] + fn with_wrong_tranche() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| false); + + assert_noop!( + LiquidityPools::update_tranche_token_metadata( + RuntimeOrigin::signed(ALICE), + POOL_ID, + TRANCHE_ID, + EVM_DOMAIN_ADDRESS.domain(), + ), + Error::::TrancheNotFound, + ); + }) + } + + #[test] + fn with_no_metadata() { + System::externalities().execute_with(|| { + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + AssetRegistry::mock_metadata(|_| None); + + assert_noop!( + LiquidityPools::update_tranche_token_metadata( + RuntimeOrigin::signed(ALICE), + POOL_ID, + TRANCHE_ID, + EVM_DOMAIN_ADDRESS.domain(), + ), + Error::::TrancheMetadataNotFound, + ); + }) + } + } +} + mod update_token_price { use super::*; @@ -958,6 +1063,376 @@ mod add_currency { } } +mod allow_investment_currency { + use super::*; + + #[test] + fn success() { + System::externalities().execute_with(|| { + AssetRegistry::mock_metadata(|_| Some(util::pool_locatable_transferable_metadata())); + Permissions::mock_has(move |scope, who, role| { + assert_eq!(who, ALICE); + assert!(matches!(scope, PermissionScope::Pool(POOL_ID))); + assert!(matches!(role, Role::PoolRole(PoolRole::PoolAdmin))); + true + }); + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, ALICE); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::AllowInvestmentCurrency { + pool_id: POOL_ID, + currency: util::currency_index(CURRENCY_ID), + } + ); + Ok(()) + }); + + assert_ok!(LiquidityPools::allow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + )); + }) + } + + mod erroring_out { + use super::*; + + #[test] + fn with_wrong_permissions() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| false); + + assert_noop!( + LiquidityPools::allow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::NotPoolAdmin + ); + }) + } + + #[test] + fn with_no_metadata() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| None); + + assert_noop!( + LiquidityPools::allow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::AssetNotFound, + ); + }) + } + + #[test] + fn with_unsupported_token() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + + assert_noop!( + LiquidityPools::allow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CurrencyId::Native + ), + TokenError::Unsupported, + ); + }) + } + + #[test] + fn with_no_transferible_asset() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + + assert_noop!( + LiquidityPools::allow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::AssetNotLiquidityPoolsTransferable, + ); + }) + } + + #[test] + fn with_wrong_location() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| Some(util::transferable_metadata())); + + assert_noop!( + LiquidityPools::allow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::AssetNotLiquidityPoolsWrappedToken + ); + }) + } + + #[test] + fn with_wrong_pool_currency() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| Some(util::locatable_transferable_metadata())); + + assert_noop!( + LiquidityPools::allow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::AssetMetadataNotPoolCurrency + ); + }) + } + } +} + +mod disallow_investment_currency { + use super::*; + + #[test] + fn success() { + System::externalities().execute_with(|| { + AssetRegistry::mock_metadata(|_| Some(util::pool_locatable_transferable_metadata())); + Permissions::mock_has(move |scope, who, role| { + assert_eq!(who, ALICE); + assert!(matches!(scope, PermissionScope::Pool(POOL_ID))); + assert!(matches!(role, Role::PoolRole(PoolRole::PoolAdmin))); + true + }); + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, ALICE); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::DisallowInvestmentCurrency { + pool_id: POOL_ID, + currency: util::currency_index(CURRENCY_ID), + } + ); + Ok(()) + }); + + assert_ok!(LiquidityPools::disallow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + )); + }) + } + + mod erroring_out { + use super::*; + + #[test] + fn with_wrong_permissions() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| false); + + assert_noop!( + LiquidityPools::disallow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::NotPoolAdmin + ); + }) + } + + #[test] + fn with_no_metadata() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| None); + + assert_noop!( + LiquidityPools::disallow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::AssetNotFound, + ); + }) + } + + #[test] + fn with_unsupported_token() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + + assert_noop!( + LiquidityPools::disallow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CurrencyId::Native + ), + TokenError::Unsupported, + ); + }) + } + + #[test] + fn with_no_transferible_asset() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + + assert_noop!( + LiquidityPools::disallow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::AssetNotLiquidityPoolsTransferable, + ); + }) + } + + #[test] + fn with_wrong_location() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| Some(util::transferable_metadata())); + + assert_noop!( + LiquidityPools::disallow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::AssetNotLiquidityPoolsWrappedToken + ); + }) + } + + #[test] + fn with_wrong_pool_currency() { + System::externalities().execute_with(|| { + Permissions::mock_has(move |_, _, _| true); + AssetRegistry::mock_metadata(|_| Some(util::locatable_transferable_metadata())); + + assert_noop!( + LiquidityPools::disallow_investment_currency( + RuntimeOrigin::signed(ALICE), + POOL_ID, + CURRENCY_ID + ), + Error::::AssetMetadataNotPoolCurrency + ); + }) + } + } +} + +mod schedule_upgrade { + use super::*; + + #[test] + fn success() { + System::externalities().execute_with(|| { + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, TreasuryAccount::get()); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::ScheduleUpgrade { + contract: CONTRACT_ACCOUNT + } + ); + Ok(()) + }); + + assert_ok!(LiquidityPools::schedule_upgrade( + RuntimeOrigin::root(), + CHAIN_ID, + CONTRACT_ACCOUNT, + )); + }) + } + + mod erroring_out { + use super::*; + + #[test] + fn with_origin() { + System::externalities().execute_with(|| { + assert_noop!( + LiquidityPools::schedule_upgrade( + RuntimeOrigin::signed(ALICE), + CHAIN_ID, + CONTRACT_ACCOUNT, + ), + DispatchError::BadOrigin + ); + }) + } + } +} + +mod cancel_upgrade { + use super::*; + + #[test] + fn success() { + System::externalities().execute_with(|| { + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, TreasuryAccount::get()); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::CancelUpgrade { + contract: CONTRACT_ACCOUNT + } + ); + Ok(()) + }); + + assert_ok!(LiquidityPools::cancel_upgrade( + RuntimeOrigin::root(), + CHAIN_ID, + CONTRACT_ACCOUNT, + )); + }) + } + + mod erroring_out { + use super::*; + + #[test] + fn with_origin() { + System::externalities().execute_with(|| { + assert_noop!( + LiquidityPools::cancel_upgrade( + RuntimeOrigin::signed(ALICE), + CHAIN_ID, + CONTRACT_ACCOUNT, + ), + DispatchError::BadOrigin + ); + }) + } + } +} + #[test] fn receiving_invalid_message() { System::externalities().execute_with(|| { diff --git a/runtime/integration-tests/src/cases/liquidity_pools.rs b/runtime/integration-tests/src/cases/liquidity_pools.rs index 43ca11a567..5f0c7db3c6 100644 --- a/runtime/integration-tests/src/cases/liquidity_pools.rs +++ b/runtime/integration-tests/src/cases/liquidity_pools.rs @@ -35,7 +35,7 @@ use runtime_common::{ }; use sp_core::{Get, H160}; use sp_runtime::{ - traits::{AccountIdConversion, BadOrigin, Convert, EnsureAdd, One, Zero}, + traits::{AccountIdConversion, Convert, EnsureAdd, One, Zero}, BoundedVec, DispatchError, FixedPointNumber, Perquintill, SaturatedConversion, }; use staging_xcm::{ @@ -50,6 +50,13 @@ use crate::{ utils::{accounts::Keyring, genesis, genesis::Genesis, orml_asset_registry}, }; +// ------------------ +// NOTE +// This file only contains foreign investments tests, but the name must remain +// as it is until feature lpv2 is merged to avoid conflicts: +// (https://github.com/centrifuge/centrifuge-chain/pull/1909) +// ------------------ + /// The AUSD asset id pub const AUSD_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(3); /// The USDT asset id @@ -662,529 +669,6 @@ mod utils { use utils::*; -mod add_allow_upgrade { - use super::*; - - #[test_runtimes([development])] - fn allow_investment_currency() { - let mut env = FudgeEnv::::from_parachain_storage( - Genesis::default() - .add(genesis::balances::(cfg(1_000))) - .add(genesis::tokens::(vec![( - GLMR_CURRENCY_ID, - DEFAULT_BALANCE_GLMR, - )])) - .storage(), - ); - - setup_test(&mut env); - - env.parachain_state_mut(|| { - let currency_id = AUSD_CURRENCY_ID; - let pool_id = POOL_ID; - let evm_chain_id: u64 = MOONBEAM_EVM_CHAIN_ID; - let evm_address = [1u8; 20]; - - // Create an AUSD pool - create_ausd_pool::(pool_id); - - enable_liquidity_pool_transferability::(currency_id); - - // Enable LiquidityPools transferability - assert_ok!(orml_asset_registry::Pallet::::update_asset( - ::RuntimeOrigin::root(), - currency_id, - None, - None, - None, - None, - // Changed: Add location which can be converted to LiquidityPoolsWrappedToken - Some(Some(liquidity_pools_transferable_multilocation::( - evm_chain_id, - evm_address, - ))), - Some(CustomMetadata { - // Changed: Allow liquidity_pools transferability - transferability: CrossChainTransferability::LiquidityPools, - pool_currency: true, - ..Default::default() - }) - )); - - assert_ok!( - pallet_liquidity_pools::Pallet::::allow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ) - ); - - assert_noop!( - pallet_liquidity_pools::Pallet::::allow_investment_currency( - RawOrigin::Signed(Keyring::Charlie.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::NotPoolAdmin - ); - }); - } - - #[test_runtimes([development])] - fn allow_investment_currency_should_fail() { - let mut env = FudgeEnv::::from_parachain_storage( - Genesis::default() - .add(genesis::balances::(cfg(1_000))) - .add(genesis::tokens::(vec![( - GLMR_CURRENCY_ID, - DEFAULT_BALANCE_GLMR, - )])) - .storage(), - ); - - setup_test(&mut env); - - env.parachain_state_mut(|| { - let pool_id = POOL_ID; - let currency_id = CurrencyId::ForeignAsset(42); - let ausd_currency_id = AUSD_CURRENCY_ID; - - // Should fail if pool does not exist - assert_noop!( - pallet_liquidity_pools::Pallet::::allow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::NotPoolAdmin - ); - - // Register currency_id with pool_currency set to true - assert_ok!(orml_asset_registry::Pallet::::register_asset( - ::RuntimeOrigin::root(), - AssetMetadata { - name: BoundedVec::default(), - symbol: BoundedVec::default(), - decimals: 12, - location: None, - existential_deposit: 1_000_000, - additional: CustomMetadata { - pool_currency: true, - ..Default::default() - }, - }, - Some(currency_id) - )); - - // Create pool - create_currency_pool::(pool_id, currency_id, 10_000 * decimals(12)); - - enable_liquidity_pool_transferability::(ausd_currency_id); - - // Should fail if currency is not liquidityPools transferable - assert_ok!(orml_asset_registry::Pallet::::update_asset( - ::RuntimeOrigin::root(), - currency_id, - None, - None, - None, - None, - None, - Some(CustomMetadata { - // Disallow any cross chain transferability - transferability: CrossChainTransferability::None, - // Changed: Allow to be usable as pool currency - pool_currency: true, - ..Default::default() - }), - )); - assert_noop!( - pallet_liquidity_pools::Pallet::::allow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::AssetNotLiquidityPoolsTransferable - ); - - // Should fail if currency does not have any Location in metadata - assert_ok!(orml_asset_registry::Pallet::::update_asset( - ::RuntimeOrigin::root(), - currency_id, - None, - None, - None, - None, - None, - Some(CustomMetadata { - // Changed: Allow liquidityPools transferability - transferability: CrossChainTransferability::LiquidityPools, - // Still allow to be pool currency - pool_currency: true, - ..Default::default() - }), - )); - assert_noop!( - pallet_liquidity_pools::Pallet::::allow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::AssetNotLiquidityPoolsWrappedToken - ); - - // Should fail if currency does not have LiquidityPoolsWrappedToken location in - // metadata - assert_ok!(orml_asset_registry::Pallet::::update_asset( - ::RuntimeOrigin::root(), - currency_id, - None, - None, - None, - None, - // Changed: Add some location which cannot be converted to - // LiquidityPoolsWrappedToken - Some(Some(VersionedLocation::V4(Default::default()))), - // No change for transferability required as it is already allowed for - // LiquidityPools - None, - )); - assert_noop!( - pallet_liquidity_pools::Pallet::::allow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::AssetNotLiquidityPoolsWrappedToken - ); - }); - } - - #[test_runtimes([development])] - fn disallow_investment_currency() { - let mut env = FudgeEnv::::from_parachain_storage( - Genesis::default() - .add(genesis::balances::(cfg(1_000))) - .add(genesis::tokens::(vec![( - GLMR_CURRENCY_ID, - DEFAULT_BALANCE_GLMR, - )])) - .storage(), - ); - - setup_test(&mut env); - - env.parachain_state_mut(|| { - let currency_id = AUSD_CURRENCY_ID; - let pool_id = POOL_ID; - let evm_chain_id: u64 = MOONBEAM_EVM_CHAIN_ID; - let evm_address = [1u8; 20]; - - // Create an AUSD pool - create_ausd_pool::(pool_id); - - enable_liquidity_pool_transferability::(currency_id); - - // Enable LiquidityPools transferability - assert_ok!(orml_asset_registry::Pallet::::update_asset( - ::RuntimeOrigin::root(), - currency_id, - None, - None, - None, - None, - // Changed: Add location which can be converted to LiquidityPoolsWrappedToken - Some(Some(liquidity_pools_transferable_multilocation::( - evm_chain_id, - evm_address, - ))), - Some(CustomMetadata { - // Changed: Allow liquidity_pools transferability - transferability: CrossChainTransferability::LiquidityPools, - pool_currency: true, - ..Default::default() - }) - )); - - assert_ok!( - pallet_liquidity_pools::Pallet::::disallow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ) - ); - - assert_noop!( - pallet_liquidity_pools::Pallet::::disallow_investment_currency( - RawOrigin::Signed(Keyring::Charlie.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::NotPoolAdmin - ); - }); - } - - #[test_runtimes([development])] - fn disallow_investment_currency_should_fail() { - let mut env = FudgeEnv::::from_parachain_storage( - Genesis::default() - .add(genesis::balances::(cfg(1_000))) - .add(genesis::tokens::(vec![( - GLMR_CURRENCY_ID, - DEFAULT_BALANCE_GLMR, - )])) - .storage(), - ); - - setup_test(&mut env); - - env.parachain_state_mut(|| { - let pool_id = POOL_ID; - let currency_id = CurrencyId::ForeignAsset(42); - let ausd_currency_id = AUSD_CURRENCY_ID; - - // Should fail if pool does not exist - assert_noop!( - pallet_liquidity_pools::Pallet::::disallow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::NotPoolAdmin - ); - - // Register currency_id with pool_currency set to true - assert_ok!(orml_asset_registry::Pallet::::register_asset( - ::RuntimeOrigin::root(), - AssetMetadata { - name: BoundedVec::default(), - symbol: BoundedVec::default(), - decimals: 12, - location: None, - existential_deposit: 1_000_000, - additional: CustomMetadata { - pool_currency: true, - ..Default::default() - }, - }, - Some(currency_id) - )); - - // Create pool - create_currency_pool::(pool_id, currency_id, 10_000 * decimals(12)); - - enable_liquidity_pool_transferability::(ausd_currency_id); - - // Should fail if currency is not liquidityPools transferable - assert_ok!(orml_asset_registry::Pallet::::update_asset( - ::RuntimeOrigin::root(), - currency_id, - None, - None, - None, - None, - None, - Some(CustomMetadata { - // Disallow any cross chain transferability - transferability: CrossChainTransferability::None, - // Changed: Allow to be usable as pool currency - pool_currency: true, - ..Default::default() - }), - )); - assert_noop!( - pallet_liquidity_pools::Pallet::::disallow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::AssetNotLiquidityPoolsTransferable - ); - - // Should fail if currency does not have any Location in metadata - assert_ok!(orml_asset_registry::Pallet::::update_asset( - ::RuntimeOrigin::root(), - currency_id, - None, - None, - None, - None, - None, - Some(CustomMetadata { - // Changed: Allow liquidityPools transferability - transferability: CrossChainTransferability::LiquidityPools, - // Still allow to be pool currency - pool_currency: true, - ..Default::default() - }), - )); - assert_noop!( - pallet_liquidity_pools::Pallet::::disallow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::AssetNotLiquidityPoolsWrappedToken - ); - - // Should fail if currency does not have LiquidityPoolsWrappedToken location in - // metadata - assert_ok!(orml_asset_registry::Pallet::::update_asset( - ::RuntimeOrigin::root(), - currency_id, - None, - None, - None, - None, - // Changed: Add some location which cannot be converted to - // LiquidityPoolsWrappedToken - Some(Some(VersionedLocation::V4(Default::default()))), - // No change for transferability required as it is already allowed for - // LiquidityPools - None, - )); - assert_noop!( - pallet_liquidity_pools::Pallet::::disallow_investment_currency( - RawOrigin::Signed(Keyring::Bob.into()).into(), - pool_id, - currency_id, - ), - pallet_liquidity_pools::Error::::AssetNotLiquidityPoolsWrappedToken - ); - }); - } - - #[test_runtimes([development])] - fn schedule_upgrade() { - let mut env = FudgeEnv::::from_parachain_storage( - Genesis::default() - .add(genesis::balances::(cfg(1_000))) - .add(genesis::tokens::(vec![( - GLMR_CURRENCY_ID, - DEFAULT_BALANCE_GLMR, - )])) - .storage(), - ); - - setup_test(&mut env); - - env.parachain_state_mut(|| { - // Only Root can call `schedule_upgrade` - assert_noop!( - pallet_liquidity_pools::Pallet::::schedule_upgrade( - RawOrigin::Signed(Keyring::Bob.into()).into(), - MOONBEAM_EVM_CHAIN_ID, - [7; 20] - ), - BadOrigin - ); - - // Now it finally works - assert_ok!(pallet_liquidity_pools::Pallet::::schedule_upgrade( - ::RuntimeOrigin::root(), - MOONBEAM_EVM_CHAIN_ID, - [7; 20] - )); - }); - } - - #[test_runtimes([development])] - fn cancel_upgrade() { - let mut env = FudgeEnv::::from_parachain_storage( - Genesis::default() - .add(genesis::balances::(cfg(1_000))) - .add(genesis::tokens::(vec![( - GLMR_CURRENCY_ID, - DEFAULT_BALANCE_GLMR, - )])) - .storage(), - ); - - setup_test(&mut env); - - env.parachain_state_mut(|| { - // Only Root can call `cancel_upgrade` - assert_noop!( - pallet_liquidity_pools::Pallet::::cancel_upgrade( - RawOrigin::Signed(Keyring::Bob.into()).into(), - MOONBEAM_EVM_CHAIN_ID, - [7; 20] - ), - BadOrigin - ); - - // Now it finally works - assert_ok!(pallet_liquidity_pools::Pallet::::cancel_upgrade( - ::RuntimeOrigin::root(), - MOONBEAM_EVM_CHAIN_ID, - [7; 20] - )); - }); - } - - #[test_runtimes([development])] - fn update_tranche_token_metadata() { - let mut env = FudgeEnv::::from_parachain_storage( - Genesis::default() - .add(genesis::balances::(cfg(1_000))) - .add(genesis::tokens::(vec![( - GLMR_CURRENCY_ID, - DEFAULT_BALANCE_GLMR, - )])) - .storage(), - ); - - setup_test(&mut env); - - env.parachain_state_mut(|| { - let pool_id = POOL_ID; - // NOTE: Default pool admin is BOB - create_ausd_pool::(pool_id); - - // Missing tranche token should throw - let nonexistent_tranche = [71u8; 16]; - - assert_noop!( - pallet_liquidity_pools::Pallet::::update_tranche_token_metadata( - RawOrigin::Signed(Keyring::Alice.into()).into(), - pool_id, - nonexistent_tranche, - Domain::EVM(MOONBEAM_EVM_CHAIN_ID), - ), - pallet_liquidity_pools::Error::::TrancheNotFound - ); - - let tranche_id = default_tranche_id::(pool_id); - - // Moving the update to another domain can be called by anyone - assert_ok!( - pallet_liquidity_pools::Pallet::::update_tranche_token_metadata( - RawOrigin::Signed(Keyring::Alice.into()).into(), - pool_id, - tranche_id, - Domain::EVM(MOONBEAM_EVM_CHAIN_ID), - ) - ); - - // Edge case: Should throw if tranche exists but metadata does not exist - let tranche_currency_id = CurrencyId::Tranche(pool_id, tranche_id); - - orml_asset_registry::Metadata::::remove(tranche_currency_id); - - assert_noop!( - pallet_liquidity_pools::Pallet::::update_tranche_token_metadata( - RawOrigin::Signed(POOL_ADMIN.into()).into(), - pool_id, - tranche_id, - Domain::EVM(MOONBEAM_EVM_CHAIN_ID), - ), - pallet_liquidity_pools::Error::::TrancheMetadataNotFound - ); - }); - } -} - mod foreign_investments { use super::*;