diff --git a/Cargo.lock b/Cargo.lock index 8b0a2668..6a5ffc83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,7 +15,7 @@ dependencies = [ [[package]] name = "account" version = "0.1.1" -source = "git+https://github.com/darwinia-network/moonbeam?branch=polkadot-v0.9.30#9d31c6120bb0f317053da9cac7fe7cd2a44f844c" +source = "git+https://github.com/darwinia-network/moonbeam.git?branch=polkadot-v0.9.30#9d31c6120bb0f317053da9cac7fe7cd2a44f844c" dependencies = [ "blake2-rfc", "hex", @@ -1361,6 +1361,7 @@ dependencies = [ "darwinia-precompile-assets", "darwinia-precompile-bls12-381", "darwinia-precompile-deposit", + "darwinia-precompile-dispatch", "darwinia-precompile-staking", "darwinia-precompile-state-storage", "darwinia-staking", @@ -1390,7 +1391,6 @@ dependencies = [ "pallet-evm", "pallet-evm-precompile-blake2", "pallet-evm-precompile-bn128", - "pallet-evm-precompile-dispatch", "pallet-evm-precompile-modexp", "pallet-evm-precompile-simple", "pallet-fee-market", @@ -2451,6 +2451,17 @@ dependencies = [ "sp-std", ] +[[package]] +name = "darwinia-precompile-dispatch" +version = "6.0.0" +dependencies = [ + "fp-evm", + "frame-support", + "pallet-evm", + "precompile-utils", + "sp-std", +] + [[package]] name = "darwinia-precompile-staking" version = "6.0.0" @@ -2517,6 +2528,7 @@ dependencies = [ "darwinia-precompile-assets", "darwinia-precompile-bls12-381", "darwinia-precompile-deposit", + "darwinia-precompile-dispatch", "darwinia-precompile-staking", "darwinia-precompile-state-storage", "darwinia-staking", @@ -2546,7 +2558,6 @@ dependencies = [ "pallet-evm", "pallet-evm-precompile-blake2", "pallet-evm-precompile-bn128", - "pallet-evm-precompile-dispatch", "pallet-evm-precompile-modexp", "pallet-evm-precompile-simple", "pallet-fee-market", @@ -6785,16 +6796,6 @@ dependencies = [ "substrate-bn", ] -[[package]] -name = "pallet-evm-precompile-dispatch" -version = "2.0.0-dev" -source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.30#1bd889c001b2a4735777160354cb57b8c17cf756" -dependencies = [ - "fp-evm", - "frame-support", - "pallet-evm", -] - [[package]] name = "pallet-evm-precompile-modexp" version = "2.0.0-dev" @@ -7455,6 +7456,7 @@ dependencies = [ "darwinia-precompile-assets", "darwinia-precompile-bls12-381", "darwinia-precompile-deposit", + "darwinia-precompile-dispatch", "darwinia-precompile-staking", "darwinia-precompile-state-storage", "darwinia-staking", @@ -7483,7 +7485,6 @@ dependencies = [ "pallet-evm", "pallet-evm-precompile-blake2", "pallet-evm-precompile-bn128", - "pallet-evm-precompile-dispatch", "pallet-evm-precompile-modexp", "pallet-evm-precompile-simple", "pallet-fee-market", @@ -9025,7 +9026,7 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "precompile-utils" version = "0.1.0" -source = "git+https://github.com/darwinia-network/moonbeam?branch=polkadot-v0.9.30#9d31c6120bb0f317053da9cac7fe7cd2a44f844c" +source = "git+https://github.com/darwinia-network/moonbeam.git?branch=polkadot-v0.9.30#9d31c6120bb0f317053da9cac7fe7cd2a44f844c" dependencies = [ "affix", "evm", @@ -9051,7 +9052,7 @@ dependencies = [ [[package]] name = "precompile-utils-macro" version = "0.1.0" -source = "git+https://github.com/darwinia-network/moonbeam?branch=polkadot-v0.9.30#9d31c6120bb0f317053da9cac7fe7cd2a44f844c" +source = "git+https://github.com/darwinia-network/moonbeam.git?branch=polkadot-v0.9.30#9d31c6120bb0f317053da9cac7fe7cd2a44f844c" dependencies = [ "case", "num_enum", @@ -13924,7 +13925,7 @@ dependencies = [ [[package]] name = "xcm-primitives" version = "0.1.0" -source = "git+https://github.com/darwinia-network/moonbeam?branch=polkadot-v0.9.30#9d31c6120bb0f317053da9cac7fe7cd2a44f844c" +source = "git+https://github.com/darwinia-network/moonbeam.git?branch=polkadot-v0.9.30#9d31c6120bb0f317053da9cac7fe7cd2a44f844c" dependencies = [ "ethereum", "ethereum-types", diff --git a/precompile/dispatch/Cargo.toml b/precompile/dispatch/Cargo.toml new file mode 100644 index 00000000..1b9d9e0a --- /dev/null +++ b/precompile/dispatch/Cargo.toml @@ -0,0 +1,37 @@ +[package] +authors = ["Darwinia Network "] +description = "Call dispatch precompile for EVM pallet." +edition = "2021" +homepage = "https://darwinia.network" +license = "GPL-3.0" +name = "darwinia-precompile-dispatch" +readme = "README.md" +repository = "https://github.com/darwinia-network/darwinia" +version = "6.0.0" + +[dependencies] +# frontier +fp-evm = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } + +# moonbeam +precompile-utils = { default-features = false, git = "https://github.com/darwinia-network/moonbeam.git", branch = "polkadot-v0.9.30" } + +# substrate +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } + +[features] +default = ["std"] +std = [ + # frontier + "fp-evm/std", + "pallet-evm/std", + + # moonbeam + "precompile-utils/std", + + # substrate + "frame-support/std", + "sp-std/std", +] diff --git a/precompile/dispatch/src/lib.rs b/precompile/dispatch/src/lib.rs new file mode 100644 index 00000000..695f7fcd --- /dev/null +++ b/precompile/dispatch/src/lib.rs @@ -0,0 +1,93 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2023 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia 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. +// +// Darwinia 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. +// +// You should have received a copy of the GNU General Public License +// along with Darwinia. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; + +// std +use alloc::format; +use core::marker::PhantomData; +// frontier +use fp_evm::{ExitError, PrecompileFailure}; +// moonbeam +use frame_support::{ + codec::{Decode, DecodeLimit as _}, + dispatch::{DispatchClass, Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo}, + traits::{ConstU32, Get}, +}; +use pallet_evm::{AddressMapping, GasWeightMapping}; +use precompile_utils::prelude::*; + +// `DecodeLimit` specifies the max depth a call can use when decoding, as unbounded depth +// can be used to overflow the stack. +// Default value is 8, which is the same as in XCM call decoding. +pub struct Dispatch> { + _marker: PhantomData<(T, DecodeLimit)>, +} + +#[precompile_utils::precompile] +impl Dispatch +where + T: pallet_evm::Config, + T::RuntimeCall: Dispatchable + GetDispatchInfo + Decode, + ::RuntimeOrigin: From>, + DecodeLimit: Get, +{ + #[precompile::public("execute(bytes)")] + fn execute( + handle: &mut impl PrecompileHandle, + encoded_call: UnboundedBytes, + ) -> EvmResult { + let target_gas = handle.gas_limit(); + let context = handle.context(); + + let call = T::RuntimeCall::decode_with_depth_limit( + DecodeLimit::get(), + &mut encoded_call.as_bytes(), + ) + .map_err(|_| revert("decode failed"))?; + let info = call.get_dispatch_info(); + + let valid_call = info.pays_fee == Pays::Yes && info.class == DispatchClass::Normal; + if !valid_call { + return Err(revert("invalid call")); + } + + if let Some(gas) = target_gas { + let valid_weight = + info.weight.ref_time() <= T::GasWeightMapping::gas_to_weight(gas, false).ref_time(); + if !valid_weight { + return Err(PrecompileFailure::Error { exit_status: ExitError::OutOfGas }); + } + } + + let origin = T::AddressMapping::into_account_id(context.caller); + match call.dispatch(Some(origin).into()) { + Ok(post_info) => { + let cost = T::GasWeightMapping::weight_to_gas( + post_info.actual_weight.unwrap_or(info.weight), + ); + + handle.record_cost(cost)?; + Ok(true) + }, + Err(e) => Err(revert(format!("dispatch failed: {}", <&'static str>::from(e)))), + } + } +} diff --git a/precompile/state-storage/Cargo.toml b/precompile/state-storage/Cargo.toml index 45d396d9..5c9d35e5 100644 --- a/precompile/state-storage/Cargo.toml +++ b/precompile/state-storage/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Darwinia Network "] -description = "State storage precompiles for EVM pallet." +description = "State storage precompile for EVM pallet." edition = "2021" homepage = "https://darwinia.network" license = "GPL-3.0" diff --git a/runtime/crab/Cargo.toml b/runtime/crab/Cargo.toml index 40359685..3901f1ee 100644 --- a/runtime/crab/Cargo.toml +++ b/runtime/crab/Cargo.toml @@ -41,6 +41,7 @@ darwinia-message-transact = { default-features = false, path = "../../pa darwinia-precompile-assets = { default-features = false, path = "../../precompile/assets" } darwinia-precompile-bls12-381 = { default-features = false, path = "../../precompile/bls12-381" } darwinia-precompile-deposit = { default-features = false, path = "../../precompile/deposit" } +darwinia-precompile-dispatch = { default-features = false, path = "../../precompile/dispatch" } darwinia-precompile-staking = { default-features = false, path = "../../precompile/staking" } darwinia-precompile-state-storage = { default-features = false, path = "../../precompile/state-storage" } darwinia-staking = { default-features = false, path = "../../pallet/staking" } @@ -66,7 +67,6 @@ pallet-ethereum = { default-features = false, features = ["forbid pallet-evm = { default-features = false, features = ["forbid-evm-reentrancy"], git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-blake2 = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-bn128 = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } -pallet-evm-precompile-dispatch = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-modexp = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-simple = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } @@ -155,6 +155,7 @@ std = [ "darwinia-precompile-bls12-381/std", "darwinia-precompile-staking/std", "darwinia-precompile-deposit/std", + "darwinia-precompile-dispatch/std", "darwinia-precompile-state-storage/std", "darwinia-staking/std", "dc-primitives/std", @@ -179,7 +180,6 @@ std = [ "pallet-evm/std", "pallet-evm-precompile-blake2/std", "pallet-evm-precompile-bn128/std", - "pallet-evm-precompile-dispatch/std", "pallet-evm-precompile-modexp/std", "pallet-evm-precompile-simple/std", diff --git a/runtime/crab/src/pallets/evm.rs b/runtime/crab/src/pallets/evm.rs index 9f07703c..d9eb03a2 100644 --- a/runtime/crab/src/pallets/evm.rs +++ b/runtime/crab/src/pallets/evm.rs @@ -146,7 +146,7 @@ where darwinia_precompile_state_storage::EthereumStorageFilter, >>::execute(handle)), a if a == addr(1025) => - Some(>::execute(handle)), + Some(>::execute(handle)), // [1026, 1536) reserved for assets precompiles. a if (1026..1536).contains(&AssetIdConverter::account_to_asset_id(a.into())) => Some(>::execute( diff --git a/runtime/darwinia/Cargo.toml b/runtime/darwinia/Cargo.toml index 8a1d9792..5857cd7b 100644 --- a/runtime/darwinia/Cargo.toml +++ b/runtime/darwinia/Cargo.toml @@ -41,6 +41,7 @@ darwinia-message-transact = { default-features = false, path = "../../pa darwinia-precompile-assets = { default-features = false, path = "../../precompile/assets" } darwinia-precompile-bls12-381 = { default-features = false, path = "../../precompile/bls12-381" } darwinia-precompile-deposit = { default-features = false, path = "../../precompile/deposit" } +darwinia-precompile-dispatch = { default-features = false, path = "../../precompile/dispatch" } darwinia-precompile-staking = { default-features = false, path = "../../precompile/staking" } darwinia-precompile-state-storage = { default-features = false, path = "../../precompile/state-storage" } darwinia-staking = { default-features = false, path = "../../pallet/staking" } @@ -66,7 +67,6 @@ pallet-ethereum = { default-features = false, features = ["forbid pallet-evm = { default-features = false, features = ["forbid-evm-reentrancy"], git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-blake2 = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-bn128 = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } -pallet-evm-precompile-dispatch = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-modexp = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-simple = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } @@ -155,6 +155,7 @@ std = [ "darwinia-precompile-bls12-381/std", "darwinia-precompile-staking/std", "darwinia-precompile-deposit/std", + "darwinia-precompile-dispatch/std", "darwinia-precompile-state-storage/std", "darwinia-staking/std", "dc-primitives/std", @@ -179,7 +180,6 @@ std = [ "pallet-evm/std", "pallet-evm-precompile-blake2/std", "pallet-evm-precompile-bn128/std", - "pallet-evm-precompile-dispatch/std", "pallet-evm-precompile-modexp/std", "pallet-evm-precompile-simple/std", diff --git a/runtime/darwinia/src/pallets/evm.rs b/runtime/darwinia/src/pallets/evm.rs index 8578cc1b..8132d270 100644 --- a/runtime/darwinia/src/pallets/evm.rs +++ b/runtime/darwinia/src/pallets/evm.rs @@ -146,7 +146,7 @@ where darwinia_precompile_state_storage::EthereumStorageFilter, >>::execute(handle)), a if a == addr(1025) => - Some(>::execute(handle)), + Some(>::execute(handle)), // [1026, 1536) reserved for assets precompiles. a if (1026..1536).contains(&AssetIdConverter::account_to_asset_id(a.into())) => Some(>::execute( diff --git a/runtime/pangolin/Cargo.toml b/runtime/pangolin/Cargo.toml index 111bc3c1..e1a608fb 100644 --- a/runtime/pangolin/Cargo.toml +++ b/runtime/pangolin/Cargo.toml @@ -41,6 +41,7 @@ darwinia-message-transact = { default-features = false, path = "../../pa darwinia-precompile-assets = { default-features = false, path = "../../precompile/assets" } darwinia-precompile-bls12-381 = { default-features = false, path = "../../precompile/bls12-381" } darwinia-precompile-deposit = { default-features = false, path = "../../precompile/deposit" } +darwinia-precompile-dispatch = { default-features = false, path = "../../precompile/dispatch" } darwinia-precompile-staking = { default-features = false, path = "../../precompile/staking" } darwinia-precompile-state-storage = { default-features = false, path = "../../precompile/state-storage" } darwinia-staking = { default-features = false, path = "../../pallet/staking" } @@ -65,7 +66,6 @@ pallet-ethereum = { default-features = false, features = ["forbid pallet-evm = { default-features = false, features = ["forbid-evm-reentrancy"], git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-blake2 = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-bn128 = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } -pallet-evm-precompile-dispatch = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-modexp = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } pallet-evm-precompile-simple = { default-features = false, git = "https://github.com/paritytech/frontier", branch = "polkadot-v0.9.30" } @@ -152,8 +152,9 @@ std = [ "darwinia-message-transact/std", "darwinia-precompile-assets/std", "darwinia-precompile-bls12-381/std", - "darwinia-precompile-staking/std", "darwinia-precompile-deposit/std", + "darwinia-precompile-dispatch/std", + "darwinia-precompile-staking/std", "darwinia-precompile-state-storage/std", "darwinia-staking/std", "dc-primitives/std", @@ -177,7 +178,6 @@ std = [ "pallet-evm/std", "pallet-evm-precompile-blake2/std", "pallet-evm-precompile-bn128/std", - "pallet-evm-precompile-dispatch/std", "pallet-evm-precompile-modexp/std", "pallet-evm-precompile-simple/std", diff --git a/runtime/pangolin/src/pallets/evm.rs b/runtime/pangolin/src/pallets/evm.rs index 0174f96c..597d6bb6 100644 --- a/runtime/pangolin/src/pallets/evm.rs +++ b/runtime/pangolin/src/pallets/evm.rs @@ -146,7 +146,7 @@ where darwinia_precompile_state_storage::EthereumStorageFilter, >>::execute(handle)), a if a == addr(1025) => - Some(>::execute(handle)), + Some(>::execute(handle)), // [1026, 1536) reserved for assets precompiles. a if (1026..1536).contains(&AssetIdConverter::account_to_asset_id(a.into())) => Some(>::execute(