Skip to content

Commit

Permalink
Enable Xcm->Evm and Erc20Xcm on Moonriver & Moonbeam (#2318)
Browse files Browse the repository at this point in the history
* update to v0.9.40

* update benchmarking weight template

* fix build

* make test compile

* Includes page heap fixes

* compile runtime-benchmarks

* make warp sync work

* toml sort

* fix editorconfig

* use new substrate version

* fix warp sync

* sort

* fix --dev

* remove duplicate SetMembersOrigin

* toml-sort

* remove kitchensink-runtime

* fix builkd

* use new weights

* set manual weights for xcm fungible

* use Weight::from_parts

* use 0 pov_size for ref_time weight

* update nimbus

* exclude generated weight files from editorconfig

* fmt

* fmt

* fix rust tests

* fix import

* fix tests

* use Weight part pov_size to 0

* make dalek test work

* fix transfer tests

* use BoundedVec for auto compound delegations

* fix modexp test

* fix modexp test

* fix tests

* fix weight tests

* fix staking tests via chunking

* fix modexp test

* fix lint and test

* fix rust weight tests

* fix partial ts tests

* temp fix for xcm v2

* Fixes weight until benchmarking is fixed

* set manual weight, fix ts tests

* Adds temp hack for xcm tests

* Use RefundSurplus as the no-op for saturating the queue, which does not have pov

* Update evm to 0.39

* Revert "Update evm to 0.39"

This reverts commit 882b85e.

* upgrade polkadot for better support of xcm v2

* prettier

* prettier

* Revert temp fix for XCM weight

* upgrade polkadot fork

* Fixing hrmp-mock tests

* clean up

* update polkadot fork to expose ForeignChainAliasAccount

* Generate remote accounts according to polkadot standards

* prettier

* fix rust test

* ts tests first pass

* add xcm-evm and erc20-xcm on moonriver

* adapt rust tests

* add xcm-evm and erc20-xcm on moonbeam

---------

Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com>
Co-authored-by: crystalin <alan.sapede@gmail.com>
Co-authored-by: girazoki <gorka.irazoki@gmail.com>
Co-authored-by: tgmichel <telmo@purestake.com>
  • Loading branch information
5 people authored Jun 6, 2023
1 parent 39c54e8 commit a294944
Show file tree
Hide file tree
Showing 19 changed files with 1,628 additions and 176 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pallets/erc20-xcm-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ pub mod pallet {
Erc20Matcher::<T::Erc20MultilocationPrefix>::is_erc20_asset(asset)
}
pub fn weight_of_erc20_transfer() -> Weight {
let gas_limit = T::Erc20TransferGasLimit::get();
Weight::from_parts(
T::Erc20TransferGasLimit::get().saturating_mul(T::WeightPerGas::get().ref_time()),
0,
gas_limit / 4, // TODO: apply gas/proof_size ratio
)
}
fn erc20_transfer(
Expand Down
5 changes: 5 additions & 0 deletions runtime/moonbeam/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ moonbeam-xcm-benchmarks = { workspace = true }
pallet-asset-manager = { workspace = true }
pallet-author-mapping = { workspace = true }
pallet-crowdloan-rewards = { workspace = true }
pallet-erc20-xcm-bridge = { workspace = true }
pallet-ethereum-chain-id = { workspace = true }
pallet-ethereum-xcm = { workspace = true }
pallet-maintenance-mode = { workspace = true, features = [ "xcm-support" ] }
pallet-migrations = { workspace = true }
pallet-moonbeam-orbiters = { workspace = true }
Expand Down Expand Up @@ -206,7 +208,9 @@ std = [
"pallet-conviction-voting/std",
"pallet-crowdloan-rewards/std",
"pallet-democracy/std",
"pallet-erc20-xcm-bridge/std",
"pallet-ethereum-chain-id/std",
"pallet-ethereum-xcm/std",
"pallet-ethereum/std",
"pallet-evm-precompile-author-mapping/std",
"pallet-evm-precompile-balances-erc20/std",
Expand Down Expand Up @@ -297,6 +301,7 @@ runtime-benchmarks = [
"pallet-conviction-voting/runtime-benchmarks",
"pallet-crowdloan-rewards/runtime-benchmarks",
"pallet-ethereum/runtime-benchmarks",
"pallet-ethereum-xcm/runtime-benchmarks",
"pallet-migrations/runtime-benchmarks",
"pallet-moonbeam-orbiters/runtime-benchmarks",
"pallet-parachain-staking/runtime-benchmarks",
Expand Down
33 changes: 32 additions & 1 deletion runtime/moonbeam/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub use frame_support::traits::Get;
use frame_support::{
construct_runtime,
dispatch::{DispatchClass, GetDispatchInfo},
ensure,
pallet_prelude::DispatchResult,
parameter_types,
traits::{
Expand Down Expand Up @@ -79,7 +80,7 @@ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{
BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, IdentityLookup,
PostDispatchInfoOf, UniqueSaturatedInto,
PostDispatchInfoOf, UniqueSaturatedInto, Zero,
},
transaction_validity::{
InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
Expand Down Expand Up @@ -620,6 +621,32 @@ impl cumulus_pallet_parachain_system::Config for Runtime {
type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
}

pub struct EthereumXcmEnsureProxy;
impl xcm_primitives::EnsureProxy<AccountId> for EthereumXcmEnsureProxy {
fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> {
// The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies
let def: pallet_proxy::ProxyDefinition<AccountId, ProxyType, BlockNumber> =
pallet_proxy::Pallet::<Runtime>::find_proxy(
&delegator,
&delegatee,
Some(ProxyType::Any),
)
.map_err(|_| "proxy error: expected `ProxyType::Any`")?;
// We only allow to use it for delay zero proxies, as the call will immediatly be executed
ensure!(def.delay.is_zero(), "proxy delay is Non-zero`");
Ok(())
}
}

impl pallet_ethereum_xcm::Config for Runtime {
type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper;
type ValidatedTransaction = pallet_ethereum::ValidatedTransaction<Self>;
type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction;
type ReservedXcmpWeight = ReservedXcmpWeight;
type EnsureProxy = EthereumXcmEnsureProxy;
type ControllerOrigin = EnsureRoot<AccountId>;
}

parameter_types! {
pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
Expand Down Expand Up @@ -999,6 +1026,7 @@ impl Contains<RuntimeCall> for MaintenanceFilter {
RuntimeCall::PolkadotXcm(_) => false,
RuntimeCall::Treasury(_) => false,
RuntimeCall::XcmTransactor(_) => false,
RuntimeCall::EthereumXcm(_) => false,
_ => true,
}
}
Expand Down Expand Up @@ -1343,6 +1371,9 @@ construct_runtime! {
XTokens: orml_xtokens::{Pallet, Call, Storage, Event<T>} = 106,
XcmTransactor: pallet_xcm_transactor::{Pallet, Call, Storage, Event<T>} = 107,
LocalAssets: pallet_assets::<Instance1>::{Pallet, Call, Storage, Event<T>} = 108,
EthereumXcm: pallet_ethereum_xcm::{Pallet, Call, Storage, Origin} = 109,
Erc20XcmBridge: pallet_erc20_xcm_bridge::{Pallet} = 110,


// Randomness
Randomness: pallet_randomness::{Pallet, Call, Storage, Event<T>, Inherent} = 120,
Expand Down
82 changes: 69 additions & 13 deletions runtime/moonbeam/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,36 @@

use super::{
governance, AccountId, AssetId, AssetManager, Assets, Balance, Balances, DealWithFees,
LocalAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
RuntimeOrigin, Treasury, XcmpQueue, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX,
Erc20XcmBridge, LocalAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall,
RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX,
};

use pallet_evm_precompileset_assets_erc20::AccountIdAssetIdConversion;
use sp_runtime::traits::Hash as THash;
use sp_runtime::{
traits::{Hash as THash, PostDispatchInfoOf},
DispatchErrorWithPostInfo,
};

use frame_support::{
dispatch::Weight,
parameter_types,
traits::{EitherOfDiverse, Everything, Nothing, PalletInfoAccess},
};

use frame_system::EnsureRoot;
use frame_system::{EnsureRoot, RawOrigin};
use sp_core::{ConstU32, H160, H256};

use xcm_builder::{
AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId,
CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter,
NoChecking, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation,
TakeWeightCredit, UsingComponents,
CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FungiblesAdapter, NoChecking,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,
WeightInfoBounds,
};

use xcm::latest::prelude::*;
use xcm_executor::traits::JustTry;
use xcm_executor::traits::{CallDispatcher, JustTry};

use orml_xcm_support::MultiNativeAsset;
use xcm_primitives::{
Expand Down Expand Up @@ -104,8 +107,21 @@ pub type LocationToAccountId = (
SiblingParachainConvertsVia<polkadot_parachain::primitives::Sibling, AccountId>,
// If we receive a MultiLocation of type AccountKey20, just generate a native account
AccountKey20Aliases<RelayNetwork, AccountId>,
// Generate remote accounts according to polkadot standards
xcm_builder::ForeignChainAliasAccount<AccountId>,
);

/// Wrapper type around `LocationToAccountId` to convert an `AccountId` to type `H160`.
pub struct LocationToH160;
impl xcm_executor::traits::Convert<MultiLocation, H160> for LocationToH160 {
fn convert(location: MultiLocation) -> Result<H160, MultiLocation> {
<LocationToAccountId as xcm_executor::traits::Convert<MultiLocation, AccountId>>::convert(
location,
)
.map(Into::into)
}
}

// The non-reserve fungible transactor type
// It will use pallet-assets, and the Id will be matched against AsAssetType
pub type ForeignFungiblesTransactor = FungiblesAdapter<
Expand Down Expand Up @@ -207,11 +223,16 @@ parameter_types! {
}

/// Xcm Weigher shared between multiple Xcm-related configs.
pub type XcmWeigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
pub type XcmWeigher = WeightInfoBounds<
moonbeam_xcm_benchmarks::weights::XcmWeight<Runtime, RuntimeCall>,
RuntimeCall,
MaxInstructions,
>;

// Allow paid executions
pub type XcmBarrier = (
TakeWeightCredit,
xcm_primitives::AllowTopLevelPaidExecutionDescendOriginFirst<Everything>,
AllowTopLevelPaidExecutionFrom<Everything>,
// Expected responses are OK.
AllowKnownQueryResponses<PolkadotXcm>,
Expand Down Expand Up @@ -254,6 +275,15 @@ parameter_types! {
pub const MaxAssetsIntoHolding: u32 = xcm_primitives::MAX_ASSETS;
}

// Our implementation of the Moonbeam Call
// Attachs the right origin in case the call is made to pallet-ethereum-xcm
#[cfg(not(feature = "evm-tracing"))]
moonbeam_runtime_common::impl_moonbeam_xcm_call!();
#[cfg(feature = "evm-tracing")]
moonbeam_runtime_common::impl_moonbeam_xcm_call_tracing!();

moonbeam_runtime_common::impl_evm_runner_precompile_or_eth_xcm!();

pub struct XcmExecutorConfig;
impl xcm_executor::Config for XcmExecutorConfig {
type RuntimeCall = RuntimeCall;
Expand Down Expand Up @@ -286,9 +316,9 @@ impl xcm_executor::Config for XcmExecutorConfig {
);
type ResponseHandler = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetTrap = pallet_erc20_xcm_bridge::AssetTrapWrapper<PolkadotXcm, Runtime>;
type AssetClaims = PolkadotXcm;
type CallDispatcher = RuntimeCall;
type CallDispatcher = MoonbeamCall;
type PalletInstancesInfo = crate::AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type AssetLocker = ();
Expand All @@ -300,7 +330,10 @@ impl xcm_executor::Config for XcmExecutorConfig {
type AssetIsBurnable = Everything;
}

type XcmExecutor = xcm_executor::XcmExecutor<XcmExecutorConfig>;
type XcmExecutor = pallet_erc20_xcm_bridge::XcmExecutorWrapper<
RuntimeCall,
xcm_executor::XcmExecutor<XcmExecutorConfig>,
>;

// Converts a Signed Local Origin into a MultiLocation
pub type LocalOriginToLocation = SignedToAccountId20<RuntimeOrigin, AccountId, RelayNetwork>;
Expand Down Expand Up @@ -574,6 +607,29 @@ impl pallet_xcm_transactor::Config for Runtime {
type HrmpEncoder = moonbeam_relay_encoder::polkadot::PolkadotEncoder;
}

parameter_types! {
// This is the relative view of erc20 assets.
// Identified by this prefix + AccountKey20(contractAddress)
// We use the RELATIVE multilocation
pub Erc20XcmBridgePalletLocation: MultiLocation = MultiLocation {
parents:0,
interior: Junctions::X1(
PalletInstance(<Erc20XcmBridge as PalletInfoAccess>::index() as u8)
)
};

// To be able to support almost all erc20 implementations,
// we provide a sufficiently hight gas limit.
pub Erc20XcmBridgeTransferGasLimit: u64 = 80_000;
}

impl pallet_erc20_xcm_bridge::Config for Runtime {
type AccountIdConverter = LocationToH160;
type Erc20MultilocationPrefix = Erc20XcmBridgePalletLocation;
type Erc20TransferGasLimit = Erc20XcmBridgeTransferGasLimit;
type EvmRunner = EvmRunnerPrecompileOrEthXcm<MoonbeamCall, Self>;
}

#[cfg(feature = "runtime-benchmarks")]
mod testing {
use super::*;
Expand Down
22 changes: 14 additions & 8 deletions runtime/moonbeam/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ use frame_support::{
weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
StorageHasher, Twox128,
};

use moonbeam_runtime::{
asset_config::LocalAssetInstance,
currency::GLMR,
xcm_config::{CurrencyId, SelfReserve, UnitWeightCost},
xcm_config::{CurrencyId, SelfReserve},
AccountId, Balances, CouncilCollective, CrowdloanRewards, OpenTechCommitteeCollective,
ParachainStaking, PolkadotXcm, Precompiles, Runtime, RuntimeBlockWeights, RuntimeCall,
RuntimeEvent, System, TechCommitteeCollective, TransactionPayment, TreasuryCouncilCollective,
XTokens, XcmTransactor, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX,
LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX,
};
use moonbeam_xcm_benchmarks::weights::XcmWeight;
use nimbus_primitives::NimbusId;
use pallet_evm::PrecompileSet;
use pallet_evm_precompileset_assets_erc20::{
Expand Down Expand Up @@ -2439,7 +2439,7 @@ fn xtokens_precompile_transfer() {
weight: 4_000_000,
},
)
.expect_cost(24000)
.expect_cost(57639)
.expect_no_logs()
.execute_returns(())
})
Expand Down Expand Up @@ -2491,7 +2491,7 @@ fn xtokens_precompile_transfer_multiasset() {
weight: 4_000_000,
},
)
.expect_cost(24000)
.expect_cost(57639)
.expect_no_logs()
.execute_returns(());
})
Expand Down Expand Up @@ -2824,7 +2824,7 @@ fn call_xtokens_with_fee() {
}

#[test]
fn test_xcm_utils_ml_to_account() {
fn test_xcm_utils_ml_tp_account() {
ExtBuilder::default().build().execute_with(|| {
let xcm_utils_precompile_address = H160::from_low_u64_be(2060);
let expected_address_parent: H160 =
Expand Down Expand Up @@ -2874,8 +2874,13 @@ fn test_xcm_utils_ml_to_account() {
},
),
);
let expected_address_alice_in_parachain_2000: H160 =
xcm_builder::ForeignChainAliasAccount::<AccountId>::convert_ref(
alice_in_parachain_2000_multilocation.clone(),
)
.unwrap()
.into();

// this should fail, this convertor is not allowed in moonriver
Precompiles::new()
.prepare_test(
ALICE,
Expand All @@ -2886,15 +2891,16 @@ fn test_xcm_utils_ml_to_account() {
)
.expect_cost(1000)
.expect_no_logs()
.execute_reverts(|output| output == b"multilocation: Failed multilocation conversion");
.execute_returns(Address(expected_address_alice_in_parachain_2000));
});
}

#[test]
fn test_xcm_utils_weight_message() {
ExtBuilder::default().build().execute_with(|| {
let xcm_utils_precompile_address = H160::from_low_u64_be(2060);
let expected_weight = UnitWeightCost::get().ref_time();
let expected_weight =
XcmWeight::<moonbeam_runtime::Runtime, RuntimeCall>::clear_origin().ref_time();

let message: Vec<u8> = xcm::VersionedXcm::<()>::V3(Xcm(vec![ClearOrigin])).encode();

Expand Down
4 changes: 4 additions & 0 deletions runtime/moonbeam/tests/xcm_mock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ pub fn para_b_account() -> AccountId32 {
ParaId::from(2).into_account_truncating()
}

pub fn para_a_account_20() -> parachain::AccountId {
ParaId::from(1).into_account_truncating()
}

pub fn evm_account() -> H160 {
H160::from_str("1000000000000000000000000000000000000001").unwrap()
}
Expand Down
Loading

0 comments on commit a294944

Please sign in to comment.