diff --git a/Cargo.lock b/Cargo.lock index e86ef3d69..964c583e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1067,12 +1067,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "case" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6c0e7b807d60291f42f33f58480c0bfafe28ed08286446f45e463728cf9c1c" - [[package]] name = "cc" version = "1.1.24" @@ -5664,7 +5658,6 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "pallet-utility", "parity-scale-codec", - "precompile-utils", "rand_chacha", "scale-info", "serde_json", @@ -7017,44 +7010,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "precompile-utils" -version = "0.1.0" -source = "git+https://github.com/opentensor/frontier?rev=635bdac882#635bdac882333afed827053f31ef56ab739f7a2e" -dependencies = [ - "environmental", - "evm", - "fp-evm", - "frame-support", - "frame-system", - "hex", - "impl-trait-for-tuples", - "log", - "num_enum", - "pallet-evm", - "parity-scale-codec", - "precompile-utils-macro", - "sp-core", - "sp-io", - "sp-runtime", - "sp-weights", - "staging-xcm", -] - -[[package]] -name = "precompile-utils-macro" -version = "0.1.0" -source = "git+https://github.com/opentensor/frontier?rev=635bdac882#635bdac882333afed827053f31ef56ab739f7a2e" -dependencies = [ - "case", - "num_enum", - "prettyplease 0.2.22", - "proc-macro2", - "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", - "syn 1.0.109", -] - [[package]] name = "predicates" version = "2.1.5" diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 0d44e0907..171ef3c47 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -20,7 +20,9 @@ name = "spec_version" path = "src/spec_version.rs" [dependencies] -ed25519-dalek = { workspace = true, default-features = false, features = ["alloc"] } +ed25519-dalek = { workspace = true, default-features = false, features = [ + "alloc", +] } subtensor-macros.workspace = true subtensor-custom-rpc-runtime-api = { path = "../pallets/subtensor/runtime-api", default-features = false } smallvec = { workspace = true } @@ -98,7 +100,6 @@ pallet-commitments = { default-features = false, path = "../pallets/commitments" fp-evm = { workspace = true } fp-rpc = { workspace = true } fp-self-contained = { workspace = true } -precompile-utils = { workspace = true } # Frontier FRAME pallet-base-fee = { workspace = true } @@ -133,9 +134,7 @@ substrate-wasm-builder = { workspace = true, optional = true } [features] default = ["std"] pow-faucet = ["pallet-subtensor/pow-faucet"] -fast-blocks = [ - "pallet-subtensor/fast-blocks" -] +fast-blocks = ["pallet-subtensor/fast-blocks"] std = [ "frame-try-runtime?/std", "frame-system-benchmarking?/std", @@ -192,7 +191,6 @@ std = [ "fp-evm/std", "fp-rpc/std", "fp-self-contained/std", - "precompile-utils/std", # Frontier FRAME "pallet-base-fee/std", "pallet-dynamic-fee/std", @@ -211,7 +209,7 @@ std = [ "hex/std", "rand_chacha/std", "sha2/std", - "w3f-bls/std" + "w3f-bls/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -240,7 +238,7 @@ runtime-benchmarks = [ "pallet-ethereum/runtime-benchmarks", "pallet-evm/runtime-benchmarks", "pallet-hotfix-sufficients/runtime-benchmarks", - "pallet-drand/runtime-benchmarks" + "pallet-drand/runtime-benchmarks", ] try-runtime = [ "frame-try-runtime/try-runtime", @@ -276,6 +274,6 @@ try-runtime = [ "pallet-ethereum/try-runtime", "pallet-evm/try-runtime", "pallet-evm-chain-id/try-runtime", - "pallet-drand/try-runtime" + "pallet-drand/try-runtime", ] metadata-hash = ["substrate-wasm-builder/metadata-hash"] diff --git a/runtime/src/precompiles/balance_transfer.rs b/runtime/src/precompiles/balance_transfer.rs index 03c4be8a6..9d9f60a80 100644 --- a/runtime/src/precompiles/balance_transfer.rs +++ b/runtime/src/precompiles/balance_transfer.rs @@ -1,15 +1,14 @@ use frame_system::RawOrigin; use pallet_evm::{ - BalanceConverter, ExitError, ExitSucceed, PrecompileFailure, PrecompileHandle, - PrecompileOutput, PrecompileResult, + BalanceConverter, ExitError, ExitSucceed, PrecompileHandle, PrecompileOutput, PrecompileResult, }; -use precompile_utils::prelude::RuntimeHelper; -use sp_core::U256; use sp_runtime::traits::UniqueSaturatedInto; use sp_std::vec; -use crate::precompiles::{bytes_to_account_id, get_method_id, get_slice}; -use crate::{Runtime, RuntimeCall}; +use crate::precompiles::{ + bytes_to_account_id, get_method_id, get_slice, try_dispatch_runtime_call, +}; +use crate::Runtime; pub const BALANCE_TRANSFER_INDEX: u64 = 2048; @@ -37,7 +36,7 @@ impl BalanceTransferPrecompile { } // Forward all received value to the destination address - let amount: U256 = handle.context().apparent_value; + let amount = handle.context().apparent_value; // Use BalanceConverter to convert EVM amount to Substrate balance let amount_sub = @@ -55,23 +54,12 @@ impl BalanceTransferPrecompile { let account_id_src = bytes_to_account_id(&CONTRACT_ADDRESS_SS58)?; let account_id_dst = bytes_to_account_id(address_bytes_dst)?; - let call = RuntimeCall::Balances(pallet_balances::Call::::transfer_allow_death { + let call = pallet_balances::Call::::transfer_allow_death { dest: account_id_dst.into(), value: amount_sub.unique_saturated_into(), - }); + }; + let origin = RawOrigin::Signed(account_id_src).into(); - // Dispatch the call - RuntimeHelper::::try_dispatch( - handle, - RawOrigin::Signed(account_id_src).into(), - call, - ) - .map(|_| PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: vec![], - }) - .map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::OutOfFund, - }) + try_dispatch_runtime_call(handle, call, origin) } } diff --git a/runtime/src/precompiles/mod.rs b/runtime/src/precompiles/mod.rs index e13516e95..e0cb85f3b 100644 --- a/runtime/src/precompiles/mod.rs +++ b/runtime/src/precompiles/mod.rs @@ -1,14 +1,21 @@ +extern crate alloc; + +use alloc::format; use core::marker::PhantomData; -use sp_core::{hashing::keccak_256, H160}; -use sp_runtime::AccountId32; +use frame_support::dispatch::{GetDispatchInfo, Pays}; +use frame_system::RawOrigin; use pallet_evm::{ - ExitError, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, - PrecompileResult, PrecompileSet, + ExitError, ExitSucceed, GasWeightMapping, IsPrecompileResult, Precompile, PrecompileFailure, + PrecompileHandle, PrecompileOutput, PrecompileResult, PrecompileSet, }; use pallet_evm_precompile_modexp::Modexp; use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; +use sp_core::{hashing::keccak_256, H160}; +use sp_runtime::{traits::Dispatchable, AccountId32}; + +use crate::{Runtime, RuntimeCall}; // Include custom precompiles mod balance_transfer; @@ -130,3 +137,70 @@ pub fn get_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], Precompil }) } } + +/// Dispatches a runtime call, but also checks and records the gas costs. +fn try_dispatch_runtime_call( + handle: &mut impl PrecompileHandle, + call: impl Into, + origin: RawOrigin, +) -> PrecompileResult { + let call = Into::::into(call); + let info = call.get_dispatch_info(); + + let target_gas = handle.gas_limit(); + if let Some(gas) = target_gas { + let valid_weight = + ::GasWeightMapping::gas_to_weight(gas, false).ref_time(); + if info.weight.ref_time() > valid_weight { + return Err(PrecompileFailure::Error { + exit_status: ExitError::OutOfGas, + }); + } + } + + handle.record_external_cost( + Some(info.weight.ref_time()), + Some(info.weight.proof_size()), + None, + )?; + + match call.dispatch(origin.into()) { + Ok(post_info) => { + if post_info.pays_fee(&info) == Pays::Yes { + let actual_weight = post_info.actual_weight.unwrap_or(info.weight); + let cost = + ::GasWeightMapping::weight_to_gas(actual_weight); + handle.record_cost(cost)?; + + handle.refund_external_cost( + Some( + info.weight + .ref_time() + .saturating_sub(actual_weight.ref_time()), + ), + Some( + info.weight + .proof_size() + .saturating_sub(actual_weight.proof_size()), + ), + ); + } + + log::info!("Dispatch succeeded. Post info: {:?}", post_info); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: Default::default(), + }) + } + Err(e) => { + log::error!("Dispatch failed. Error: {:?}", e); + log::warn!("Returning error PrecompileFailure::Error"); + Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + format!("dispatch execution failed: {}", <&'static str>::from(e)).into(), + ), + }) + } + } +} diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs index f8534927b..8f2996b8e 100644 --- a/runtime/src/precompiles/staking.rs +++ b/runtime/src/precompiles/staking.rs @@ -30,7 +30,6 @@ use pallet_evm::{ AddressMapping, BalanceConverter, ExitError, ExitSucceed, HashedAddressMapping, PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileResult, }; -use precompile_utils::prelude::RuntimeHelper; use sp_core::crypto::Ss58Codec; use sp_core::U256; use sp_runtime::traits::{BlakeTwo256, Dispatchable, StaticLookup, UniqueSaturatedInto}; @@ -38,7 +37,7 @@ use sp_runtime::AccountId32; use sp_std::vec; use crate::{ - precompiles::{get_method_id, get_slice}, + precompiles::{get_method_id, get_slice, try_dispatch_runtime_call}, ProxyType, Runtime, RuntimeCall, }; @@ -214,28 +213,7 @@ impl StakingPrecompile { Self::transfer_back_to_caller(&account_id, amount)?; } - match RuntimeHelper::::try_dispatch( - handle, - RawOrigin::Signed(account_id.clone()).into(), - call, - ) { - Ok(post_info) => { - log::info!("Dispatch succeeded. Post info: {:?}", post_info); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: vec![], - }) - } - - Err(dispatch_error) => { - log::error!("Dispatch failed. Error: {:?}", dispatch_error); - log::warn!("Returning error PrecompileFailure::Error"); - Err(PrecompileFailure::Error { - exit_status: ExitError::Other("Subtensor call failed".into()), - }) - } - } + try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id.clone()).into()) } fn transfer_back_to_caller(