From 1193c552f1bd4d131a42ba8a7f47698d7dc65bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Wed, 24 Jul 2024 12:41:54 +0200 Subject: [PATCH] LP: Unitary testing for inbound messages (#1927) * tests inbound messages * some cleanings * some adjustements --- pallets/liquidity-pools/src/mock.rs | 99 ++- pallets/liquidity-pools/src/tests.rs | 432 ++++------ pallets/liquidity-pools/src/tests/inbound.rs | 792 +++++++++++++++++++ 3 files changed, 1055 insertions(+), 268 deletions(-) create mode 100644 pallets/liquidity-pools/src/tests/inbound.rs diff --git a/pallets/liquidity-pools/src/mock.rs b/pallets/liquidity-pools/src/mock.rs index 3d120e2e53..f194bd2445 100644 --- a/pallets/liquidity-pools/src/mock.rs +++ b/pallets/liquidity-pools/src/mock.rs @@ -1,20 +1,54 @@ use cfg_primitives::{PoolId, TrancheId}; -use cfg_traits::Millis; +use cfg_traits::{Millis, Seconds}; use cfg_types::{ domain_address::{Domain, DomainAddress}, permissions::PermissionScope, - tokens::{AssetStringLimit, CurrencyId, CustomMetadata, TrancheCurrency}, + tokens::{ + AssetMetadata, AssetStringLimit, CrossChainTransferability, CurrencyId, CustomMetadata, + LocalAssetId, TrancheCurrency, + }, }; -use frame_support::derive_impl; +use frame_support::{derive_impl, traits::PalletInfo as _}; use orml_traits::parameter_type_with_key; use sp_runtime::{traits::IdentityLookup, AccountId32, DispatchResult, FixedU128}; +use staging_xcm::{ + v4::{Junction::*, Location, NetworkId}, + VersionedLocation, +}; -use crate::pallet as pallet_liquidity_pools; +use crate::{pallet as pallet_liquidity_pools, GeneralCurrencyIndexOf}; pub type Balance = u128; pub type AccountId = AccountId32; pub type Ratio = FixedU128; +pub const CHAIN_ID: u64 = 1; +pub const ALICE_32: [u8; 32] = [2; 32]; +pub const ALICE: AccountId = AccountId::new(ALICE_32); +pub const ALICE_ETH: [u8; 20] = [2; 20]; +pub const ALICE_EVM_DOMAIN_ADDRESS: DomainAddress = DomainAddress::EVM(42, ALICE_ETH); +pub const CENTRIFUGE_DOMAIN_ADDRESS: DomainAddress = DomainAddress::Centrifuge(ALICE_32); +pub const CONTRACT_ACCOUNT: [u8; 20] = [1; 20]; +pub const CONTRACT_ACCOUNT_ID: AccountId = AccountId::new([1; 32]); +pub const EVM_DOMAIN_ADDRESS: DomainAddress = DomainAddress::EVM(CHAIN_ID, CONTRACT_ACCOUNT); +pub const AMOUNT: Balance = 100; +pub const CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(1); +pub const POOL_CURRENCY_ID: CurrencyId = CurrencyId::LocalAsset(LocalAssetId(1)); +pub const POOL_ID: PoolId = 1; +pub const TRANCHE_ID: TrancheId = [1; 16]; +pub const NOW: Millis = 10000; +pub const NOW_SECS: Seconds = 10; +pub const NAME: &[u8] = b"Token name"; +pub const SYMBOL: &[u8] = b"Token symbol"; +pub const DECIMALS: u8 = 6; +pub const TRANCHE_CURRENCY: CurrencyId = CurrencyId::Tranche(POOL_ID, TRANCHE_ID); +pub const TRANCHE_TOKEN_PRICE: Ratio = Ratio::from_rational(10, 1); +pub const MARKET_RATIO: Ratio = Ratio::from_rational(2, 1); +pub const INVESTMENT_ID: TrancheCurrency = TrancheCurrency { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, +}; + frame_support::construct_runtime!( pub enum Runtime { System: frame_system, @@ -149,3 +183,60 @@ impl pallet_liquidity_pools::Config for Runtime { type TreasuryAccount = TreasuryAccount; type WeightInfo = (); } + +pub mod util { + use super::*; + + pub fn default_metadata() -> AssetMetadata { + AssetMetadata { + decimals: DECIMALS as u32, + name: Vec::from(NAME).try_into().unwrap(), + symbol: Vec::from(SYMBOL).try_into().unwrap(), + ..cfg_types::tokens::default_metadata() + } + } + + pub fn transferable_metadata() -> AssetMetadata { + AssetMetadata { + additional: CustomMetadata { + transferability: CrossChainTransferability::LiquidityPools, + ..Default::default() + }, + ..default_metadata() + } + } + + pub fn locatable_transferable_metadata() -> AssetMetadata { + let pallet_index = PalletInfo::index::(); + AssetMetadata { + location: Some(VersionedLocation::V4(Location::new( + 0, + [ + PalletInstance(pallet_index.unwrap() as u8), + GlobalConsensus(NetworkId::Ethereum { chain_id: CHAIN_ID }), + AccountKey20 { + network: None, + key: CONTRACT_ACCOUNT, + }, + ], + ))), + ..transferable_metadata() + } + } + + 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() + .index + } +} diff --git a/pallets/liquidity-pools/src/tests.rs b/pallets/liquidity-pools/src/tests.rs index 4f0da61ae5..f0f3a582cb 100644 --- a/pallets/liquidity-pools/src/tests.rs +++ b/pallets/liquidity-pools/src/tests.rs @@ -1,101 +1,19 @@ -use cfg_primitives::{PoolId, TrancheId}; -use cfg_traits::{liquidity_pools::InboundQueue, Millis, Seconds}; +use cfg_traits::Seconds; use cfg_types::{ domain_address::DomainAddress, permissions::{PermissionScope, PoolRole, Role}, - tokens::{AssetMetadata, CrossChainTransferability, CurrencyId, CustomMetadata, LocalAssetId}, + tokens::CurrencyId, }; use cfg_utils::vec_to_fixed_array; use frame_support::{ assert_noop, assert_ok, - traits::{ - fungibles::{Inspect as _, Mutate as _}, - PalletInfo as _, - }, + traits::fungibles::{Inspect as _, Mutate as _}, }; use sp_runtime::{traits::Saturating, DispatchError, TokenError}; -use staging_xcm::{ - v4::{Junction::*, Location, NetworkId}, - VersionedLocation, -}; - -use crate::{mock::*, Error, GeneralCurrencyIndexOf, Message}; - -const CHAIN_ID: u64 = 1; -const ALICE: AccountId = AccountId::new([0; 32]); -const CONTRACT_ACCOUNT: [u8; 20] = [1; 20]; -const CONTRACT_ACCOUNT_ID: AccountId = AccountId::new([1; 32]); -const EVM_DOMAIN_ADDRESS: DomainAddress = DomainAddress::EVM(CHAIN_ID, CONTRACT_ACCOUNT); -const AMOUNT: Balance = 100; -const CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(1); -const POOL_CURRENCY_ID: CurrencyId = CurrencyId::LocalAsset(LocalAssetId(1)); -const POOL_ID: PoolId = 1; -const TRANCHE_ID: TrancheId = [1; 16]; -const NOW: Millis = 10000; -const NOW_SECS: Seconds = 10; -const NAME: &[u8] = b"Token name"; -const SYMBOL: &[u8] = b"Token symbol"; -const DECIMALS: u8 = 6; -const TRANCHE_CURRENCY: CurrencyId = CurrencyId::Tranche(POOL_ID, TRANCHE_ID); -const TRANCHE_TOKEN_PRICE: Ratio = Ratio::from_rational(10, 1); -const MARKET_RATIO: Ratio = Ratio::from_rational(2, 1); - -mod util { - use super::*; - - pub fn default_metadata() -> AssetMetadata { - AssetMetadata { - decimals: DECIMALS as u32, - name: Vec::from(NAME).try_into().unwrap(), - symbol: Vec::from(SYMBOL).try_into().unwrap(), - ..cfg_types::tokens::default_metadata() - } - } - - pub fn transferable_metadata() -> AssetMetadata { - AssetMetadata { - additional: CustomMetadata { - transferability: CrossChainTransferability::LiquidityPools, - ..Default::default() - }, - ..default_metadata() - } - } - - pub fn locatable_transferable_metadata() -> AssetMetadata { - let pallet_index = PalletInfo::index::(); - AssetMetadata { - location: Some(VersionedLocation::V4(Location::new( - 0, - [ - PalletInstance(pallet_index.unwrap() as u8), - GlobalConsensus(NetworkId::Ethereum { chain_id: CHAIN_ID }), - AccountKey20 { - network: None, - key: CONTRACT_ACCOUNT, - }, - ], - ))), - ..transferable_metadata() - } - } - pub fn pool_locatable_transferable_metadata() -> AssetMetadata { - AssetMetadata { - additional: CustomMetadata { - pool_currency: true, - ..transferable_metadata().additional - }, - ..locatable_transferable_metadata() - } - } +use crate::{mock::*, Error, Message}; - pub fn currency_index(currency_id: CurrencyId) -> u128 { - GeneralCurrencyIndexOf::::try_from(currency_id) - .unwrap() - .index - } -} +mod inbound; mod transfer { use super::*; @@ -105,7 +23,6 @@ mod transfer { System::externalities().execute_with(|| { AssetRegistry::mock_metadata(|_| Some(util::locatable_transferable_metadata())); TransferFilter::mock_check(|_| Ok(())); - Tokens::mint_into(CURRENCY_ID, &ALICE, AMOUNT).unwrap(); Gateway::mock_submit(|sender, destination, msg| { assert_eq!(sender, ALICE); assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); @@ -121,6 +38,8 @@ mod transfer { Ok(()) }); + Tokens::mint_into(CURRENCY_ID, &ALICE, AMOUNT).unwrap(); + assert_ok!(LiquidityPools::transfer( RuntimeOrigin::signed(ALICE), CurrencyId::ForeignAsset(1), @@ -291,40 +210,45 @@ mod transfer { mod transfer_tranche_tokens { use super::*; + fn config_mocks() { + DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); + Time::mock_now(|| NOW); + Permissions::mock_has(move |scope, who, role| { + assert_eq!(who, CONTRACT_ACCOUNT_ID); + assert!(matches!(scope, PermissionScope::Pool(POOL_ID))); + assert!(matches!( + role, + Role::PoolRole(PoolRole::TrancheInvestor(TRANCHE_ID, NOW_SECS)) + )); + true + }); + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + TransferFilter::mock_check(|_| Ok(())); + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, ALICE); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: ALICE.into(), + domain: EVM_DOMAIN_ADDRESS.domain().into(), + receiver: EVM_DOMAIN_ADDRESS.address(), + amount: AMOUNT + } + ); + Ok(()) + }); + } + #[test] fn success() { System::externalities().execute_with(|| { - DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); - Time::mock_now(|| NOW); - Permissions::mock_has(move |scope, who, role| { - assert_eq!(who, CONTRACT_ACCOUNT_ID); - assert!(matches!(scope, PermissionScope::Pool(POOL_ID))); - assert!(matches!( - role, - Role::PoolRole(PoolRole::TrancheInvestor(TRANCHE_ID, NOW_SECS)) - )); - true - }); - Pools::mock_pool_exists(|_| true); - Pools::mock_tranche_exists(|_, _| true); - TransferFilter::mock_check(|_| Ok(())); + config_mocks(); + Tokens::mint_into(TRANCHE_CURRENCY, &ALICE, AMOUNT).unwrap(); - Gateway::mock_submit(|sender, destination, msg| { - assert_eq!(sender, ALICE); - assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); - assert_eq!( - msg, - Message::TransferTrancheTokens { - pool_id: POOL_ID, - tranche_id: TRANCHE_ID, - sender: ALICE.into(), - domain: EVM_DOMAIN_ADDRESS.domain().into(), - receiver: EVM_DOMAIN_ADDRESS.address(), - amount: AMOUNT - } - ); - Ok(()) - }); assert_ok!(LiquidityPools::transfer_tranche_tokens( RuntimeOrigin::signed(ALICE), @@ -362,8 +286,7 @@ mod transfer_tranche_tokens { #[test] fn with_wrong_permissions() { System::externalities().execute_with(|| { - DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); - Time::mock_now(|| NOW); + config_mocks(); Permissions::mock_has(|_, _, _| false); assert_noop!( @@ -382,9 +305,7 @@ mod transfer_tranche_tokens { #[test] fn with_wrong_pool() { System::externalities().execute_with(|| { - DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); - Time::mock_now(|| NOW); - Permissions::mock_has(move |_, _, _| true); + config_mocks(); Pools::mock_pool_exists(|_| false); assert_noop!( @@ -403,10 +324,7 @@ mod transfer_tranche_tokens { #[test] fn with_wrong_tranche() { System::externalities().execute_with(|| { - DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); - Time::mock_now(|| NOW); - Permissions::mock_has(move |_, _, _| true); - Pools::mock_pool_exists(|_| true); + config_mocks(); Pools::mock_tranche_exists(|_, _| false); assert_noop!( @@ -425,11 +343,7 @@ mod transfer_tranche_tokens { #[test] fn without_satisfy_filter() { System::externalities().execute_with(|| { - DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); - Time::mock_now(|| NOW); - Permissions::mock_has(move |_, _, _| true); - Pools::mock_pool_exists(|_| true); - Pools::mock_tranche_exists(|_, _| true); + config_mocks(); TransferFilter::mock_check(|_| Err(DispatchError::Other("Err"))); assert_noop!( @@ -516,34 +430,38 @@ mod add_pool { mod add_tranche { use super::*; + fn config_mocks() { + 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 + }); + 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::AddTranche { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + token_name: vec_to_fixed_array(NAME), + token_symbol: vec_to_fixed_array(SYMBOL), + decimals: DECIMALS, + restriction_set: 1 + } + ); + Ok(()) + }); + } + #[test] fn success() { System::externalities().execute_with(|| { - 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 - }); - 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::AddTranche { - pool_id: POOL_ID, - tranche_id: TRANCHE_ID, - token_name: vec_to_fixed_array(NAME), - token_symbol: vec_to_fixed_array(SYMBOL), - decimals: DECIMALS, - restriction_set: 1 - } - ); - Ok(()) - }); + config_mocks(); assert_ok!(LiquidityPools::add_tranche( RuntimeOrigin::signed(ALICE), @@ -577,7 +495,7 @@ mod add_tranche { #[test] fn with_wrong_pool() { System::externalities().execute_with(|| { - Permissions::mock_has(move |_, _, _| true); + config_mocks(); Pools::mock_pool_exists(|_| false); assert_noop!( @@ -595,8 +513,7 @@ mod add_tranche { #[test] fn with_wrong_tranche() { System::externalities().execute_with(|| { - Permissions::mock_has(move |_, _, _| true); - Pools::mock_pool_exists(|_| true); + config_mocks(); Pools::mock_tranche_exists(|_, _| false); assert_noop!( @@ -614,9 +531,7 @@ mod add_tranche { #[test] fn with_no_metadata() { System::externalities().execute_with(|| { - Permissions::mock_has(move |_, _, _| true); - Pools::mock_pool_exists(|_| true); - Pools::mock_tranche_exists(|_, _| true); + config_mocks(); AssetRegistry::mock_metadata(|_| None); assert_noop!( @@ -636,27 +551,30 @@ mod add_tranche { mod update_tranche_token_metadata { use super::*; + fn config_mocks() { + 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(()) + }); + } + #[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(()) - }); + config_mocks(); assert_ok!(LiquidityPools::update_tranche_token_metadata( RuntimeOrigin::signed(ALICE), @@ -673,7 +591,7 @@ mod update_tranche_token_metadata { #[test] fn with_wrong_pool() { System::externalities().execute_with(|| { - Permissions::mock_has(move |_, _, _| true); + config_mocks(); Pools::mock_pool_exists(|_| false); assert_noop!( @@ -691,8 +609,7 @@ mod update_tranche_token_metadata { #[test] fn with_wrong_tranche() { System::externalities().execute_with(|| { - Permissions::mock_has(move |_, _, _| true); - Pools::mock_pool_exists(|_| true); + config_mocks(); Pools::mock_tranche_exists(|_, _| false); assert_noop!( @@ -710,8 +627,7 @@ mod update_tranche_token_metadata { #[test] fn with_no_metadata() { System::externalities().execute_with(|| { - Pools::mock_pool_exists(|_| true); - Pools::mock_tranche_exists(|_, _| true); + config_mocks(); AssetRegistry::mock_metadata(|_| None); assert_noop!( @@ -731,34 +647,38 @@ mod update_tranche_token_metadata { mod update_token_price { use super::*; + fn config_mocks() { + Pools::mock_get_price(|_, _| Some((TRANCHE_TOKEN_PRICE, 1234))); + Pools::mock_currency_for(|_| Some(POOL_CURRENCY_ID)); + MarketRatio::mock_market_ratio(|target, origin| { + assert_eq!(target, CURRENCY_ID); + assert_eq!(origin, POOL_CURRENCY_ID); + Ok(MARKET_RATIO) + }); + AssetRegistry::mock_metadata(|_| Some(util::locatable_transferable_metadata())); + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, ALICE); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::UpdateTrancheTokenPrice { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + currency: util::currency_index(CURRENCY_ID), + price: TRANCHE_TOKEN_PRICE + .saturating_mul(MARKET_RATIO) + .into_inner(), + computed_at: 1234 + } + ); + Ok(()) + }); + } + #[test] fn success() { System::externalities().execute_with(|| { - Pools::mock_get_price(|_, _| Some((TRANCHE_TOKEN_PRICE, 1234))); - Pools::mock_currency_for(|_| Some(POOL_CURRENCY_ID)); - MarketRatio::mock_market_ratio(|target, origin| { - assert_eq!(target, CURRENCY_ID); - assert_eq!(origin, POOL_CURRENCY_ID); - Ok(MARKET_RATIO) - }); - AssetRegistry::mock_metadata(|_| Some(util::locatable_transferable_metadata())); - Gateway::mock_submit(|sender, destination, msg| { - assert_eq!(sender, ALICE); - assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); - assert_eq!( - msg, - Message::UpdateTrancheTokenPrice { - pool_id: POOL_ID, - tranche_id: TRANCHE_ID, - currency: util::currency_index(CURRENCY_ID), - price: TRANCHE_TOKEN_PRICE - .saturating_mul(MARKET_RATIO) - .into_inner(), - computed_at: 1234 - } - ); - Ok(()) - }); + config_mocks(); assert_ok!(LiquidityPools::update_token_price( RuntimeOrigin::signed(ALICE), @@ -794,7 +714,7 @@ mod update_token_price { #[test] fn with_wrong_pool() { System::externalities().execute_with(|| { - Pools::mock_get_price(|_, _| Some((TRANCHE_TOKEN_PRICE, 1234))); + config_mocks(); Pools::mock_currency_for(|_| None); assert_noop!( @@ -813,8 +733,7 @@ mod update_token_price { #[test] fn with_no_market_ratio() { System::externalities().execute_with(|| { - Pools::mock_get_price(|_, _| Some((TRANCHE_TOKEN_PRICE, 1234))); - Pools::mock_currency_for(|_| Some(POOL_CURRENCY_ID)); + config_mocks(); MarketRatio::mock_market_ratio(|_, _| Err(DispatchError::Other(""))); assert_noop!( @@ -833,9 +752,7 @@ mod update_token_price { #[test] fn with_no_transferible_asset() { System::externalities().execute_with(|| { - Pools::mock_get_price(|_, _| Some((TRANCHE_TOKEN_PRICE, 1234))); - Pools::mock_currency_for(|_| Some(POOL_CURRENCY_ID)); - MarketRatio::mock_market_ratio(|_, _| Ok(MARKET_RATIO)); + config_mocks(); AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); assert_noop!( @@ -858,36 +775,40 @@ mod update_member { const VALID_UNTIL_SECS: Seconds = NOW_SECS + 1; + fn config_mocks() { + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + Time::mock_now(|| NOW); + DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); + Permissions::mock_has(move |scope, who, role| { + assert_eq!(who, CONTRACT_ACCOUNT_ID); + assert!(matches!(scope, PermissionScope::Pool(POOL_ID))); + assert!(matches!( + role, + Role::PoolRole(PoolRole::TrancheInvestor(TRANCHE_ID, VALID_UNTIL_SECS)) + )); + true + }); + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, ALICE); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::UpdateMember { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + valid_until: VALID_UNTIL_SECS, + member: EVM_DOMAIN_ADDRESS.address(), + } + ); + Ok(()) + }); + } + #[test] fn success() { System::externalities().execute_with(|| { - Pools::mock_pool_exists(|_| true); - Pools::mock_tranche_exists(|_, _| true); - Time::mock_now(|| NOW); - DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); - Permissions::mock_has(move |scope, who, role| { - assert_eq!(who, CONTRACT_ACCOUNT_ID); - assert!(matches!(scope, PermissionScope::Pool(POOL_ID))); - assert!(matches!( - role, - Role::PoolRole(PoolRole::TrancheInvestor(TRANCHE_ID, VALID_UNTIL_SECS)) - )); - true - }); - Gateway::mock_submit(|sender, destination, msg| { - assert_eq!(sender, ALICE); - assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); - assert_eq!( - msg, - Message::UpdateMember { - pool_id: POOL_ID, - tranche_id: TRANCHE_ID, - valid_until: VALID_UNTIL_SECS, - member: EVM_DOMAIN_ADDRESS.address(), - } - ); - Ok(()) - }); + config_mocks(); assert_ok!(LiquidityPools::update_member( RuntimeOrigin::signed(ALICE), @@ -923,7 +844,7 @@ mod update_member { #[test] fn with_wrong_tranche() { System::externalities().execute_with(|| { - Pools::mock_pool_exists(|_| true); + config_mocks(); Pools::mock_tranche_exists(|_, _| false); assert_noop!( @@ -942,8 +863,7 @@ mod update_member { #[test] fn with_wrong_time() { System::externalities().execute_with(|| { - Pools::mock_pool_exists(|_| true); - Pools::mock_tranche_exists(|_, _| true); + config_mocks(); Time::mock_now(|| VALID_UNTIL_SECS * 1000); assert_noop!( @@ -962,10 +882,7 @@ mod update_member { #[test] fn with_wrong_permissions() { System::externalities().execute_with(|| { - Pools::mock_pool_exists(|_| true); - Pools::mock_tranche_exists(|_, _| true); - Time::mock_now(|| NOW); - DomainAddressToAccountId::mock_convert(|_| CONTRACT_ACCOUNT_ID); + config_mocks(); Permissions::mock_has(|_, _, _| false); assert_noop!( @@ -1432,16 +1349,3 @@ mod cancel_upgrade { } } } - -#[test] -fn receiving_invalid_message() { - System::externalities().execute_with(|| { - // Add pool is an outbound message, not valid to be received - let msg = Message::AddPool { pool_id: 123 }; - - assert_noop!( - LiquidityPools::submit(EVM_DOMAIN_ADDRESS, msg), - Error::::InvalidIncomingMessage, - ); - }) -} diff --git a/pallets/liquidity-pools/src/tests/inbound.rs b/pallets/liquidity-pools/src/tests/inbound.rs new file mode 100644 index 0000000000..3c9b876d43 --- /dev/null +++ b/pallets/liquidity-pools/src/tests/inbound.rs @@ -0,0 +1,792 @@ +use cfg_traits::liquidity_pools::InboundQueue; +use cfg_types::{ + domain_address::DomainAddress, + permissions::{PermissionScope, PoolRole, Role}, +}; +use frame_support::{ + assert_noop, assert_ok, + traits::fungibles::{Inspect as _, Mutate as _}, +}; + +use crate::{mock::*, Error, Message}; + +#[test] +fn receiving_invalid_message() { + System::externalities().execute_with(|| { + // Add pool is an outbound message, not valid to be received + let msg = Message::AddPool { pool_id: 123 }; + + assert_noop!( + LiquidityPools::submit(EVM_DOMAIN_ADDRESS, msg), + Error::::InvalidIncomingMessage, + ); + }) +} + +mod handle_transfer { + use super::*; + + #[test] + fn success() { + System::externalities().execute_with(|| { + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + + assert_ok!(LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::Transfer { + currency: util::currency_index(CURRENCY_ID), + sender: EVM_DOMAIN_ADDRESS.address(), + receiver: ALICE.into(), + amount: AMOUNT, + }, + )); + + assert_eq!(Tokens::balance(CURRENCY_ID, &ALICE.into()), AMOUNT); + }); + } + + mod erroring_out { + use super::*; + + #[test] + fn with_zero_balance() { + System::externalities().execute_with(|| { + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::Transfer { + currency: util::currency_index(CURRENCY_ID), + sender: EVM_DOMAIN_ADDRESS.address(), + receiver: ALICE.into(), + amount: 0, + }, + ), + Error::::InvalidTransferAmount + ); + }) + } + + #[test] + fn with_no_metadata() { + System::externalities().execute_with(|| { + AssetRegistry::mock_metadata(|_| None); + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::Transfer { + currency: util::currency_index(CURRENCY_ID), + sender: EVM_DOMAIN_ADDRESS.address(), + receiver: ALICE.into(), + amount: AMOUNT, + }, + ), + Error::::AssetNotFound, + ); + }) + } + } +} + +mod handle_tranche_tokens_transfer { + use super::*; + + fn config_mocks(receiver: DomainAddress) { + DomainAccountToDomainAddress::mock_convert(move |_| receiver.clone()); + DomainAddressToAccountId::mock_convert(move |_| ALICE); + Time::mock_now(|| NOW); + Permissions::mock_has(move |scope, who, role| { + assert_eq!(who, ALICE); + assert!(matches!(scope, PermissionScope::Pool(POOL_ID))); + assert!(matches!( + role, + Role::PoolRole(PoolRole::TrancheInvestor(TRANCHE_ID, NOW_SECS)) + )); + true + }); + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + } + + #[test] + fn success_with_centrifuge_domain() { + System::externalities().execute_with(|| { + config_mocks(CENTRIFUGE_DOMAIN_ADDRESS); + + Tokens::mint_into( + TRANCHE_CURRENCY, + &EVM_DOMAIN_ADDRESS.domain().into_account(), + AMOUNT, + ) + .unwrap(); + + assert_ok!(LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: EVM_DOMAIN_ADDRESS.address(), + domain: CENTRIFUGE_DOMAIN_ADDRESS.domain().into(), + receiver: ALICE.into(), + amount: AMOUNT + } + )); + + let origin = EVM_DOMAIN_ADDRESS.domain().into_account(); + assert_eq!(Tokens::balance(TRANCHE_CURRENCY, &origin), 0); + assert_eq!(Tokens::balance(TRANCHE_CURRENCY, &ALICE.into()), AMOUNT); + }); + } + + #[test] + fn success_with_evm_domain() { + System::externalities().execute_with(|| { + config_mocks(ALICE_EVM_DOMAIN_ADDRESS); + + TransferFilter::mock_check(|_| Ok(())); + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, ALICE); + assert_eq!(destination, ALICE_EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: ALICE.into(), + domain: ALICE_EVM_DOMAIN_ADDRESS.domain().into(), + receiver: ALICE_EVM_DOMAIN_ADDRESS.address().into(), + amount: AMOUNT + } + ); + Ok(()) + }); + + Tokens::mint_into( + TRANCHE_CURRENCY, + &EVM_DOMAIN_ADDRESS.domain().into_account(), + AMOUNT, + ) + .unwrap(); + + assert_ok!(LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: EVM_DOMAIN_ADDRESS.address(), + domain: ALICE_EVM_DOMAIN_ADDRESS.domain().into(), + receiver: ALICE.into(), + amount: AMOUNT + } + )); + + let origin = EVM_DOMAIN_ADDRESS.domain().into_account(); + assert_eq!(Tokens::balance(TRANCHE_CURRENCY, &origin), 0); + + let destination = ALICE_EVM_DOMAIN_ADDRESS.domain().into_account(); + assert_eq!(Tokens::balance(TRANCHE_CURRENCY, &destination), AMOUNT); + }); + } + + mod erroring_out { + use super::*; + + #[test] + fn with_zero_balance() { + System::externalities().execute_with(|| { + config_mocks(CENTRIFUGE_DOMAIN_ADDRESS); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: EVM_DOMAIN_ADDRESS.address(), + domain: CENTRIFUGE_DOMAIN_ADDRESS.domain().into(), + receiver: ALICE.into(), + amount: 0, + } + ), + Error::::InvalidTransferAmount, + ); + }) + } + + #[test] + fn with_wrong_permissions() { + System::externalities().execute_with(|| { + config_mocks(CENTRIFUGE_DOMAIN_ADDRESS); + Permissions::mock_has(|_, _, _| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: EVM_DOMAIN_ADDRESS.address(), + domain: CENTRIFUGE_DOMAIN_ADDRESS.domain().into(), + receiver: ALICE.into(), + amount: AMOUNT, + } + ), + Error::::UnauthorizedTransfer, + ); + }) + } + + #[test] + fn with_wrong_pool() { + System::externalities().execute_with(|| { + config_mocks(CENTRIFUGE_DOMAIN_ADDRESS); + Pools::mock_pool_exists(|_| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: EVM_DOMAIN_ADDRESS.address(), + domain: CENTRIFUGE_DOMAIN_ADDRESS.domain().into(), + receiver: ALICE.into(), + amount: AMOUNT, + } + ), + Error::::PoolNotFound, + ); + }) + } + + #[test] + fn with_wrong_tranche() { + System::externalities().execute_with(|| { + config_mocks(CENTRIFUGE_DOMAIN_ADDRESS); + Pools::mock_tranche_exists(|_, _| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: EVM_DOMAIN_ADDRESS.address(), + domain: CENTRIFUGE_DOMAIN_ADDRESS.domain().into(), + receiver: ALICE.into(), + amount: AMOUNT, + } + ), + Error::::TrancheNotFound, + ); + }) + } + + #[test] + fn without_sufficient_balance() { + System::externalities().execute_with(|| { + config_mocks(CENTRIFUGE_DOMAIN_ADDRESS); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::TransferTrancheTokens { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + sender: EVM_DOMAIN_ADDRESS.address(), + domain: CENTRIFUGE_DOMAIN_ADDRESS.domain().into(), + receiver: ALICE.into(), + amount: AMOUNT, + } + ), + orml_tokens::Error::::BalanceTooLow + ); + }) + } + } +} + +mod handle_increase_invest_order { + use super::*; + + fn config_mocks() { + DomainAccountToDomainAddress::mock_convert(|_| CENTRIFUGE_DOMAIN_ADDRESS); + DomainAddressToAccountId::mock_convert(|_| ALICE); + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + ForeignInvestment::mock_increase_foreign_investment( + |who, investment_id, amount, foreign_currency| { + assert_eq!(*who, ALICE); + assert_eq!(investment_id, INVESTMENT_ID); + assert_eq!(amount, AMOUNT); + assert_eq!(foreign_currency, CURRENCY_ID); + Ok(()) + }, + ); + } + + #[test] + fn success() { + System::externalities().execute_with(|| { + config_mocks(); + + assert_ok!(LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseInvestOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + )); + }); + } + + mod erroring_out { + use super::*; + + #[test] + fn with_wrong_pool() { + System::externalities().execute_with(|| { + config_mocks(); + Pools::mock_pool_exists(|_| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseInvestOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + ), + Error::::PoolNotFound, + ); + }) + } + + #[test] + fn with_wrong_tranche() { + System::externalities().execute_with(|| { + config_mocks(); + Pools::mock_tranche_exists(|_, _| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseInvestOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + ), + Error::::TrancheNotFound, + ); + }) + } + + #[test] + fn with_no_metadata() { + System::externalities().execute_with(|| { + config_mocks(); + AssetRegistry::mock_metadata(|_| None); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseInvestOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + ), + Error::::AssetNotFound, + ); + }) + } + } +} + +mod handle_cancel_invest_order { + use super::*; + + fn config_mocks() { + DomainAccountToDomainAddress::mock_convert(|_| CENTRIFUGE_DOMAIN_ADDRESS); + DomainAddressToAccountId::mock_convert(|_| ALICE); + ForeignInvestment::mock_investment(|_, _| Ok(AMOUNT)); + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + ForeignInvestment::mock_decrease_foreign_investment( + |who, investment_id, amount, foreign_currency| { + assert_eq!(*who, ALICE); + assert_eq!(investment_id, INVESTMENT_ID); + assert_eq!(amount, AMOUNT); + assert_eq!(foreign_currency, CURRENCY_ID); + Ok(()) + }, + ); + } + + #[test] + fn success() { + System::externalities().execute_with(|| { + config_mocks(); + + assert_ok!(LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::CancelInvestOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + }, + )); + }); + } + + mod erroring_out { + use super::*; + + #[test] + fn with_wrong_pool() { + System::externalities().execute_with(|| { + config_mocks(); + Pools::mock_pool_exists(|_| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::CancelInvestOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + }, + ), + Error::::PoolNotFound, + ); + }) + } + + #[test] + fn with_wrong_tranche() { + System::externalities().execute_with(|| { + config_mocks(); + Pools::mock_tranche_exists(|_, _| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::CancelInvestOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + }, + ), + Error::::TrancheNotFound, + ); + }) + } + + #[test] + fn with_no_metadata() { + System::externalities().execute_with(|| { + config_mocks(); + AssetRegistry::mock_metadata(|_| None); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::CancelInvestOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + }, + ), + Error::::AssetNotFound, + ); + }) + } + } +} + +mod handle_increase_redeem_order { + use super::*; + + fn config_mocks() { + DomainAccountToDomainAddress::mock_convert(|_| CENTRIFUGE_DOMAIN_ADDRESS); + DomainAddressToAccountId::mock_convert(|_| ALICE); + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + ForeignInvestment::mock_increase_foreign_redemption( + |who, investment_id, amount, foreign_currency| { + assert_eq!(*who, ALICE); + assert_eq!(investment_id, INVESTMENT_ID); + assert_eq!(amount, AMOUNT); + assert_eq!(foreign_currency, CURRENCY_ID); + Ok(()) + }, + ); + } + + #[test] + fn success() { + System::externalities().execute_with(|| { + config_mocks(); + + Tokens::mint_into( + TRANCHE_CURRENCY, + &EVM_DOMAIN_ADDRESS.domain().into_account(), + AMOUNT, + ) + .unwrap(); + + assert_ok!(LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + )); + + let destination = EVM_DOMAIN_ADDRESS.domain().into_account(); + assert_eq!(Tokens::balance(TRANCHE_CURRENCY, &destination), 0); + assert_eq!(Tokens::balance(TRANCHE_CURRENCY, &ALICE), AMOUNT); + }); + } + + mod erroring_out { + use super::*; + + #[test] + fn with_wrong_pool() { + System::externalities().execute_with(|| { + config_mocks(); + Pools::mock_pool_exists(|_| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + ), + Error::::PoolNotFound, + ); + }) + } + + #[test] + fn with_wrong_tranche() { + System::externalities().execute_with(|| { + config_mocks(); + Pools::mock_tranche_exists(|_, _| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + ), + Error::::TrancheNotFound, + ); + }) + } + + #[test] + fn with_no_metadata() { + System::externalities().execute_with(|| { + config_mocks(); + AssetRegistry::mock_metadata(|_| None); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + ), + Error::::AssetNotFound, + ); + }) + } + + #[test] + fn without_sufficient_balance() { + System::externalities().execute_with(|| { + config_mocks(); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::IncreaseRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + amount: AMOUNT, + }, + ), + orml_tokens::Error::::BalanceTooLow + ); + }) + } + } +} + +mod handle_cancel_redeem_order { + use super::*; + + fn config_mocks() { + DomainAccountToDomainAddress::mock_convert(|_| CENTRIFUGE_DOMAIN_ADDRESS); + DomainAddressToAccountId::mock_convert(|_| ALICE); + ForeignInvestment::mock_redemption(|_, _| Ok(AMOUNT)); + Pools::mock_pool_exists(|_| true); + Pools::mock_tranche_exists(|_, _| true); + AssetRegistry::mock_metadata(|_| Some(util::default_metadata())); + ForeignInvestment::mock_decrease_foreign_redemption( + |who, investment_id, amount, foreign_currency| { + assert_eq!(*who, ALICE); + assert_eq!(investment_id, INVESTMENT_ID); + assert_eq!(amount, AMOUNT); + assert_eq!(foreign_currency, CURRENCY_ID); + + // Side effects of this call + ForeignInvestment::mock_redemption(|_, _| Ok(0)); + Tokens::mint_into(TRANCHE_CURRENCY, &ALICE, AMOUNT).unwrap(); + Ok(()) + }, + ); + Gateway::mock_submit(|sender, destination, msg| { + assert_eq!(sender, TreasuryAccount::get()); + assert_eq!(destination, EVM_DOMAIN_ADDRESS.domain()); + assert_eq!( + msg, + Message::ExecutedDecreaseRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + tranche_tokens_payout: AMOUNT, + remaining_redeem_amount: 0, + } + ); + Ok(()) + }); + } + + #[test] + fn success() { + System::externalities().execute_with(|| { + config_mocks(); + + assert_ok!(LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::CancelRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + }, + )); + + let destination = EVM_DOMAIN_ADDRESS.domain().into_account(); + assert_eq!(Tokens::balance(TRANCHE_CURRENCY, &ALICE), 0); + assert_eq!(Tokens::balance(TRANCHE_CURRENCY, &destination), AMOUNT); + }); + } + + mod erroring_out { + use super::*; + + #[test] + fn with_wrong_pool() { + System::externalities().execute_with(|| { + config_mocks(); + Pools::mock_pool_exists(|_| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::CancelRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + }, + ), + Error::::PoolNotFound, + ); + }) + } + + #[test] + fn with_wrong_tranche() { + System::externalities().execute_with(|| { + config_mocks(); + Pools::mock_tranche_exists(|_, _| false); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::CancelRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + }, + ), + Error::::TrancheNotFound, + ); + }) + } + + #[test] + fn with_no_metadata() { + System::externalities().execute_with(|| { + config_mocks(); + AssetRegistry::mock_metadata(|_| None); + + assert_noop!( + LiquidityPools::submit( + EVM_DOMAIN_ADDRESS, + Message::CancelRedeemOrder { + pool_id: POOL_ID, + tranche_id: TRANCHE_ID, + investor: ALICE.into(), + currency: util::currency_index(CURRENCY_ID), + }, + ), + Error::::AssetNotFound, + ); + }) + } + } +}