From 472d1af5935e733b0de9d7f71f40a5f4d15a14e4 Mon Sep 17 00:00:00 2001 From: Frederik Gartenmeister Date: Fri, 1 Mar 2024 16:41:38 +0100 Subject: [PATCH] fix: bug on oracle fetching (#1750) * fix: bug on oracle fetching * feat: tests for oracle provider. WTF... * feat: enable for runtimes * chore: add no-std feat gate migration tuples * fix: compilation * feat: final tests * chore: rm unused test mod * fix: change request * fix: review request * fix: unused import * fix: integration tests --------- Co-authored-by: William Freudenberger --- runtime/centrifuge/src/migrations.rs | 12 -- runtime/common/src/oracle.rs | 4 +- .../src/generic/cases/investments.rs | 22 +-- .../src/generic/cases/loans.rs | 24 ++- .../src/generic/cases/oracles.rs | 171 +++++++++++++++++ .../src/generic/cases/proxy.rs | 24 ++- .../src/generic/envs/runtime_env.rs | 11 +- runtime/integration-tests/src/generic/mod.rs | 1 + .../src/generic/utils/currency.rs | 180 ++++++++++-------- .../src/generic/utils/genesis.rs | 6 +- 10 files changed, 332 insertions(+), 123 deletions(-) create mode 100644 runtime/integration-tests/src/generic/cases/oracles.rs diff --git a/runtime/centrifuge/src/migrations.rs b/runtime/centrifuge/src/migrations.rs index b33b804a20..a47affdd31 100644 --- a/runtime/centrifuge/src/migrations.rs +++ b/runtime/centrifuge/src/migrations.rs @@ -89,18 +89,6 @@ pub type UpgradeCentrifuge1025 = ( burn_unburned::Migration, ); -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - mod burn_unburned { const LOG_PREFIX: &str = "BurnUnburnedMigration: "; const LP_ETH_USDC: CurrencyId = CurrencyId::ForeignAsset(100_001); diff --git a/runtime/common/src/oracle.rs b/runtime/common/src/oracle.rs index c2448e69f4..8ecc509c92 100644 --- a/runtime/common/src/oracle.rs +++ b/runtime/common/src/oracle.rs @@ -187,8 +187,8 @@ where (from, to): &(CurrencyId, CurrencyId), ) -> Result, DispatchError> { let locally_coupled_assets = match (from, to) { - (_, &CurrencyId::LocalAsset(_)) => from.is_local_representation_of(to), - (&CurrencyId::LocalAsset(_), _) => to.is_local_representation_of(from), + (_, &CurrencyId::LocalAsset(_)) => to.is_local_representation_of(from), + (&CurrencyId::LocalAsset(_), _) => from.is_local_representation_of(to), _ => Ok(false), }?; diff --git a/runtime/integration-tests/src/generic/cases/investments.rs b/runtime/integration-tests/src/generic/cases/investments.rs index 8fb446dd41..83abfb1855 100644 --- a/runtime/integration-tests/src/generic/cases/investments.rs +++ b/runtime/integration-tests/src/generic/cases/investments.rs @@ -41,15 +41,15 @@ mod common { let mut env = E::from_parachain_storage( Genesis::::default() .add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES)) - .add(genesis::assets(vec![Usd6::ID])) - .add(genesis::tokens(vec![(Usd6::ID, Usd6::ED)])) + .add(genesis::assets(vec![Box::new(Usd6)])) + .add(genesis::tokens(vec![(Usd6.id(), Usd6.ed())])) .storage(), ); env.parachain_state_mut(|| { // Create a pool utils::give_balance::(POOL_ADMIN.id(), T::PoolDeposit::get()); - utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, Usd6::ID); + utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, Usd6.id()); // Grant permissions let tranche_id = T::Api::tranche_id(POOL_A, 0).unwrap(); @@ -73,7 +73,7 @@ fn investment_portfolio_single_tranche() { // Invest to have pending pool currency env.parachain_state_mut(|| { - utils::give_tokens::(INVESTOR.id(), Usd6::ID, EXPECTED_POOL_BALANCE); + utils::give_tokens::(INVESTOR.id(), Usd6.id(), EXPECTED_POOL_BALANCE); utils::invest::(INVESTOR.id(), POOL_A, tranche_id, EXPECTED_POOL_BALANCE); assert_eq!( pallet_investments::InvestOrders::::get(INVESTOR.id(), invest_id) @@ -87,7 +87,7 @@ fn investment_portfolio_single_tranche() { investment_portfolio, vec![( invest_id, - InvestmentPortfolio::::new(Usd6::ID) + InvestmentPortfolio::::new(Usd6.id()) .with_pending_invest_currency(EXPECTED_POOL_BALANCE) )] ); @@ -102,7 +102,7 @@ fn investment_portfolio_single_tranche() { investment_portfolio, vec![( invest_id, - InvestmentPortfolio::::new(Usd6::ID) + InvestmentPortfolio::::new(Usd6.id()) .with_claimable_tranche_tokens(EXPECTED_POOL_BALANCE) )] ); @@ -116,7 +116,7 @@ fn investment_portfolio_single_tranche() { investment_portfolio, vec![( invest_id, - InvestmentPortfolio::::new(Usd6::ID) + InvestmentPortfolio::::new(Usd6.id()) .with_free_tranche_tokens(EXPECTED_POOL_BALANCE) )] ); @@ -130,7 +130,7 @@ fn investment_portfolio_single_tranche() { investment_portfolio, vec![( invest_id, - InvestmentPortfolio::::new(Usd6::ID) + InvestmentPortfolio::::new(Usd6.id()) .with_free_tranche_tokens(EXPECTED_POOL_BALANCE - REDEEM_AMOUNT) .with_pending_redeem_tranche_tokens(REDEEM_AMOUNT) )] @@ -146,7 +146,7 @@ fn investment_portfolio_single_tranche() { investment_portfolio, vec![( invest_id, - InvestmentPortfolio::::new(Usd6::ID) + InvestmentPortfolio::::new(Usd6.id()) .with_free_tranche_tokens(EXPECTED_POOL_BALANCE - REDEEM_AMOUNT) .with_claimable_currency(REDEEM_AMOUNT) )] @@ -161,7 +161,7 @@ fn investment_portfolio_single_tranche() { investment_portfolio, vec![( invest_id, - InvestmentPortfolio::::new(Usd6::ID) + InvestmentPortfolio::::new(Usd6.id()) .with_free_tranche_tokens(EXPECTED_POOL_BALANCE - REDEEM_AMOUNT) )] ); @@ -181,7 +181,7 @@ fn investment_portfolio_single_tranche() { investment_portfolio, vec![( invest_id, - InvestmentPortfolio::::new(Usd6::ID) + InvestmentPortfolio::::new(Usd6.id()) .with_free_tranche_tokens(EXPECTED_POOL_BALANCE - REDEEM_AMOUNT - HOLD_AMOUNT) .with_reserved_tranche_tokens(HOLD_AMOUNT) )] diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index 800dc1ac08..e28a4224cd 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -73,15 +73,15 @@ mod common { let mut env = E::from_parachain_storage( Genesis::::default() .add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES)) - .add(genesis::assets(vec![Usd6::ID])) - .add(genesis::tokens(vec![(Usd6::ID, Usd6::ED)])) + .add(genesis::assets(vec![Box::new(Usd6)])) + .add(genesis::tokens(vec![(Usd6.id(), Usd6.ed())])) .storage(), ); env.parachain_state_mut(|| { // Creating a pool utils::give_balance::(POOL_ADMIN.id(), T::PoolDeposit::get()); - utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, Usd6::ID); + utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, Usd6.id()); // Setting borrower utils::give_pool_role::(BORROWER.id(), POOL_A, PoolRole::Borrower); @@ -94,7 +94,7 @@ mod common { let tranche_id = T::Api::tranche_id(POOL_A, 0).unwrap(); let tranche_investor = PoolRole::TrancheInvestor(tranche_id, Seconds::MAX); utils::give_pool_role::(INVESTOR.id(), POOL_A, tranche_investor); - utils::give_tokens::(INVESTOR.id(), Usd6::ID, EXPECTED_POOL_BALANCE); + utils::give_tokens::(INVESTOR.id(), Usd6.id(), EXPECTED_POOL_BALANCE); utils::invest::(INVESTOR.id(), POOL_A, tranche_id, EXPECTED_POOL_BALANCE); }); @@ -161,13 +161,13 @@ mod common { Pricing::External(ExternalPricing { price_id: PRICE_A, max_borrow_amount: ExtMaxBorrowAmount::Quantity(QUANTITY), - notional: currency::price_to_currency(PRICE_VALUE_A, Usd6::ID), + notional: currency::price_to_currency(PRICE_VALUE_A, Usd6), max_price_variation: rate_from_percent(50), }) } pub fn price_to_usd6(price: Quantity) -> Balance { - currency::price_to_currency(price, Usd6::ID) + currency::price_to_currency(price, Usd6) } } @@ -286,7 +286,11 @@ fn internal_priced() { env.parachain_state_mut(|| { // Give required tokens to the borrower to be able to repay the interest accrued // until this moment - utils::give_tokens::(BORROWER.id(), Usd6::ID, loan_portfolio.outstanding_interest); + utils::give_tokens::( + BORROWER.id(), + Usd6.id(), + loan_portfolio.outstanding_interest, + ); }); env.submit_now( @@ -326,7 +330,11 @@ fn oracle_priced() { env.parachain_state_mut(|| { // Give required tokens to the borrower to be able to repay the interest accrued // until this moment - utils::give_tokens::(BORROWER.id(), Usd6::ID, loan_portfolio.outstanding_interest); + utils::give_tokens::( + BORROWER.id(), + Usd6.id(), + loan_portfolio.outstanding_interest, + ); // Oracle modify the value utils::oracle::feed_from_root::(PRICE_A, PRICE_VALUE_B); diff --git a/runtime/integration-tests/src/generic/cases/oracles.rs b/runtime/integration-tests/src/generic/cases/oracles.rs new file mode 100644 index 0000000000..3e0d2dd380 --- /dev/null +++ b/runtime/integration-tests/src/generic/cases/oracles.rs @@ -0,0 +1,171 @@ +// Copyright 2021 Centrifuge Foundation (centrifuge.io). +// +// This file is part of the Centrifuge chain project. +// Centrifuge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version (see http://www.gnu.org/licenses). +// Centrifuge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +//! Testing setups around our oracles + +mod ratio_provider { + use cfg_traits::ValueProvider; + use cfg_types::{ + fixed_point::Ratio, + oracles::OracleKey, + tokens::{CrossChainTransferability, CurrencyId, CustomMetadata, LocalAssetId}, + }; + use frame_support::traits::OriginTrait; + use runtime_common::oracle::Feeder; + use sp_runtime::{traits::One, FixedPointNumber}; + + use crate::{ + generic::{ + config::Runtime, + env::Env, + envs::runtime_env::RuntimeEnv, + utils::currency::{register_currency, CurrencyInfo, CONST_DEFAULT_CUSTOM}, + }, + test_for_runtimes, + }; + + pub struct OtherLocal; + impl CurrencyInfo for OtherLocal { + fn id(&self) -> CurrencyId { + CurrencyId::LocalAsset(LocalAssetId(2)) + } + + fn custom(&self) -> CustomMetadata { + CustomMetadata { + pool_currency: true, + transferability: CrossChainTransferability::None, + ..CONST_DEFAULT_CUSTOM + } + } + } + + pub struct LocalUSDC; + impl CurrencyInfo for LocalUSDC { + fn id(&self) -> CurrencyId { + CurrencyId::LocalAsset(LocalAssetId(1)) + } + + fn custom(&self) -> CustomMetadata { + CustomMetadata { + pool_currency: true, + transferability: CrossChainTransferability::None, + ..CONST_DEFAULT_CUSTOM + } + } + } + + pub struct DomainUSDC; + impl CurrencyInfo for DomainUSDC { + fn id(&self) -> CurrencyId { + CurrencyId::ForeignAsset(100_001) + } + + fn custom(&self) -> CustomMetadata { + CustomMetadata { + pool_currency: true, + transferability: CrossChainTransferability::LiquidityPools, + local_representation: Some(LocalAssetId(1)), + ..CONST_DEFAULT_CUSTOM + } + } + } + + fn feeder() -> Feeder { + pallet_order_book::MarketFeederId::::get().unwrap() + } + + fn get_rate_with( + key: (CurrencyId, CurrencyId), + setup: impl FnOnce(), + ) -> Option { + let mut env = RuntimeEnv::::default(); + + env.parachain_state_mut(|| { + register_currency::(LocalUSDC, |_| {}); + register_currency::(DomainUSDC, |_| {}); + register_currency::(OtherLocal, |_| {}); + + pallet_order_book::Pallet::::set_market_feeder( + T::RuntimeOriginExt::root(), + Feeder::::root(), + ) + .unwrap(); + + setup(); + + ::RatioProvider::get(&feeder::(), &key).unwrap() + }) + } + + fn get_rate(key: (CurrencyId, CurrencyId)) -> Option { + get_rate_with::(key, || {}) + } + + fn local_to_variant() { + assert_eq!( + get_rate::((LocalUSDC.id(), DomainUSDC.id())), + Some(Ratio::one()) + ); + } + + fn variant_to_local() { + assert_eq!( + get_rate::((DomainUSDC.id(), LocalUSDC.id())), + Some(Ratio::one()) + ); + } + + fn variant_to_other_local() { + assert_eq!(get_rate::((DomainUSDC.id(), OtherLocal.id())), None); + } + + fn other_local_to_variant() { + assert_eq!(get_rate::((OtherLocal.id(), DomainUSDC.id())), None); + } + + fn variant_to_local_rate_set() { + let pair = (LocalUSDC.id(), DomainUSDC.id()); + assert_eq!( + get_rate_with::(pair, || { + pallet_oracle_feed::Pallet::::feed( + feeder::().0.into(), + OracleKey::ConversionRatio(pair.1, pair.0), + Ratio::checked_from_rational(1, 5).unwrap(), + ) + .unwrap(); + }), + Some(Ratio::one()) + ); + } + + fn local_to_variant_rate_set() { + let pair = (LocalUSDC.id(), DomainUSDC.id()); + assert_eq!( + get_rate_with::(pair, || { + pallet_oracle_feed::Pallet::::feed( + feeder::().0.into(), + OracleKey::ConversionRatio(pair.0, pair.1), + Ratio::checked_from_rational(1, 5).unwrap(), + ) + .unwrap(); + }), + Some(Ratio::one()) + ); + } + + test_for_runtimes!(all, variant_to_local); + test_for_runtimes!(all, local_to_variant); + test_for_runtimes!(all, variant_to_other_local); + test_for_runtimes!(all, other_local_to_variant); + test_for_runtimes!(all, variant_to_local_rate_set); + test_for_runtimes!(all, local_to_variant_rate_set); +} diff --git a/runtime/integration-tests/src/generic/cases/proxy.rs b/runtime/integration-tests/src/generic/cases/proxy.rs index 834fc9ca71..fd0e301c08 100644 --- a/runtime/integration-tests/src/generic/cases/proxy.rs +++ b/runtime/integration-tests/src/generic/cases/proxy.rs @@ -1,4 +1,5 @@ use cfg_primitives::Balance; +use cfg_types::{tokens::CrossChainTransferability, xcm::XcmMetadata}; use frame_support::{assert_err, assert_ok, traits::Get}; use frame_system::RawOrigin; use sp_runtime::{traits::StaticLookup, DispatchResult}; @@ -37,12 +38,12 @@ fn configure_proxy_and_transfer(proxy_type: T::ProxyType) -> Dispatc let env = RuntimeEnv::::from_parachain_storage( Genesis::::default() .add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES)) - .add(genesis::tokens(vec![(Usd6::ID, Usd6::ED)])) + .add(genesis::tokens(vec![(Usd6.id(), Usd6.ed())])) .storage(), ); let call = pallet_restricted_tokens::Call::transfer { - currency_id: Usd6::ID, + currency_id: Usd6.id(), amount: TRANSFER_AMOUNT, dest: T::Lookup::unlookup(TO.id()), } @@ -59,21 +60,26 @@ fn configure_proxy_and_x_transfer( .add(genesis::balances::( T::ExistentialDeposit::get() + FOR_FEES, )) - .add(genesis::tokens(vec![(Usd6::ID, Usd6::ED)])) + .add(genesis::tokens(vec![(Usd6.id(), Usd6.ed())])) .storage(), ); setup_xcm(&mut env); env.parachain_state_mut(|| { - register_currency::(Some(VersionedMultiLocation::V3(MultiLocation::new( - 1, - X1(Parachain(T::FudgeHandle::SIBLING_ID)), - )))); + register_currency::(Usd6, |meta| { + meta.location = Some(VersionedMultiLocation::V3(MultiLocation::new( + 1, + X1(Parachain(T::FudgeHandle::SIBLING_ID)), + ))); + meta.additional.transferability = CrossChainTransferability::Xcm(XcmMetadata { + fee_per_second: Some(1_000), + }); + }); }); let call = pallet_restricted_xtokens::Call::transfer { - currency_id: Usd6::ID, + currency_id: Usd6.id(), amount: TRANSFER_AMOUNT, dest: Box::new( MultiLocation::new( @@ -101,7 +107,7 @@ fn configure_proxy_and_call( call: T::RuntimeCallExt, ) -> DispatchResult { env.parachain_state_mut(|| { - utils::give_tokens::(FROM.id(), Usd6::ID, TRANSFER_AMOUNT); + utils::give_tokens::(FROM.id(), Usd6.id(), TRANSFER_AMOUNT); // Register PROXY as proxy of FROM pallet_proxy::Pallet::::add_proxy( diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 097981ffe9..88495d3205 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -11,11 +11,12 @@ use frame_support::{ storage::{transactional, TransactionOutcome}, traits::GenesisBuild, }; +use frame_system::LastRuntimeUpgradeInfo; use parity_scale_codec::Encode; use sp_api::runtime_decl_for_core::CoreV4; use sp_block_builder::runtime_decl_for_block_builder::BlockBuilderV6; use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; -use sp_core::{sr25519::Public, H256}; +use sp_core::{sr25519::Public, Get, H256}; use sp_runtime::{ traits::Extrinsic, transaction_validity::{InvalidTransaction, TransactionValidityError}, @@ -66,6 +67,14 @@ impl Env for RuntimeEnv { let mut parachain_ext = sp_io::TestExternalities::new(parachain_storage); + // NOTE: Setting the current on-chain runtime version to the latest one, to + // prevent running migrations + parachain_ext.execute_with(|| { + frame_system::LastRuntimeUpgrade::::put(LastRuntimeUpgradeInfo::from( + ::Version::get(), + )) + }); + parachain_ext.execute_with(|| Self::prepare_block(1)); // Needed for the aura usage diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 5e21be5bc1..fb0fe1c517 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -19,6 +19,7 @@ mod cases { mod investments; mod liquidity_pools; mod loans; + mod oracles; mod proxy; mod restricted_transfers; } diff --git a/runtime/integration-tests/src/generic/utils/currency.rs b/runtime/integration-tests/src/generic/utils/currency.rs index 954fdd9a88..5acd2786fa 100644 --- a/runtime/integration-tests/src/generic/utils/currency.rs +++ b/runtime/integration-tests/src/generic/utils/currency.rs @@ -2,47 +2,59 @@ //! considered at this level. use cfg_primitives::{conversion, Balance, CFG}; -use cfg_types::{ - tokens::{AssetMetadata, CrossChainTransferability, CurrencyId, CustomMetadata}, - xcm::XcmMetadata, -}; +use cfg_types::tokens::{AssetMetadata, CrossChainTransferability, CurrencyId, CustomMetadata}; use frame_support::{assert_ok, traits::OriginTrait}; use sp_runtime::FixedPointNumber; -use xcm::VersionedMultiLocation; -use crate::generic::{config::Runtime, envs::fudge_env::FudgeSupport}; +use crate::generic::config::Runtime; pub const fn cfg(amount: Balance) -> Balance { amount * CFG } pub trait CurrencyInfo { - const ID: CurrencyId; - const DECIMALS: u32; - const UNIT: Balance = 10u128.pow(Self::DECIMALS); - const SYMBOL: &'static str; - const NAME: &'static str = Self::SYMBOL; - const LOCATION: Option = None; - const CUSTOM: CustomMetadata; - const ED: Balance = 0; - - fn metadata() -> AssetMetadata { + fn id(&self) -> CurrencyId; + + fn decimals(&self) -> u32 { + 18 + } + + fn unit(&self) -> Balance { + 10u128.pow(self.decimals()) + } + + fn symbol(&self) -> &'static str { + "TKN" + } + + fn name(&self) -> &'static str { + &self.symbol() + } + + fn location(&self) -> Option { + None + } + + fn custom(&self) -> CustomMetadata; + + fn ed(&self) -> Balance { + 0 + } + + fn metadata(&self) -> AssetMetadata { AssetMetadata { - decimals: Self::DECIMALS, - name: Self::NAME.as_bytes().to_vec(), - symbol: Self::SYMBOL.as_bytes().to_vec(), - existential_deposit: Self::ED, - location: None, - additional: CustomMetadata { - pool_currency: true, - ..Default::default() - }, + decimals: self.decimals(), + name: self.name().as_bytes().to_vec(), + symbol: self.symbol().as_bytes().to_vec(), + existential_deposit: self.ed(), + location: self.location(), + additional: self.custom(), } } } /// Matches default() but for const support -const CONST_DEFAULT_CUSTOM: CustomMetadata = CustomMetadata { +pub const CONST_DEFAULT_CUSTOM: CustomMetadata = CustomMetadata { transferability: CrossChainTransferability::None, mintable: false, permissioned: false, @@ -50,86 +62,100 @@ const CONST_DEFAULT_CUSTOM: CustomMetadata = CustomMetadata { local_representation: None, }; -pub fn find_metadata(currency_id: CurrencyId) -> AssetMetadata { - match currency_id { - Usd6::ID => Usd6::metadata(), - Usd12::ID => Usd12::metadata(), - Usd18::ID => Usd18::metadata(), - _ => panic!("Unsupported currency {currency_id:?}"), - } -} - pub fn price_to_currency>( price: N, - currency_id: CurrencyId, + currency_id: impl CurrencyInfo, ) -> Balance { - let decimals = find_metadata(currency_id).decimals; - conversion::fixed_point_to_balance(price, decimals as usize).unwrap() + conversion::fixed_point_to_balance(price, currency_id.decimals() as usize).unwrap() } pub struct Usd6; impl CurrencyInfo for Usd6 { - const CUSTOM: CustomMetadata = CustomMetadata { - pool_currency: true, - transferability: CrossChainTransferability::Xcm(XcmMetadata { - fee_per_second: Some(1_000), - }), - ..CONST_DEFAULT_CUSTOM - }; - const DECIMALS: u32 = 6; - const ID: CurrencyId = CurrencyId::ForeignAsset(1); - const SYMBOL: &'static str = "USD6"; + fn id(&self) -> CurrencyId { + CurrencyId::ForeignAsset(1) + } + + fn decimals(&self) -> u32 { + 6 + } + + fn symbol(&self) -> &'static str { + "USD6" + } + + fn custom(&self) -> CustomMetadata { + CustomMetadata { + pool_currency: true, + ..CONST_DEFAULT_CUSTOM + } + } } pub const fn usd6(amount: Balance) -> Balance { - amount * Usd6::UNIT + amount * 10u128.pow(6) } pub struct Usd12; impl CurrencyInfo for Usd12 { - const CUSTOM: CustomMetadata = CustomMetadata { - pool_currency: true, - ..CONST_DEFAULT_CUSTOM - }; - const DECIMALS: u32 = 12; - const ID: CurrencyId = CurrencyId::ForeignAsset(2); - const SYMBOL: &'static str = "USD12"; + fn id(&self) -> CurrencyId { + CurrencyId::ForeignAsset(2) + } + + fn decimals(&self) -> u32 { + 12 + } + + fn symbol(&self) -> &'static str { + "USD12" + } + + fn custom(&self) -> CustomMetadata { + CustomMetadata { + pool_currency: true, + ..CONST_DEFAULT_CUSTOM + } + } } pub const fn usd12(amount: Balance) -> Balance { - amount * Usd12::UNIT + amount * 10u128.pow(12) } pub struct Usd18; impl CurrencyInfo for Usd18 { - const CUSTOM: CustomMetadata = CustomMetadata { - pool_currency: true, - ..CONST_DEFAULT_CUSTOM - }; - const DECIMALS: u32 = 18; - const ID: CurrencyId = CurrencyId::ForeignAsset(3); - const SYMBOL: &'static str = "USD12"; + fn id(&self) -> CurrencyId { + CurrencyId::ForeignAsset(3) + } + + fn decimals(&self) -> u32 { + 18 + } + + fn symbol(&self) -> &'static str { + "USD12" + } + + fn custom(&self) -> CustomMetadata { + CustomMetadata { + pool_currency: true, + ..CONST_DEFAULT_CUSTOM + } + } } pub const fn usd18(amount: Balance) -> Balance { - amount * Usd18::UNIT + amount * 10u128.pow(18) } -pub fn register_currency( - location: Option, +pub fn register_currency( + currency: impl CurrencyInfo, + adaptor: impl FnOnce(&mut AssetMetadata), ) { - let meta: AssetMetadata = AssetMetadata { - decimals: C::DECIMALS, - name: C::NAME.into(), - symbol: C::SYMBOL.into(), - existential_deposit: C::ED, - location, - additional: C::CUSTOM, - }; - + let mut meta = currency.metadata(); + adaptor(&mut meta); assert_ok!(orml_asset_registry::Pallet::::register_asset( ::RuntimeOrigin::root(), meta, - Some(C::ID) + Some(currency.id()) )); } diff --git a/runtime/integration-tests/src/generic/utils/genesis.rs b/runtime/integration-tests/src/generic/utils/genesis.rs index 871fcceb30..7792bc92ef 100644 --- a/runtime/integration-tests/src/generic/utils/genesis.rs +++ b/runtime/integration-tests/src/generic/utils/genesis.rs @@ -11,7 +11,7 @@ use sp_core::crypto::AccountId32; use sp_runtime::Storage; use crate::{ - generic::{config::Runtime, utils::currency}, + generic::{config::Runtime, utils::currency::CurrencyInfo}, utils::accounts::{default_accounts, Keyring}, }; @@ -67,11 +67,11 @@ pub fn tokens(values: Vec<(CurrencyId, Balance)>) -> impl GenesisBui } } -pub fn assets(currency_ids: Vec) -> impl GenesisBuild { +pub fn assets(currency_ids: Vec>) -> impl GenesisBuild { orml_asset_registry::GenesisConfig:: { assets: currency_ids .into_iter() - .map(|currency_id| (currency_id, currency::find_metadata(currency_id).encode())) + .map(|currency_id| (currency_id.id(), currency_id.metadata().encode())) .collect(), last_asset_id: Default::default(), // It seems deprecated }