diff --git a/Cargo.lock b/Cargo.lock index eb9aa5af2f..98722469ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4898,6 +4898,29 @@ dependencies = [ "scale-info", ] +[[package]] +name = "pallet-evm-precompile" +version = "1.0.0-dev" +dependencies = [ + "fp-evm", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-evm", + "pallet-evm-precompile-modexp", + "pallet-evm-precompile-sha3fips", + "pallet-evm-precompile-simple", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-evm-precompile-blake2" version = "2.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 93769f35d1..66dc33a15c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "frame/ethereum", "frame/evm", "frame/evm-chain-id", + "frame/evm-precompile", "frame/hotfix-sufficients", "frame/evm/precompile/sha3fips", "frame/evm/precompile/simple", @@ -137,6 +138,7 @@ pallet-dynamic-fee = { version = "4.0.0-dev", path = "frame/dynamic-fee", defaul pallet-ethereum = { version = "4.0.0-dev", path = "frame/ethereum", default-features = false } pallet-evm = { version = "6.0.0-dev", path = "frame/evm", default-features = false } pallet-evm-chain-id = { version = "1.0.0-dev", path = "frame/evm-chain-id", default-features = false } +pallet-evm-precompile = { version = "1.0.0-dev", path = "frame/evm-precompile", default-features = false } pallet-evm-precompile-modexp = { version = "2.0.0-dev", path = "frame/evm/precompile/modexp", default-features = false } pallet-evm-precompile-sha3fips = { version = "2.0.0-dev", path = "frame/evm/precompile/sha3fips", default-features = false } pallet-evm-precompile-simple = { version = "2.0.0-dev", path = "frame/evm/precompile/simple", default-features = false } diff --git a/frame/evm-precompile/Cargo.toml b/frame/evm-precompile/Cargo.toml new file mode 100644 index 0000000000..d06d773fab --- /dev/null +++ b/frame/evm-precompile/Cargo.toml @@ -0,0 +1,68 @@ +[package] +name = "pallet-evm-precompile" +version = "1.0.0-dev" +license = "Apache-2.0" +readme = "README.md" +description = "FRAME EVM Precompile pallet." +authors = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +scale-codec = { package = "parity-scale-codec", workspace = true } +scale-info = { workspace = true } +serde = { workspace = true, default-features = false } +# Substrate +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } + +# Frontier +pallet-evm = { workspace = true } +pallet-evm-precompile-modexp = { workspace = true } +pallet-evm-precompile-sha3fips = { workspace = true } +pallet-evm-precompile-simple = { workspace = true } + +[dev-dependencies] +# Substrate +pallet-balances = { workspace = true, features = ["default"] } +pallet-timestamp = { workspace = true } +sp-io = { workspace = true } + +# Frontier +fp-evm = { workspace = true } + +[features] +default = ["std"] +std = [ + "serde/std", + # Substrate + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", + # Frontier + "pallet-evm/std", + "pallet-evm-precompile-modexp/std", + "pallet-evm-precompile-sha3fips/std", + "pallet-evm-precompile-simple/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-evm/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-evm/try-runtime", +] diff --git a/frame/evm-precompile/README.md b/frame/evm-precompile/README.md new file mode 100644 index 0000000000..ab3335e4b4 --- /dev/null +++ b/frame/evm-precompile/README.md @@ -0,0 +1,12 @@ +# EVM Precompile Module + +The EVM Precompile Module allows using Precompiles with arbitrary addresses, potentially more than one. + +A `StorageMap` keeps track of the Precompiles on-chain, where: +- key: `H160` +- value: `PrecompileLabel` + +A `PrecompileLabel` determines which functionality the Precompile has. It is declared as a `BoundedVec>`, which means the user is free to choose a label (e.g.: `b"Sha3FIPS512"`) that's up-to 32 bytes long. + +`OnChainPrecompiles` implements the `PrecompileSet` trait, where the Precompile addresses are routed to the appropriate `Precompile::execute` implementation according to the on-chan mapping. + diff --git a/frame/evm-precompile/src/benchmarking.rs b/frame/evm-precompile/src/benchmarking.rs new file mode 100644 index 0000000000..569b71cdd9 --- /dev/null +++ b/frame/evm-precompile/src/benchmarking.rs @@ -0,0 +1,44 @@ +use super::*; + +#[allow(unused)] +use crate::Pallet as EVMPrecompile; +use frame_benchmarking::{benchmarks, impl_benchmark_test_suite}; +use frame_system::RawOrigin; + +benchmarks! { + add_precompile { + let address = H160::from_low_u64_be(1); + let label = PrecompileLabel::new( + b"SomePrecompileLabel" + .to_vec() + .try_into() + .expect("less than 32 chars; qed"), + ); + + }: _(RawOrigin::Root, address, label.clone()) + verify { + let read_precompile = EVMPrecompile::::precompiles(address); + assert_eq!(read_precompile, label); + } + + remove_precompile { + let address = H160::from_low_u64_be(1); + let label = PrecompileLabel::new( + b"SomePrecompileLabel" + .to_vec() + .try_into() + .expect("less than 32 chars; qed"), + ); + EVMPrecompile::::add_precompile(RawOrigin::Root.into(), address, label).unwrap(); + }: _(RawOrigin::Root, address) + verify { + let read_precompile = EVMPrecompile::::precompiles(address); + assert_eq!(read_precompile, PrecompileLabel::default()); + } +} + +impl_benchmark_test_suite!( + EVMPrecompile, + crate::tests::new_test_ext(), + crate::mock::Test +); diff --git a/frame/evm-precompile/src/lib.rs b/frame/evm-precompile/src/lib.rs new file mode 100644 index 0000000000..1adea49212 --- /dev/null +++ b/frame/evm-precompile/src/lib.rs @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: Apache-2.0 +// This file is part of Frontier. +// +// Copyright (c) 2020-2023 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +pub mod weights; +pub use weights::*; + +use frame_support::BoundedVec; +use pallet_evm::{Precompile, PrecompileHandle, 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 scale_codec::{Decode, Encode}; +use scale_info::{prelude::marker::PhantomData, TypeInfo}; +use sp_core::{ConstU32, MaxEncodedLen, H160}; +use sp_std::ops::Deref; + +#[derive(Decode, Encode, Default, TypeInfo, Clone, PartialEq, Debug, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct PrecompileLabel(BoundedVec>); + +impl PrecompileLabel { + pub fn new(l: BoundedVec>) -> PrecompileLabel { + PrecompileLabel(l) + } +} + +impl Deref for PrecompileLabel { + type Target = BoundedVec>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +pub struct OnChainPrecompiles(PhantomData); + +impl OnChainPrecompiles +where + R: pallet::Config + pallet_evm::Config, +{ + pub fn new() -> Self { + Self(Default::default()) + } +} +impl PrecompileSet for OnChainPrecompiles +where + R: pallet::Config + pallet_evm::Config, +{ + fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { + match handle.code_address() { + // Ethereum precompiles : + a if &Precompiles::::get(a)[..] == b"ECRecover" => Some(ECRecover::execute(handle)), + a if &Precompiles::::get(a)[..] == b"Sha256" => Some(Sha256::execute(handle)), + a if &Precompiles::::get(a)[..] == b"Ripemd160" => Some(Ripemd160::execute(handle)), + a if &Precompiles::::get(a)[..] == b"Identity" => Some(Identity::execute(handle)), + a if &Precompiles::::get(a)[..] == b"Modexp" => Some(Modexp::execute(handle)), + // Non-Frontier specific nor Ethereum precompiles : + a if &Precompiles::::get(a)[..] == b"Sha3FIPS256" => { + Some(Sha3FIPS256::execute(handle)) + } + a if &Precompiles::::get(a)[..] == b"ECRecoverPublicKey" => { + Some(ECRecoverPublicKey::execute(handle)) + } + _ => None, + } + } + + fn is_precompile(&self, address: H160) -> bool { + match address { + a if &Precompiles::::get(a)[..] == b"ECRecover" => true, + a if &Precompiles::::get(a)[..] == b"Sha256" => true, + a if &Precompiles::::get(a)[..] == b"Ripemd160" => true, + a if &Precompiles::::get(a)[..] == b"Identity" => true, + a if &Precompiles::::get(a)[..] == b"Modexp" => true, + a if &Precompiles::::get(a)[..] == b"Sha3FIPS256" => true, + a if &Precompiles::::get(a)[..] == b"ECRecoverPublicKey" => true, + _ => false, + } + } +} + +#[frame_support::pallet] +pub mod pallet { + use crate::{PrecompileLabel, WeightInfo}; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + use sp_core::H160; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Origin allowed to modify Precompiles + type PrecompileModifierOrigin: EnsureOrigin; + + // WeightInfo type + type WeightInfo: WeightInfo; + } + + #[pallet::genesis_config] + #[cfg_attr(feature = "std", derive(Default))] + pub struct GenesisConfig { + pub precompiles: Vec<(H160, PrecompileLabel)>, + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + for (address, label) in &self.precompiles { + Pallet::::do_add_precompile(address, label.clone()); + } + } + } + + #[pallet::storage] + #[pallet::getter(fn precompiles)] + pub type Precompiles = + StorageMap<_, Blake2_128Concat, H160, PrecompileLabel, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + PrecompileAdded { + address: H160, + label: PrecompileLabel, + }, + PrecompileRemoved { + address: H160, + }, + } + + #[pallet::error] + pub enum Error { + PrecompileDoesNotExist, + } + + #[pallet::call] + impl Pallet { + /// Add a precompile to storage + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::add_precompile())] + pub fn add_precompile( + origin: OriginFor, + address: H160, + label: PrecompileLabel, + ) -> DispatchResult { + T::PrecompileModifierOrigin::ensure_origin(origin)?; + + Self::do_add_precompile(&address, label.clone()); + + Self::deposit_event(Event::PrecompileAdded { address, label }); + + Ok(()) + } + + /// Remove a precompile from storage + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::remove_precompile())] + pub fn remove_precompile(origin: OriginFor, address: H160) -> DispatchResult { + T::PrecompileModifierOrigin::ensure_origin(origin)?; + + ensure!( + Precompiles::::contains_key(address), + Error::::PrecompileDoesNotExist + ); + + Self::do_remove_precompile(&address); + + Self::deposit_event(Event::PrecompileRemoved { address }); + + Ok(()) + } + } +} + +impl Pallet { + /// Add a precompile to storage + pub fn do_add_precompile(address: &H160, label: PrecompileLabel) { + Precompiles::::set(address, label); + } + + /// Remove a precompile from storage + pub fn do_remove_precompile(address: &H160) { + Precompiles::::remove(address); + } +} diff --git a/frame/evm-precompile/src/mock.rs b/frame/evm-precompile/src/mock.rs new file mode 100644 index 0000000000..35cc5b2e95 --- /dev/null +++ b/frame/evm-precompile/src/mock.rs @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: Apache-2.0 +// This file is part of Frontier. +// +// Copyright (c) 2020-2023 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Test mock for unit tests and benchmarking + +use frame_support::{ + pallet_prelude::PhantomData, + parameter_types, + traits::{ConstU32, FindAuthor}, + weights::Weight, +}; +use sp_core::{H160, H256, U256}; +use sp_runtime::{ + generic, + traits::{BlakeTwo256, IdentityLookup}, + ConsensusEngineId, +}; +use sp_std::{boxed::Box, prelude::*, str::FromStr}; + +use pallet_evm::{EnsureAddressNever, EnsureAddressRoot, FeeCalculator, IdentityAddressMapping}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime! { + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage}, + EVM: pallet_evm::{Pallet, Call, Storage, Config, Event}, + EVMPrecompile: crate::{Pallet, Call, Storage, Config, Event}, + } +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(Weight::from_ref_time(1024)); +} +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = H160; + type Lookup = IdentityLookup; + type Header = generic::Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 0; +} +impl pallet_balances::Config for Test { + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1000; +} +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +pub struct FixedGasPrice; +impl FeeCalculator for FixedGasPrice { + fn min_gas_price() -> (U256, Weight) { + // Return some meaningful gas price and weight + (1_000_000_000u128.into(), Weight::from_ref_time(7u64)) + } +} + +impl crate::Config for Test { + type RuntimeEvent = RuntimeEvent; + type PrecompileModifierOrigin = frame_system::EnsureRoot; + type WeightInfo = crate::weights::SubstrateWeight; +} + +pub struct FindAuthorTruncated; +impl FindAuthor for FindAuthorTruncated { + fn find_author<'a, I>(_digests: I) -> Option + where + I: 'a + IntoIterator, + { + Some(H160::from_str("1234500000000000000000000000000000000000").unwrap()) + } +} +parameter_types! { + pub BlockGasLimit: U256 = U256::max_value(); + pub WeightPerGas: Weight = Weight::from_ref_time(20_000); + pub MockPrecompiles: crate::OnChainPrecompiles = crate::OnChainPrecompiles(PhantomData::); +} +impl pallet_evm::Config for Test { + type FeeCalculator = FixedGasPrice; + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + + type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping; + type CallOrigin = EnsureAddressRoot; + + type WithdrawOrigin = EnsureAddressNever; + type AddressMapping = IdentityAddressMapping; + type Currency = Balances; + + type RuntimeEvent = RuntimeEvent; + type PrecompilesType = crate::OnChainPrecompiles; + type PrecompilesValue = MockPrecompiles; + type ChainId = (); + type BlockGasLimit = BlockGasLimit; + type Runner = pallet_evm::runner::stack::Runner; + type OnChargeTransaction = (); + type OnCreate = (); + type FindAuthor = FindAuthorTruncated; +} diff --git a/frame/evm-precompile/src/tests.rs b/frame/evm-precompile/src/tests.rs new file mode 100644 index 0000000000..30b2e55664 --- /dev/null +++ b/frame/evm-precompile/src/tests.rs @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: Apache-2.0 +// This file is part of Frontier. +// +// Copyright (c) 2020-2023 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(test)] + +use super::*; +use crate::mock::*; + +use fp_evm::GenesisAccount; +use frame_support::{assert_ok, traits::GenesisBuild}; +use sp_core::U256; +use std::{collections::BTreeMap, str::FromStr}; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + let mut accounts = BTreeMap::new(); + accounts.insert( + H160::from_str("1000000000000000000000000000000000000001").unwrap(), + GenesisAccount { + nonce: U256::from(1), + balance: U256::from(1000000), + storage: Default::default(), + code: vec![ + 0x00, // STOP + ], + }, + ); + accounts.insert( + H160::from_str("1000000000000000000000000000000000000002").unwrap(), + GenesisAccount { + nonce: U256::from(1), + balance: U256::from(1000000), + storage: Default::default(), + code: vec![ + 0xff, // INVALID + ], + }, + ); + accounts.insert( + H160::default(), // root + GenesisAccount { + nonce: U256::from(1), + balance: U256::max_value(), + storage: Default::default(), + code: vec![], + }, + ); + + pallet_balances::GenesisConfig:: { + // Create the block author account with some balance. + balances: vec![( + H160::from_str("0x1234500000000000000000000000000000000000").unwrap(), + 12345, + )], + } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + GenesisBuild::::assimilate_storage(&pallet_evm::GenesisConfig { accounts }, &mut t) + .unwrap(); + t.into() +} + +#[test] +fn precompile_storage_works() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::root(); + let address = H160::from_low_u64_be(1); + + let mut read_precompile = Pallet::::precompiles(address); + assert_eq!(read_precompile, PrecompileLabel::default(),); + + let label = PrecompileLabel::new( + b"ECRecover" + .to_vec() + .try_into() + .expect("less than 32 chars; qed"), + ); + + assert_ok!(Pallet::::add_precompile( + origin.clone(), + address, + label.clone(), + )); + + read_precompile = Pallet::::precompiles(address); + assert_eq!(read_precompile, label); + + assert_ok!(Pallet::::remove_precompile(origin, address)); + + read_precompile = Pallet::::precompiles(address); + assert_eq!(read_precompile, PrecompileLabel::default()); + }); +} diff --git a/frame/evm-precompile/src/weights.rs b/frame/evm-precompile/src/weights.rs new file mode 100644 index 0000000000..141cc12f78 --- /dev/null +++ b/frame/evm-precompile/src/weights.rs @@ -0,0 +1,126 @@ +//! Autogenerated weights for `pallet_evm_precompile` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bernardo-benchmarking`, CPU: `AMD EPYC 7B13` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/frontier-template-node +// benchmark +// pallet +// --chain +// dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet +// pallet_evm_precompile +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --output +// weights.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +pub trait WeightInfo { + fn add_precompile() -> Weight; + fn remove_precompile() -> Weight; +} + +/// Weight functions for `pallet_evm_precompile`. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: System Number (r:1 w:0) + /// Proof: System Number (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System ExecutionPhase (r:1 w:0) + /// Proof: System ExecutionPhase (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: System EventCount (r:1 w:1) + /// Proof: System EventCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Events (r:1 w:1) + /// Proof Skipped: System Events (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: EVMPrecompile Precompiles (r:0 w:1) + /// Proof: EVMPrecompile Precompiles (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + fn add_precompile() -> Weight { + // Proof Size summary in bytes: + // Measured: `30` + // Estimated: `2023` + // Minimum execution time: 18_840 nanoseconds. + Weight::from_ref_time(19_460_000) + .saturating_add(Weight::from_proof_size(2023)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EVMPrecompile Precompiles (r:1 w:1) + /// Proof: EVMPrecompile Precompiles (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: System Number (r:1 w:0) + /// Proof: System Number (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System ExecutionPhase (r:1 w:0) + /// Proof: System ExecutionPhase (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: System EventCount (r:1 w:1) + /// Proof: System EventCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Events (r:1 w:1) + /// Proof Skipped: System Events (max_values: Some(1), max_size: None, mode: Measured) + fn remove_precompile() -> Weight { + // Proof Size summary in bytes: + // Measured: `154` + // Estimated: `4691` + // Minimum execution time: 24_460 nanoseconds. + Weight::from_ref_time(25_180_000) + .saturating_add(Weight::from_proof_size(4691)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} + +impl WeightInfo for () { + /// Storage: System Number (r:1 w:0) + /// Proof: System Number (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System ExecutionPhase (r:1 w:0) + /// Proof: System ExecutionPhase (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: System EventCount (r:1 w:1) + /// Proof: System EventCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Events (r:1 w:1) + /// Proof Skipped: System Events (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: EVMPrecompile Precompiles (r:0 w:1) + /// Proof: EVMPrecompile Precompiles (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + fn add_precompile() -> Weight { + // Proof Size summary in bytes: + // Measured: `30` + // Estimated: `2023` + // Minimum execution time: 18_840 nanoseconds. + Weight::from_ref_time(19_460_000) + .saturating_add(Weight::from_proof_size(2023)) + .saturating_add(RocksDbWeight::get().reads(4)) + .saturating_add(RocksDbWeight::get().writes(3)) + } + /// Storage: EVMPrecompile Precompiles (r:1 w:1) + /// Proof: EVMPrecompile Precompiles (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: System Number (r:1 w:0) + /// Proof: System Number (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System ExecutionPhase (r:1 w:0) + /// Proof: System ExecutionPhase (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: System EventCount (r:1 w:1) + /// Proof: System EventCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Events (r:1 w:1) + /// Proof Skipped: System Events (max_values: Some(1), max_size: None, mode: Measured) + fn remove_precompile() -> Weight { + // Proof Size summary in bytes: + // Measured: `154` + // Estimated: `4691` + // Minimum execution time: 24_460 nanoseconds. + Weight::from_ref_time(25_180_000) + .saturating_add(Weight::from_proof_size(4691)) + .saturating_add(RocksDbWeight::get().reads(5)) + .saturating_add(RocksDbWeight::get().writes(3)) + } +} \ No newline at end of file