diff --git a/Cargo.lock b/Cargo.lock index fbae6d19c1..a420dcd050 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -486,7 +486,7 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-backing-primitives" version = "0.9.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "sp-api", "sp-consensus-slots", @@ -6794,6 +6794,7 @@ dependencies = [ "pallet-evm-precompile-relay-verifier", "pallet-evm-precompile-sha3fips", "pallet-evm-precompile-simple", + "pallet-evm-precompile-xcm", "pallet-evm-precompile-xcm-transactor", "pallet-evm-precompile-xcm-utils", "pallet-evm-precompile-xtokens", @@ -7226,6 +7227,7 @@ dependencies = [ "pallet-evm-precompile-relay-verifier", "pallet-evm-precompile-sha3fips", "pallet-evm-precompile-simple", + "pallet-evm-precompile-xcm", "pallet-evm-precompile-xcm-transactor", "pallet-evm-precompile-xcm-utils", "pallet-evm-precompile-xtokens", @@ -7578,7 +7580,7 @@ dependencies = [ [[package]] name = "nimbus-consensus" version = "0.9.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "async-backing-primitives", "async-trait", @@ -7618,7 +7620,7 @@ dependencies = [ [[package]] name = "nimbus-primitives" version = "0.9.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "async-trait", "frame-benchmarking", @@ -8203,7 +8205,7 @@ dependencies = [ [[package]] name = "pallet-async-backing" version = "0.9.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-primitives-core", @@ -8223,7 +8225,7 @@ dependencies = [ [[package]] name = "pallet-author-inherent" version = "0.9.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "frame-benchmarking", "frame-support", @@ -8242,7 +8244,7 @@ dependencies = [ [[package]] name = "pallet-author-mapping" version = "2.0.5" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "frame-benchmarking", "frame-support", @@ -8261,7 +8263,7 @@ dependencies = [ [[package]] name = "pallet-author-slot-filter" version = "0.9.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "frame-benchmarking", "frame-support", @@ -8618,7 +8620,7 @@ dependencies = [ [[package]] name = "pallet-emergency-para-xcm" version = "0.1.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-primitives-core", @@ -9332,7 +9334,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-xcm" version = "0.1.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "cumulus-primitives-core", "evm", @@ -9343,12 +9345,15 @@ dependencies = [ "num_enum 0.7.3", "pallet-evm", "pallet-xcm", + "parity-scale-codec", "precompile-utils", + "scale-info", "sp-core", "sp-runtime", "sp-std", "sp-weights", "staging-xcm", + "staging-xcm-executor", "xcm-primitives 0.1.0", ] @@ -9580,7 +9585,7 @@ dependencies = [ [[package]] name = "pallet-maintenance-mode" version = "0.1.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -9631,7 +9636,7 @@ dependencies = [ [[package]] name = "pallet-migrations" version = "0.1.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "frame-benchmarking", "frame-support", @@ -9959,7 +9964,7 @@ dependencies = [ [[package]] name = "pallet-randomness" version = "0.1.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "environmental", "frame-benchmarking", @@ -10034,7 +10039,7 @@ dependencies = [ [[package]] name = "pallet-relay-storage-roots" version = "0.1.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-primitives-core", @@ -14895,7 +14900,7 @@ dependencies = [ [[package]] name = "session-keys-primitives" version = "0.1.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "async-trait", "frame-support", @@ -18548,7 +18553,7 @@ dependencies = [ [[package]] name = "xcm-primitives" version = "0.1.0" -source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#b808b333086a36fe405647e35d20ea953d77dca3" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-stable2407#f32e4035c5b00083accd53f0f6b829feb9b88b1e" dependencies = [ "frame-support", "impl-trait-for-tuples", diff --git a/runtime/moonbeam/Cargo.toml b/runtime/moonbeam/Cargo.toml index b8e0bde163..5c3bba2ebe 100644 --- a/runtime/moonbeam/Cargo.toml +++ b/runtime/moonbeam/Cargo.toml @@ -172,6 +172,7 @@ nimbus-primitives = { workspace = true } pallet-async-backing = { workspace = true } pallet-author-inherent = { workspace = true } pallet-author-slot-filter = { workspace = true } +pallet-evm-precompile-xcm = { workspace = true } pallet-relay-storage-roots = { workspace = true } # Benchmarking @@ -257,6 +258,7 @@ std = [ "pallet-evm-precompile-referenda/std", "pallet-evm-precompile-relay-encoder/std", "pallet-evm-precompile-relay-verifier/std", + "pallet-evm-precompile-xcm/std", "pallet-evm-precompile-xcm-transactor/std", "pallet-evm-precompile-xcm-utils/std", "pallet-evm-precompile-xtokens/std", diff --git a/runtime/moonbeam/src/lib.rs b/runtime/moonbeam/src/lib.rs index 12bf20574b..e99b378e10 100644 --- a/runtime/moonbeam/src/lib.rs +++ b/runtime/moonbeam/src/lib.rs @@ -1209,6 +1209,7 @@ impl Contains for NormalFilter { // is populated at genesis RuntimeCall::PolkadotXcm(method) => match method { pallet_xcm::Call::force_default_xcm_version { .. } => true, + pallet_xcm::Call::transfer_assets_using_type_and_then { .. } => true, _ => false, }, // We filter anonymous proxy as they make "reserve" inconsistent diff --git a/runtime/moonbeam/src/precompiles.rs b/runtime/moonbeam/src/precompiles.rs index 685f292ce3..934c7ff3b5 100644 --- a/runtime/moonbeam/src/precompiles.rs +++ b/runtime/moonbeam/src/precompiles.rs @@ -15,13 +15,17 @@ // along with Moonbeam. If not, see . use crate::{ - asset_config::ForeignAssetInstance, xcm_config::XcmExecutorConfig, OpenTechCommitteeInstance, - Runtime, TreasuryCouncilInstance, + asset_config::ForeignAssetInstance, + xcm_config::{AssetType, XcmExecutorConfig}, + AccountId, AssetId, AssetManager, Balances, Erc20XcmBridge, OpenTechCommitteeInstance, Runtime, + TreasuryCouncilInstance, H160, }; -use crate::{AssetId, H160}; use frame_support::parameter_types; use moonbeam_runtime_common::weights as moonbeam_weights; -use moonkit_xcm_primitives::AccountIdAssetIdConversion; +use moonkit_xcm_primitives::{ + location_matcher::{Erc20PalletMatcher, ForeignAssetMatcher, SingleAddressMatcher}, + AccountIdAssetIdConversion, +}; use pallet_evm_precompile_author_mapping::AuthorMappingPrecompile; use pallet_evm_precompile_balances_erc20::{Erc20BalancesPrecompile, Erc20Metadata}; use pallet_evm_precompile_batch::BatchPrecompile; @@ -45,6 +49,7 @@ use pallet_evm_precompile_relay_encoder::RelayEncoderPrecompile; use pallet_evm_precompile_relay_verifier::RelayDataVerifierPrecompile; use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; +use pallet_evm_precompile_xcm::PalletXcmPrecompile; use pallet_evm_precompile_xcm_transactor::{ v1::XcmTransactorPrecompileV1, v2::XcmTransactorPrecompileV2, v3::XcmTransactorPrecompileV3, }; @@ -54,6 +59,7 @@ use pallet_evm_precompileset_assets_erc20::Erc20AssetsPrecompileSet; use pallet_precompile_benchmarks::WeightInfo; use precompile_utils::precompile_set::*; use sp_std::prelude::*; +use xcm_primitives::AsAssetType; parameter_types! { pub P256VerifyWeight: frame_support::weights::Weight = @@ -93,6 +99,9 @@ pub const FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; /// to Erc20AssetsPrecompileSet being marked as local pub const LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8, 255u8, 255u8, 254u8]; +/// Const to identify ERC20_BALANCES_PRECOMPILE address +pub const ERC20_BALANCES_PRECOMPILE: u64 = 2050; + parameter_types! { pub ForeignAssetPrefix: &'static [u8] = FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX; pub LocalAssetPrefix: &'static [u8] = LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX; @@ -100,6 +109,19 @@ parameter_types! { type EthereumPrecompilesChecks = (AcceptDelegateCall, CallableByContract, CallableByPrecompile); +// Pallet-xcm precompile types. +// Type that converts AssetId into Location +type AssetIdToLocationManager = AsAssetType; + +// The pallet-balances address is identified by ERC20_BALANCES_PRECOMPILE const +type SingleAddressMatch = SingleAddressMatcher; + +// Type that matches an AccountId with a foreign asset address (if any) +type ForeignAssetMatch = ForeignAssetMatcher; + +// Erc20XcmBridge pallet is used to match ERC20s +type Erc20Match = Erc20PalletMatcher; + #[precompile_utils::precompile_name_from_address] type MoonbeamPrecompilesAt = ( // Ethereum precompiles: @@ -249,6 +271,11 @@ type MoonbeamPrecompilesAt = ( RelayDataVerifierPrecompile, (CallableByContract, CallableByPrecompile), >, + PrecompileAt< + AddressU64<2074>, + PalletXcmPrecompile, + (CallableByContract, CallableByPrecompile), + >, ); pub struct DisabledLocalAssets(sp_std::marker::PhantomData); diff --git a/runtime/moonbeam/tests/integration_test.rs b/runtime/moonbeam/tests/integration_test.rs index 01f40b6990..10176af701 100644 --- a/runtime/moonbeam/tests/integration_test.rs +++ b/runtime/moonbeam/tests/integration_test.rs @@ -2455,7 +2455,7 @@ fn precompile_existence() { let precompile_addresses: std::collections::BTreeSet<_> = vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 256, 1024, 1025, 1026, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, - 2068, 2069, 2070, 2071, 2072, 2073, + 2068, 2069, 2070, 2071, 2072, 2073, 2074, ] .into_iter() .map(H160::from_low_u64_be) diff --git a/runtime/moonriver/Cargo.toml b/runtime/moonriver/Cargo.toml index bfdfdb853e..668d644cac 100644 --- a/runtime/moonriver/Cargo.toml +++ b/runtime/moonriver/Cargo.toml @@ -173,6 +173,7 @@ nimbus-primitives = { workspace = true } pallet-async-backing = { workspace = true } pallet-author-inherent = { workspace = true } pallet-author-slot-filter = { workspace = true } +pallet-evm-precompile-xcm = { workspace = true } pallet-relay-storage-roots = { workspace = true } # Benchmarking @@ -258,6 +259,7 @@ std = [ "pallet-evm-precompile-referenda/std", "pallet-evm-precompile-relay-encoder/std", "pallet-evm-precompile-relay-verifier/std", + "pallet-evm-precompile-xcm/std", "pallet-evm-precompile-xcm-transactor/std", "pallet-evm-precompile-xcm-utils/std", "pallet-evm-precompile-xtokens/std", diff --git a/runtime/moonriver/src/lib.rs b/runtime/moonriver/src/lib.rs index fb5733e1d8..3a7c0ffd6c 100644 --- a/runtime/moonriver/src/lib.rs +++ b/runtime/moonriver/src/lib.rs @@ -1213,6 +1213,7 @@ impl Contains for NormalFilter { // is populated at genesis RuntimeCall::PolkadotXcm(method) => match method { pallet_xcm::Call::force_default_xcm_version { .. } => true, + pallet_xcm::Call::transfer_assets_using_type_and_then { .. } => true, _ => false, }, // We filter anonymous proxy as they make "reserve" inconsistent diff --git a/runtime/moonriver/src/precompiles.rs b/runtime/moonriver/src/precompiles.rs index a7106e4ac0..2349fa5b26 100644 --- a/runtime/moonriver/src/precompiles.rs +++ b/runtime/moonriver/src/precompiles.rs @@ -15,11 +15,16 @@ // along with Moonbeam. If not, see . use crate::{ - asset_config::ForeignAssetInstance, xcm_config::XcmExecutorConfig, OpenTechCommitteeInstance, - Runtime, TreasuryCouncilInstance, + asset_config::ForeignAssetInstance, + xcm_config::{AssetType, XcmExecutorConfig}, + AccountId, AssetId, AssetManager, Balances, Erc20XcmBridge, OpenTechCommitteeInstance, Runtime, + TreasuryCouncilInstance, }; use frame_support::parameter_types; use moonbeam_runtime_common::weights as moonriver_weights; +use moonkit_xcm_primitives::location_matcher::{ + Erc20PalletMatcher, ForeignAssetMatcher, SingleAddressMatcher, +}; use pallet_evm_precompile_author_mapping::AuthorMappingPrecompile; use pallet_evm_precompile_balances_erc20::{Erc20BalancesPrecompile, Erc20Metadata}; use pallet_evm_precompile_batch::BatchPrecompile; @@ -43,6 +48,7 @@ use pallet_evm_precompile_relay_encoder::RelayEncoderPrecompile; use pallet_evm_precompile_relay_verifier::RelayDataVerifierPrecompile; use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; +use pallet_evm_precompile_xcm::PalletXcmPrecompile; use pallet_evm_precompile_xcm_transactor::{ v1::XcmTransactorPrecompileV1, v2::XcmTransactorPrecompileV2, v3::XcmTransactorPrecompileV3, }; @@ -51,6 +57,7 @@ use pallet_evm_precompile_xtokens::XtokensPrecompile; use pallet_evm_precompileset_assets_erc20::Erc20AssetsPrecompileSet; use pallet_precompile_benchmarks::WeightInfo; use precompile_utils::precompile_set::*; +use xcm_primitives::AsAssetType; parameter_types! { pub P256VerifyWeight: frame_support::weights::Weight = @@ -87,12 +94,28 @@ impl Erc20Metadata for NativeErc20Metadata { /// to Erc20AssetsPrecompileSet being marked as foreign pub const FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; +/// Const to identify ERC20_BALANCES_PRECOMPILE address +pub const ERC20_BALANCES_PRECOMPILE: u64 = 2050; + parameter_types! { pub ForeignAssetPrefix: &'static [u8] = FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX; } type EthereumPrecompilesChecks = (AcceptDelegateCall, CallableByContract, CallableByPrecompile); +// Pallet-xcm precompile types. +// Type that converts AssetId into Location +type AssetIdToLocationManager = AsAssetType; + +// The pallet-balances address is identified by ERC20_BALANCES_PRECOMPILE const +type SingleAddressMatch = SingleAddressMatcher; + +// Type that matches an AccountId with a foreign asset address (if any) +type ForeignAssetMatch = ForeignAssetMatcher; + +// Erc20XcmBridge pallet is used to match ERC20s +type Erc20Match = Erc20PalletMatcher; + #[precompile_utils::precompile_name_from_address] type MoonriverPrecompilesAt = ( // Ethereum precompiles: @@ -242,6 +265,11 @@ type MoonriverPrecompilesAt = ( RelayDataVerifierPrecompile, (CallableByContract, CallableByPrecompile), >, + PrecompileAt< + AddressU64<2074>, + PalletXcmPrecompile, + (CallableByContract, CallableByPrecompile), + >, ); /// The PrecompileSet installed in the Moonriver runtime. diff --git a/runtime/moonriver/tests/integration_test.rs b/runtime/moonriver/tests/integration_test.rs index 7fc32dc06f..5b596b0ae7 100644 --- a/runtime/moonriver/tests/integration_test.rs +++ b/runtime/moonriver/tests/integration_test.rs @@ -2367,7 +2367,7 @@ fn precompile_existence() { let precompile_addresses: std::collections::BTreeSet<_> = vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 256, 1024, 1025, 1026, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, - 2068, 2069, 2070, 2071, 2072, 2073, + 2068, 2069, 2070, 2071, 2072, 2073, 2074, ] .into_iter() .map(H160::from_low_u64_be) diff --git a/test/contracts/src/XcmInterface.sol b/test/contracts/src/XcmInterface.sol index f05c771008..97eca04fe9 100644 --- a/test/contracts/src/XcmInterface.sol +++ b/test/contracts/src/XcmInterface.sol @@ -35,68 +35,139 @@ interface XCM { uint256 amount; } + // The values start at `0` and are represented as `uint8` + enum TransferType { + Teleport, + LocalReserve, + DestinationReserve + } + /// @dev Function to send assets via XCM using transfer_assets() pallet-xcm extrinsic. - /// @custom:selector 59df8416 + /// @custom:selector 9ea8ada7 /// @param dest The destination chain. /// @param beneficiary The actual account that will receive the tokens on dest. - /// @param assets The combination (array) of assets to send. + /// @param assets The combination (array) of assets to send in Location format. /// @param feeAssetItem The index of the asset that will be used to pay for fees. - /// @param weight The weight to be used for the whole XCM operation. - /// (uint64::MAX in refTime means Unlimited weight) function transferAssetsLocation( Location memory dest, Location memory beneficiary, AssetLocationInfo[] memory assets, - uint32 feeAssetItem, - Weight memory weight + uint32 feeAssetItem ) external; /// @dev Function to send assets via XCM to a 20 byte-like parachain /// using transfer_assets() pallet-xcm extrinsic. - /// @custom:selector b489262e + /// @custom:selector a0aeb5fe /// @param paraId The para-id of the destination chain. /// @param beneficiary The actual account that will receive the tokens on paraId destination. - /// @param assets The combination (array) of assets to send. + /// @param assets The combination (array) of assets to send in Address format. /// @param feeAssetItem The index of the asset that will be used to pay for fees. - /// @param weight The weight to be used for the whole XCM operation. - /// (uint64::MAX in refTime means Unlimited weight) function transferAssetsToPara20( uint32 paraId, address beneficiary, AssetAddressInfo[] memory assets, - uint32 feeAssetItem, - Weight memory weight + uint32 feeAssetItem ) external; /// @dev Function to send assets via XCM to a 32 byte-like parachain /// using transfer_assets() pallet-xcm extrinsic. - /// @custom:selector 4461e6f5 + /// @custom:selector f23032c3 /// @param paraId The para-id of the destination chain. /// @param beneficiary The actual account that will receive the tokens on paraId destination. - /// @param assets The combination (array) of assets to send. + /// @param assets The combination (array) of assets to send in Address format. /// @param feeAssetItem The index of the asset that will be used to pay for fees. - /// @param weight The weight to be used for the whole XCM operation. - /// (uint64::MAX in refTime means Unlimited weight) function transferAssetsToPara32( uint32 paraId, bytes32 beneficiary, AssetAddressInfo[] memory assets, - uint32 feeAssetItem, - Weight memory weight + uint32 feeAssetItem ) external; /// @dev Function to send assets via XCM to the relay chain /// using transfer_assets() pallet-xcm extrinsic. - /// @custom:selector d7c89659 + /// @custom:selector 6521cc2c /// @param beneficiary The actual account that will receive the tokens on the relay chain. - /// @param assets The combination (array) of assets to send. + /// @param assets The combination (array) of assets to send in Address format. /// @param feeAssetItem The index of the asset that will be used to pay for fees. - /// @param weight The weight to be used for the whole XCM operation. - /// (uint64::MAX in refTime means Unlimited weight) function transferAssetsToRelay( bytes32 beneficiary, AssetAddressInfo[] memory assets, - uint32 feeAssetItem, - Weight memory weight + uint32 feeAssetItem + ) external; + + /// @dev Function to send assets through transfer_assets_using_type_and_then() pallet-xcm + /// extrinsic. + /// Important: in this selector RemoteReserve type (for either assets or fees) is not allowed. + /// If users want to send assets and fees (in Location format) with a remote reserve, + /// they must use the selector fc19376c. + /// @custom:selector 8425d893 + /// @param dest The destination chain. + /// @param assets The combination (array) of assets to send in Location format. + /// @param assetsTransferType The TransferType corresponding to assets being sent. + /// @param remoteFeesIdIndex The index of the asset (inside assets array) to use as fees. + /// @param feesTransferType The TransferType corresponding to the asset used as fees. + /// @param customXcmOnDest The XCM message to execute on destination chain. + function transferAssetsUsingTypeAndThenLocation( + Location memory dest, + AssetLocationInfo[] memory assets, + TransferType assetsTransferType, + uint8 remoteFeesIdIndex, + TransferType feesTransferType, + bytes memory customXcmOnDest + ) external; + + /// @dev Function to send assets through transfer_assets_using_type_and_then() pallet-xcm + /// extrinsic. + /// @custom:selector fc19376c + /// @param dest The destination chain. + /// @param assets The combination (array) of assets to send in Location format. + /// @param remoteFeesIdIndex The index of the asset (inside assets array) to use as fees. + /// @param customXcmOnDest The XCM message to execute on destination chain. + /// @param remoteReserve The remote reserve corresponding for assets and fees. They MUST + /// share the same reserve. + function transferAssetsUsingTypeAndThenLocation( + Location memory dest, + AssetLocationInfo[] memory assets, + uint8 remoteFeesIdIndex, + bytes memory customXcmOnDest, + Location memory remoteReserve + ) external; + + /// @dev Function to send assets through transfer_assets_using_type_and_then() pallet-xcm + /// extrinsic. + /// Important: in this selector RemoteReserve type (for either assets or fees) is not allowed. + /// If users want to send assets and fees (in Address format) with a remote reserve, + /// they must use the selector aaecfc62. + /// @custom:selector 998093ee + /// @param dest The destination chain. + /// @param assets The combination (array) of assets to send in Address format. + /// @param assetsTransferType The TransferType corresponding to assets being sent. + /// @param remoteFeesIdIndex The index of the asset (inside assets array) to use as fees. + /// @param feesTransferType The TransferType corresponding to the asset used as fees. + /// @param customXcmOnDest The XCM message to execute on destination chain. + function transferAssetsUsingTypeAndThenAddress( + Location memory dest, + AssetAddressInfo[] memory assets, + TransferType assetsTransferType, + uint8 remoteFeesIdIndex, + TransferType feesTransferType, + bytes memory customXcmOnDest + ) external; + + /// @dev Function to send assets through transfer_assets_using_type_and_then() pallet-xcm + /// extrinsic. + /// @custom:selector aaecfc62 + /// @param dest The destination chain. + /// @param assets The combination (array) of assets to send in Address format. + /// @param remoteFeesIdIndex The index of the asset (inside assets array) to use as fees. + /// @param customXcmOnDest The XCM message to execute on destination chain. + /// @param remoteReserve The remote reserve corresponding for assets and fees. They MUST + /// share the same reserve. + function transferAssetsUsingTypeAndThenAddress( + Location memory dest, + AssetAddressInfo[] memory assets, + uint8 remoteFeesIdIndex, + bytes memory customXcmOnDest, + Location memory remoteReserve ) external; } \ No newline at end of file diff --git a/test/suites/dev/moonbase/test-precompile/test-precompile-pallet-xcm.ts b/test/suites/dev/moonbase/test-precompile/test-precompile-pallet-xcm.ts index a25642d9dc..2cd1fcb249 100644 --- a/test/suites/dev/moonbase/test-precompile/test-precompile-pallet-xcm.ts +++ b/test/suites/dev/moonbase/test-precompile/test-precompile-pallet-xcm.ts @@ -2,6 +2,7 @@ import "@moonbeam-network/api-augment"; import { beforeAll, describeSuite, fetchCompiledContract, expect } from "@moonwall/cli"; import { ALITH_ADDRESS, BALTATHAR_ADDRESS, alith, createEthersTransaction } from "@moonwall/util"; import { u128 } from "@polkadot/types-codec"; +import { numberToHex } from "@polkadot/util"; import { PalletAssetsAssetAccount, PalletAssetsAssetDetails } from "@polkadot/types/lookup"; import { encodeFunctionData } from "viem"; import { expectEVMResult, mockOldAssetBalance } from "../../../../helpers"; @@ -74,7 +75,7 @@ describeSuite({ to: PRECOMPILE_PALLET_XCM_ADDRESS, data: encodeFunctionData({ abi: xcmInterface, - args: [dest, beneficiary, assetLocationInfo, 0, weight], + args: [dest, beneficiary, assetLocationInfo, 0], functionName: "transferAssetsLocation", }), gasLimit: 500_000n, @@ -110,7 +111,7 @@ describeSuite({ to: PRECOMPILE_PALLET_XCM_ADDRESS, data: encodeFunctionData({ abi: xcmInterface, - args: [paraId, BALTATHAR_ADDRESS, assetAddressInfo, 0, weight], + args: [paraId, BALTATHAR_ADDRESS, assetAddressInfo, 0], functionName: "transferAssetsToPara20", }), gasLimit: 500_000n, @@ -147,7 +148,7 @@ describeSuite({ to: PRECOMPILE_PALLET_XCM_ADDRESS, data: encodeFunctionData({ abi: xcmInterface, - args: [paraId, beneficiaryAddress, assetAddressInfo, 0, weight], + args: [paraId, beneficiaryAddress, assetAddressInfo, 0], functionName: "transferAssetsToPara32", }), gasLimit: 500_000n, @@ -183,7 +184,7 @@ describeSuite({ to: PRECOMPILE_PALLET_XCM_ADDRESS, data: encodeFunctionData({ abi: xcmInterface, - args: [beneficiaryAddress, assetAddressInfo, 0, weight], + args: [beneficiaryAddress, assetAddressInfo, 0], functionName: "transferAssetsToRelay", }), gasLimit: 500_000n, @@ -200,5 +201,219 @@ describeSuite({ expect(assetBalanceAfter).to.equal(assetBalanceBefore - amountToSend); }, }); + + it({ + id: "T05", + title: "allows to call transferAssetsUsingTypeAndThenLocation::8425d893 selector", + test: async function () { + const { abi: xcmInterface } = fetchCompiledContract("XCM"); + const assetBalanceBefore = ( + await context.polkadotJs().query.assets.account(assetId.toU8a(), ALITH_ADDRESS) + ) + .unwrap() + .balance.toBigInt(); + + const dest: [number, any[]] = [1, []]; + const assetLocation: [number, any[]] = [1, []]; + const assetLocationInfo = [[assetLocation, amountToSend]]; + + // DestinationReserve + const assetsAndFeesTransferType = 2; + + const message = { + V3: [ + { + ClearOrigin: null, + }, + ], + }; + const xcmOnDest = context.polkadotJs().createType("XcmVersionedXcm", message); + + const rawTxn = await createEthersTransaction(context, { + to: PRECOMPILE_PALLET_XCM_ADDRESS, + data: encodeFunctionData({ + abi: xcmInterface, + args: [ + dest, + assetLocationInfo, + assetsAndFeesTransferType, + 0n, + assetsAndFeesTransferType, + xcmOnDest.toHex(), + ], + functionName: "transferAssetsUsingTypeAndThenLocation", + }), + gasLimit: 500_000n, + }); + + const result = await context.createBlock(rawTxn); + expectEVMResult(result.result!.events, "Succeed"); + + const assetBalanceAfter = ( + await context.polkadotJs().query.assets.account(assetId.toU8a(), ALITH_ADDRESS) + ) + .unwrap() + .balance.toBigInt(); + expect(assetBalanceAfter).to.equal(assetBalanceBefore - amountToSend); + }, + }); + + it({ + id: "T06", + title: "allows to call transferAssetsUsingTypeAndThenLocation::fc19376c selector", + test: async function () { + const { abi: xcmInterface } = fetchCompiledContract("XCM"); + const assetBalanceBefore = ( + await context.polkadotJs().query.assets.account(assetId.toU8a(), ALITH_ADDRESS) + ) + .unwrap() + .balance.toBigInt(); + + const paraIdInHex = numberToHex(2000, 32); + const parachain_enum_selector = "0x00"; + + // This represents X2(Parent, Parachain(2000)) + const dest: [number, any[]] = [1, [parachain_enum_selector + paraIdInHex.slice(2)]]; + + const remoteReserve: [number, any[]] = [1, []]; + const assetLocation: [number, any[]] = [1, []]; + const assetLocationInfo = [[assetLocation, amountToSend]]; + + const message = { + V3: [ + { + ClearOrigin: null, + }, + ], + }; + const xcmOnDest = context.polkadotJs().createType("XcmVersionedXcm", message); + + const rawTxn = await createEthersTransaction(context, { + to: PRECOMPILE_PALLET_XCM_ADDRESS, + data: encodeFunctionData({ + abi: xcmInterface, + args: [dest, assetLocationInfo, 0n, xcmOnDest.toHex(), remoteReserve], + functionName: "transferAssetsUsingTypeAndThenLocation", + }), + gasLimit: 500_000n, + }); + + const result = await context.createBlock(rawTxn); + expectEVMResult(result.result!.events, "Succeed"); + + const assetBalanceAfter = ( + await context.polkadotJs().query.assets.account(assetId.toU8a(), ALITH_ADDRESS) + ) + .unwrap() + .balance.toBigInt(); + expect(assetBalanceAfter).to.equal(assetBalanceBefore - amountToSend); + }, + }); + + it({ + id: "T07", + title: "allows to call transferAssetsUsingTypeAndThenAddress::998093ee selector", + test: async function () { + const { abi: xcmInterface } = fetchCompiledContract("XCM"); + const assetBalanceBefore = ( + await context.polkadotJs().query.assets.account(assetId.toU8a(), ALITH_ADDRESS) + ) + .unwrap() + .balance.toBigInt(); + + // Relay as destination + const dest: [number, any[]] = [1, []]; + const assetAddressInfo = [[ADDRESS_ERC20, amountToSend]]; + + // DestinationReserve + const assetsAndFeesTransferType = 2; + + const message = { + V3: [ + { + ClearOrigin: null, + }, + ], + }; + const xcmOnDest = context.polkadotJs().createType("XcmVersionedXcm", message); + + const rawTxn = await createEthersTransaction(context, { + to: PRECOMPILE_PALLET_XCM_ADDRESS, + data: encodeFunctionData({ + abi: xcmInterface, + args: [ + dest, + assetAddressInfo, + assetsAndFeesTransferType, + 0n, + assetsAndFeesTransferType, + xcmOnDest.toHex(), + ], + functionName: "transferAssetsUsingTypeAndThenAddress", + }), + gasLimit: 500_000n, + }); + + const result = await context.createBlock(rawTxn); + expectEVMResult(result.result!.events, "Succeed"); + + const assetBalanceAfter = ( + await context.polkadotJs().query.assets.account(assetId.toU8a(), ALITH_ADDRESS) + ) + .unwrap() + .balance.toBigInt(); + expect(assetBalanceAfter).to.equal(assetBalanceBefore - amountToSend); + }, + }); + + it({ + id: "T08", + title: "allows to call transferAssetsUsingTypeAndThenAddress::aaecfc62 selector", + test: async function () { + const { abi: xcmInterface } = fetchCompiledContract("XCM"); + const assetBalanceBefore = ( + await context.polkadotJs().query.assets.account(assetId.toU8a(), ALITH_ADDRESS) + ) + .unwrap() + .balance.toBigInt(); + + const paraIdInHex = numberToHex(2000, 32); + const parachain_enum_selector = "0x00"; + + // This represents X2(Parent, Parachain(2000)) + const dest: [number, any[]] = [1, [parachain_enum_selector + paraIdInHex.slice(2)]]; + const assetAddressInfo = [[ADDRESS_ERC20, amountToSend]]; + const remoteReserve: [number, any[]] = [1, []]; + + const message = { + V3: [ + { + ClearOrigin: null, + }, + ], + }; + const xcmOnDest = context.polkadotJs().createType("XcmVersionedXcm", message); + + const rawTxn = await createEthersTransaction(context, { + to: PRECOMPILE_PALLET_XCM_ADDRESS, + data: encodeFunctionData({ + abi: xcmInterface, + args: [dest, assetAddressInfo, 0n, xcmOnDest.toHex(), remoteReserve], + functionName: "transferAssetsUsingTypeAndThenAddress", + }), + gasLimit: 500_000n, + }); + + const result = await context.createBlock(rawTxn); + expectEVMResult(result.result!.events, "Succeed"); + + const assetBalanceAfter = ( + await context.polkadotJs().query.assets.account(assetId.toU8a(), ALITH_ADDRESS) + ) + .unwrap() + .balance.toBigInt(); + expect(assetBalanceAfter).to.equal(assetBalanceBefore - amountToSend); + }, + }); }, });