From 3add4c5df65a8d85f3103cac4532842dd9b4e37e Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas Date: Mon, 3 Mar 2025 18:02:08 +0000 Subject: [PATCH] test new behaviour --- runtime/moonbeam/tests/common/mod.rs | 55 +++++-- runtime/moonbeam/tests/integration_test.rs | 171 +++++++++++++------- runtime/moonriver/tests/common/mod.rs | 55 +++++-- runtime/moonriver/tests/integration_test.rs | 168 ++++++++++++------- 4 files changed, 310 insertions(+), 139 deletions(-) diff --git a/runtime/moonbeam/tests/common/mod.rs b/runtime/moonbeam/tests/common/mod.rs index 0dce9be4f3..eb5e08d08d 100644 --- a/runtime/moonbeam/tests/common/mod.rs +++ b/runtime/moonbeam/tests/common/mod.rs @@ -37,6 +37,8 @@ use sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem, Perbill use std::collections::BTreeMap; use fp_rpc::ConvertTransaction; +use moonbeam_runtime::EvmForeignAssets; +use sp_runtime::traits::MaybeEquivalence; pub fn existential_deposit() -> u128 { ::ExistentialDeposit::get() @@ -142,6 +144,7 @@ pub struct ExtBuilder { evm_accounts: BTreeMap, // [assettype, metadata, Vec, is_sufficient] xcm_assets: Vec, + evm_native_foreign_assets: bool, safe_xcm_version: Option, } @@ -175,6 +178,7 @@ impl Default for ExtBuilder { chain_id: CHAIN_ID, evm_accounts: BTreeMap::new(), xcm_assets: vec![], + evm_native_foreign_assets: false, safe_xcm_version: None, } } @@ -219,6 +223,11 @@ impl ExtBuilder { self } + pub fn with_evm_native_foreign_assets(mut self) -> Self { + self.evm_native_foreign_assets = true; + self + } + pub fn with_safe_xcm_version(mut self, safe_xcm_version: u32) -> Self { self.safe_xcm_version = Some(safe_xcm_version); self @@ -294,22 +303,40 @@ impl ExtBuilder { // If any xcm assets specified, we register them here for xcm_asset_initialization in xcm_assets { let asset_id: AssetId = xcm_asset_initialization.asset_type.clone().into(); - AssetManager::register_foreign_asset( - root_origin(), - xcm_asset_initialization.asset_type, - xcm_asset_initialization.metadata, - 1, - xcm_asset_initialization.is_sufficient, - ) - .unwrap(); - for (account, balance) in xcm_asset_initialization.balances { - moonbeam_runtime::Assets::mint( - origin_of(AssetManager::account_id()), - asset_id.into(), - account, - balance, + if self.evm_native_foreign_assets { + let AssetType::Xcm(location) = xcm_asset_initialization.asset_type; + let metadata = xcm_asset_initialization.metadata.clone(); + EvmForeignAssets::register_foreign_asset( + asset_id, + xcm_builder::WithLatestLocationConverter::convert_back(&location).unwrap(), + metadata.decimals, + metadata.symbol.try_into().unwrap(), + metadata.name.try_into().unwrap(), + ) + .expect("register evm native foreign asset"); + + for (account, balance) in xcm_asset_initialization.balances { + EvmForeignAssets::mint_into(asset_id.into(), account, balance.into()) + .expect("mint evm native foreign asset"); + } + } else { + AssetManager::register_foreign_asset( + root_origin(), + xcm_asset_initialization.asset_type, + xcm_asset_initialization.metadata, + 1, + xcm_asset_initialization.is_sufficient, ) .unwrap(); + for (account, balance) in xcm_asset_initialization.balances { + moonbeam_runtime::Assets::mint( + origin_of(AssetManager::account_id()), + asset_id.into(), + account, + balance, + ) + .unwrap(); + } } } System::set_block_number(1); diff --git a/runtime/moonbeam/tests/integration_test.rs b/runtime/moonbeam/tests/integration_test.rs index 16ad41fac2..904f2e8f59 100644 --- a/runtime/moonbeam/tests/integration_test.rs +++ b/runtime/moonbeam/tests/integration_test.rs @@ -19,7 +19,10 @@ #![cfg(test)] mod common; + use common::*; +use std::cell::Cell; +use std::rc::Rc; use fp_evm::{Context, IsPrecompileResult}; use frame_support::{ @@ -38,10 +41,11 @@ use moonbeam_runtime::{ asset_config::ForeignAssetInstance, currency::GLMR, xcm_config::{CurrencyId, SelfReserve}, - AccountId, Balances, CrowdloanRewards, Executive, OpenTechCommitteeCollective, - ParachainStaking, PolkadotXcm, Precompiles, Runtime, RuntimeBlockWeights, RuntimeCall, - RuntimeEvent, System, TransactionPayment, TransactionPaymentAsGasPrice, Treasury, - TreasuryCouncilCollective, XcmTransactor, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, WEEKS, + AccountId, Balances, CrowdloanRewards, EvmForeignAssets, Executive, + OpenTechCommitteeCollective, ParachainStaking, PolkadotXcm, Precompiles, Runtime, + RuntimeBlockWeights, RuntimeCall, RuntimeEvent, System, TransactionPayment, + TransactionPaymentAsGasPrice, Treasury, TreasuryCouncilCollective, XcmTransactor, + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, WEEKS, }; use moonbeam_xcm_benchmarks::weights::XcmWeight; use moonkit_xcm_primitives::AccountIdAssetIdConversion; @@ -1942,62 +1946,117 @@ fn xcm_asset_erc20_precompiles_approve() { #[test] fn xtokens_precompile_transfer() { - ExtBuilder::default() - .with_xcm_assets(vec![XcmAssetInitialization { - asset_type: AssetType::Xcm(xcm::v3::Location::parent()), - metadata: AssetRegistrarMetadata { - name: b"RelayToken".to_vec(), - symbol: b"Relay".to_vec(), - decimals: 12, - is_frozen: false, - }, - balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], - is_sufficient: true, - }]) - .with_balances(vec![ - (AccountId::from(ALICE), 2_000 * GLMR), - (AccountId::from(BOB), 1_000 * GLMR), - ]) - .with_safe_xcm_version(3) - .build() - .execute_with(|| { - let xtokens_precompile_address = H160::from_low_u64_be(2052); + fn run_test_variant(evm_native: bool) { + let mut builder = ExtBuilder::default(); - // We have the assetId that corresponds to the relay chain registered - let relay_asset_id: moonbeam_runtime::AssetId = - AssetType::Xcm(xcm::v3::Location::parent()).into(); + if evm_native { + builder = builder.with_evm_native_foreign_assets(); + } - // Its address is - let asset_precompile_address = Runtime::asset_id_to_account( - FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, - relay_asset_id, - ); + let asset_type = AssetType::Xcm(xcm::v3::Location::parent()); + builder + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: asset_type.clone(), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_safe_xcm_version(3) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); - // Alice has 1000 tokens. She should be able to send through precompile - let destination = Location::new( - 1, - [Junction::AccountId32 { - network: None, - id: [1u8; 32], - }], - ); + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: moonbeam_runtime::AssetId = + AssetType::Xcm(xcm::v3::Location::parent()).into(); - // We use the address of the asset as an identifier of the asset we want to transfer - Precompiles::new() - .prepare_test( - ALICE, - xtokens_precompile_address, - XtokensPCall::transfer { - currency_address: Address(asset_precompile_address.into()), - amount: 500_000_000_000_000u128.into(), - destination, - weight: 4_000_000, - }, - ) - .expect_cost(25121) - .expect_no_logs() - .execute_returns(()) - }) + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = Location::new( + 1, + [Junction::AccountId32 { + network: None, + id: [1u8; 32], + }], + ); + + let inside = Rc::new(Cell::new(false)); + let inside2 = inside.clone(); + + // We use the address of the asset as an identifier of the asset we want to transfer + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer { + currency_address: Address(asset_precompile_address.into()), + amount: 500_000_000_000_000u128.into(), + destination, + weight: 4_000_000, + }, + ) + .expect_cost(if evm_native { 176721 } else { 25121 }) + .expect_no_logs() + // We expect an evm subcall ERC20.burnFrom + .with_subcall_handle(move |subcall| { + let Subcall { + address, + transfer, + input, + target_gas: _, + is_static, + context, + } = subcall; + + assert_eq!(context.caller, EvmForeignAssets::account_id().into()); + + let asset_id: u128 = asset_type.clone().into(); + let expected_address: H160 = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + asset_id, + ) + .into(); + assert_eq!(address, expected_address); + assert_eq!(is_static, false); + + assert!(transfer.is_none()); + + assert_eq!(context.address, expected_address); + assert_eq!(context.apparent_value, 0u8.into()); + + assert_eq!(&input[..4], &keccak256!("burnFrom(address,uint256)")[..4]); + assert_eq!(&input[4..16], &[0u8; 12]); + assert_eq!(&input[16..36], ALICE); + + inside2.set(true); + + SubcallOutput { + output: Default::default(), + cost: 149_000, + logs: vec![], + ..SubcallOutput::succeed() + } + }) + .execute_returns(()) + }) + } + + run_test_variant(false); + run_test_variant(true); } #[test] diff --git a/runtime/moonriver/tests/common/mod.rs b/runtime/moonriver/tests/common/mod.rs index aa77aac886..bec87a643b 100644 --- a/runtime/moonriver/tests/common/mod.rs +++ b/runtime/moonriver/tests/common/mod.rs @@ -37,7 +37,9 @@ use sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem, Perbill use std::collections::BTreeMap; use fp_rpc::ConvertTransaction; +use moonriver_runtime::{Assets, EvmForeignAssets}; use pallet_transaction_payment::Multiplier; +use sp_runtime::traits::MaybeEquivalence; pub fn existential_deposit() -> u128 { ::ExistentialDeposit::get() @@ -143,6 +145,7 @@ pub struct ExtBuilder { evm_accounts: BTreeMap, // [assettype, metadata, Vec, is_sufficient] xcm_assets: Vec, + evm_native_foreign_assets: bool, safe_xcm_version: Option, } @@ -176,6 +179,7 @@ impl Default for ExtBuilder { chain_id: CHAIN_ID, evm_accounts: BTreeMap::new(), xcm_assets: vec![], + evm_native_foreign_assets: false, safe_xcm_version: None, } } @@ -226,6 +230,11 @@ impl ExtBuilder { self } + pub fn with_evm_native_foreign_assets(mut self) -> Self { + self.evm_native_foreign_assets = true; + self + } + pub fn with_safe_xcm_version(mut self, safe_xcm_version: u32) -> Self { self.safe_xcm_version = Some(safe_xcm_version); self @@ -301,22 +310,40 @@ impl ExtBuilder { // If any xcm assets specified, we register them here for xcm_asset_initialization in xcm_assets { let asset_id: AssetId = xcm_asset_initialization.asset_type.clone().into(); - AssetManager::register_foreign_asset( - root_origin(), - xcm_asset_initialization.asset_type, - xcm_asset_initialization.metadata, - 1, - xcm_asset_initialization.is_sufficient, - ) - .unwrap(); - for (account, balance) in xcm_asset_initialization.balances { - moonriver_runtime::Assets::mint( - origin_of(AssetManager::account_id()), - asset_id.into(), - account, - balance, + if self.evm_native_foreign_assets { + let AssetType::Xcm(location) = xcm_asset_initialization.asset_type; + let metadata = xcm_asset_initialization.metadata.clone(); + EvmForeignAssets::register_foreign_asset( + asset_id, + xcm_builder::WithLatestLocationConverter::convert_back(&location).unwrap(), + metadata.decimals, + metadata.symbol.try_into().unwrap(), + metadata.name.try_into().unwrap(), + ) + .expect("register evm native foreign asset"); + + for (account, balance) in xcm_asset_initialization.balances { + EvmForeignAssets::mint_into(asset_id.into(), account, balance.into()) + .expect("mint evm native foreign asset"); + } + } else { + AssetManager::register_foreign_asset( + root_origin(), + xcm_asset_initialization.asset_type, + xcm_asset_initialization.metadata, + 1, + xcm_asset_initialization.is_sufficient, ) .unwrap(); + for (account, balance) in xcm_asset_initialization.balances { + Assets::mint( + origin_of(AssetManager::account_id()), + asset_id.into(), + account, + balance, + ) + .unwrap(); + } } } System::set_block_number(1); diff --git a/runtime/moonriver/tests/integration_test.rs b/runtime/moonriver/tests/integration_test.rs index 5a3eb3feaf..115e179341 100644 --- a/runtime/moonriver/tests/integration_test.rs +++ b/runtime/moonriver/tests/integration_test.rs @@ -19,7 +19,10 @@ #![cfg(test)] mod common; + use common::*; +use std::cell::Cell; +use std::rc::Rc; use fp_evm::{Context, IsPrecompileResult}; use frame_support::traits::fungible::Inspect; @@ -40,9 +43,10 @@ use moonriver_runtime::runtime_params::dynamic_params; use moonriver_runtime::{ asset_config::ForeignAssetInstance, xcm_config::{CurrencyId, SelfReserve}, - AssetId, Balances, CrowdloanRewards, Executive, OpenTechCommitteeCollective, PolkadotXcm, - Precompiles, RuntimeBlockWeights, TransactionPayment, TransactionPaymentAsGasPrice, Treasury, - TreasuryCouncilCollective, XcmTransactor, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, WEEKS, + AssetId, Balances, CrowdloanRewards, EvmForeignAssets, Executive, OpenTechCommitteeCollective, + PolkadotXcm, Precompiles, RuntimeBlockWeights, TransactionPayment, + TransactionPaymentAsGasPrice, Treasury, TreasuryCouncilCollective, XcmTransactor, + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, WEEKS, }; use nimbus_primitives::NimbusId; use pallet_evm::PrecompileSet; @@ -1921,62 +1925,116 @@ fn xcm_asset_erc20_precompiles_approve() { #[test] fn xtokens_precompiles_transfer() { - ExtBuilder::default() - .with_xcm_assets(vec![XcmAssetInitialization { - asset_type: AssetType::Xcm(xcm::v3::Location::parent()), - metadata: AssetRegistrarMetadata { - name: b"RelayToken".to_vec(), - symbol: b"Relay".to_vec(), - decimals: 12, - is_frozen: false, - }, - balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], - is_sufficient: true, - }]) - .with_balances(vec![ - (AccountId::from(ALICE), 2_000 * MOVR), - (AccountId::from(BOB), 1_000 * MOVR), - ]) - .with_safe_xcm_version(3) - .build() - .execute_with(|| { - let xtokens_precompile_address = H160::from_low_u64_be(2052); + fn run_test_variant(evm_native: bool) { + let mut builder = ExtBuilder::default(); - // We have the assetId that corresponds to the relay chain registered - let relay_asset_id: moonriver_runtime::AssetId = - AssetType::Xcm(xcm::v3::Location::parent()).into(); + if evm_native { + builder = builder.with_evm_native_foreign_assets(); + } - // Its address is - let asset_precompile_address = Runtime::asset_id_to_account( - FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, - relay_asset_id, - ); + let asset_type = AssetType::Xcm(xcm::v3::Location::parent()); + builder + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: asset_type.clone(), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_safe_xcm_version(3) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); - // Alice has 1000 tokens. She should be able to send through precompile - let destination = Location::new( - 1, - [Junction::AccountId32 { - network: None, - id: [1u8; 32], - }], - ); + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: AssetId = AssetType::Xcm(xcm::v3::Location::parent()).into(); - // We use the address of the asset as an identifier of the asset we want to transferS - Precompiles::new() - .prepare_test( - ALICE, - xtokens_precompile_address, - XtokensPCall::transfer { - currency_address: Address(asset_precompile_address.into()), - amount: 500_000_000_000_000u128.into(), - destination, - weight: 4_000_000, - }, - ) - .expect_cost(25190) - .expect_no_logs() - .execute_returns(()) - }) + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = Location::new( + 1, + [Junction::AccountId32 { + network: None, + id: [1u8; 32], + }], + ); + + let inside = Rc::new(Cell::new(false)); + let inside2 = inside.clone(); + + // We use the address of the asset as an identifier of the asset we want to transfer + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer { + currency_address: Address(asset_precompile_address.into()), + amount: 500_000_000_000_000u128.into(), + destination, + weight: 4_000_000, + }, + ) + .expect_cost(if evm_native { 176790 } else { 25190 }) + .expect_no_logs() + // We expect an evm subcall ERC20.burnFrom + .with_subcall_handle(move |subcall| { + let Subcall { + address, + transfer, + input, + target_gas: _, + is_static, + context, + } = subcall; + + assert_eq!(context.caller, EvmForeignAssets::account_id().into()); + + let asset_id: u128 = asset_type.clone().into(); + let expected_address: H160 = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + asset_id, + ) + .into(); + assert_eq!(address, expected_address); + assert_eq!(is_static, false); + + assert!(transfer.is_none()); + + assert_eq!(context.address, expected_address); + assert_eq!(context.apparent_value, 0u8.into()); + + assert_eq!(&input[..4], &keccak256!("burnFrom(address,uint256)")[..4]); + assert_eq!(&input[4..16], &[0u8; 12]); + assert_eq!(&input[16..36], ALICE); + + inside2.set(true); + + SubcallOutput { + output: Default::default(), + cost: 149_000, + logs: vec![], + ..SubcallOutput::succeed() + } + }) + .execute_returns(()) + }) + } + + run_test_variant(false); + run_test_variant(true); } #[test]