Skip to content

Commit fca59a0

Browse files
Precompiles uses StorageMap; add struct PrecompileLabel; add_precompile + remove_precompile dispatchables
1 parent 71e440d commit fca59a0

File tree

9 files changed

+217
-34
lines changed

9 files changed

+217
-34
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frame/evm/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ repository = { workspace = true }
1212
targets = ["x86_64-unknown-linux-gnu"]
1313

1414
[dependencies]
15+
serde = { workspace = true, default-features = false }
1516
environmental = { workspace = true, optional = true }
1617
evm = { workspace = true, features = ["with-codec"] }
1718
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
@@ -40,6 +41,7 @@ pallet-evm-precompile-simple = { workspace = true }
4041
[features]
4142
default = ["std"]
4243
std = [
44+
"serde/std",
4345
"environmental?/std",
4446
"evm/std",
4547
"evm/with-serde",

frame/evm/src/lib.rs

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ use frame_support::{
7474
};
7575
use frame_system::RawOrigin;
7676
use impl_trait_for_tuples::impl_for_tuples;
77+
use scale_codec::{Decode, Encode};
78+
use scale_info::TypeInfo;
7779
use sp_core::{Hasher, H160, H256, U256};
7880
use sp_runtime::{
7981
traits::{BadOrigin, Saturating, UniqueSaturatedInto, Zero},
@@ -155,6 +157,9 @@ pub mod pallet {
155157
/// Find author for the current block.
156158
type FindAuthor: FindAuthor<H160>;
157159

160+
/// Origin allowed to modify Precompiles
161+
type PrecompileModifierOrigin: EnsureOrigin<Self::RuntimeOrigin>;
162+
158163
/// EVM config used in the module.
159164
fn config() -> &'static EvmConfig {
160165
&LONDON_CONFIG
@@ -404,6 +409,37 @@ pub mod pallet {
404409
pays_fee: Pays::No,
405410
})
406411
}
412+
413+
/// Add a precompile to storage
414+
#[pallet::call_index(4)]
415+
#[pallet::weight(0)]
416+
pub fn add_precompile(
417+
origin: OriginFor<T>,
418+
address: H160,
419+
label: PrecompileLabel,
420+
) -> DispatchResult {
421+
T::PrecompileModifierOrigin::ensure_origin(origin)?;
422+
423+
Self::do_add_precompile(&address, label);
424+
425+
Ok(())
426+
}
427+
428+
/// Remove a precompile from storage
429+
#[pallet::call_index(5)]
430+
#[pallet::weight(0)]
431+
pub fn remove_precompile(
432+
origin: OriginFor<T>,
433+
address: H160,
434+
) -> DispatchResult {
435+
T::PrecompileModifierOrigin::ensure_origin(origin)?;
436+
437+
ensure!(Precompiles::<T>::contains_key(address), Error::<T>::PrecompileDoesNotExist);
438+
439+
Self::do_remove_precompile(&address);
440+
441+
Ok(())
442+
}
407443
}
408444

409445
#[pallet::event]
@@ -445,6 +481,8 @@ pub mod pallet {
445481
Reentrancy,
446482
/// EIP-3607,
447483
TransactionMustComeFromEOA,
484+
/// Precompile does not exist in storage
485+
PrecompileDoesNotExist,
448486
}
449487

450488
impl<T> From<InvalidEvmTransactionError> for Error<T> {
@@ -467,7 +505,7 @@ pub mod pallet {
467505
#[cfg_attr(feature = "std", derive(Default))]
468506
pub struct GenesisConfig {
469507
pub accounts: std::collections::BTreeMap<H160, GenesisAccount>,
470-
pub precompiles: Vec<(Vec<u8>, H160)>,
508+
pub precompiles: Vec<(H160, PrecompileLabel)>,
471509
}
472510

473511
#[pallet::genesis_build]
@@ -499,8 +537,8 @@ pub mod pallet {
499537
}
500538
}
501539

502-
for (label, address) in &self.precompiles {
503-
Pallet::<T>::add_precompile(label, address);
540+
for (address, label) in &self.precompiles {
541+
Pallet::<T>::do_add_precompile(address, label.clone());
504542
}
505543
}
506544
}
@@ -515,15 +553,21 @@ pub mod pallet {
515553
StorageDoubleMap<_, Blake2_128Concat, H160, Blake2_128Concat, H256, H256, ValueQuery>;
516554

517555
/// Allows for precompiles to have arbitrary addresses, potentially more than one.
518-
/// `k1`: precompile label, e.g.: `b"Sha3FIPS256".to_vec()`
519-
/// `k2`: precompile address
520-
///
556+
/// `key`: precompile `H160` address
557+
/// `value`: precompile label, e.g.: `PrecompileLabel { label: b"Sha3FIPS256".to_vec() }`
558+
521559
/// Please note that adding a new precompile label here is not enough to guarantee its execution
522-
/// It is also required to list the new label on the implementation of `PrecompileSet::execute()`
560+
/// It is also required to list new labels on the implementation of `PrecompileSet::execute()`
523561
#[pallet::storage]
524562
#[pallet::getter(fn precompiles)]
525563
pub type Precompiles<T: Config> =
526-
StorageDoubleMap<_, Blake2_128Concat, Vec<u8>, Blake2_128Concat, H160, (), OptionQuery>;
564+
StorageMap<_, Blake2_128Concat, H160, PrecompileLabel, ValueQuery>;
565+
}
566+
567+
#[derive(Decode, Encode, Default, TypeInfo, Clone, PartialEq, Debug)]
568+
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
569+
pub struct PrecompileLabel {
570+
pub label: Vec<u8>,
527571
}
528572

529573
/// Type alias for currency balance.
@@ -688,13 +732,13 @@ static LONDON_CONFIG: EvmConfig = EvmConfig::london();
688732

689733
impl<T: Config> Pallet<T> {
690734
/// Add a precompile to storage
691-
pub fn add_precompile(label: &Vec<u8>, address: &H160) {
692-
Precompiles::<T>::set(label, address, Some(()));
735+
pub fn do_add_precompile(address: &H160, label: PrecompileLabel) {
736+
Precompiles::<T>::set(address, label);
693737
}
694738

695739
/// Remove a precompile from storage
696-
pub fn remove_precompile(label: &Vec<u8>, address: &H160) {
697-
Precompiles::<T>::remove(label, address);
740+
pub fn do_remove_precompile(address: &H160) {
741+
Precompiles::<T>::remove(address);
698742
}
699743

700744
/// Check whether an account is empty.

frame/evm/src/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ impl crate::Config for Test {
152152
type OnChargeTransaction = ();
153153
type OnCreate = ();
154154
type FindAuthor = FindAuthorTruncated;
155+
type PrecompileModifierOrigin = frame_system::EnsureRoot<Self::AccountId>;
155156
}
156157

157158
/// Exemple PrecompileSet with only Identity precompile.

frame/evm/src/tests.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,3 +620,28 @@ fn eip3607_transaction_from_precompile_should_fail() {
620620
}
621621
});
622622
}
623+
624+
#[test]
625+
fn precompile_storage_works() {
626+
new_test_ext().execute_with(|| {
627+
let origin = RuntimeOrigin::root();
628+
let address = H160::from_low_u64_be(1);
629+
630+
let mut read_precompile = EVM::precompiles(address);
631+
assert_eq!(read_precompile, PrecompileLabel::default());
632+
633+
let label = PrecompileLabel {
634+
label: b"ECRecover".to_vec(),
635+
};
636+
637+
assert_ok!(EVM::add_precompile(origin.clone(), address, label.clone()));
638+
639+
read_precompile = EVM::precompiles(address);
640+
assert_eq!(read_precompile, label);
641+
642+
assert_ok!(EVM::remove_precompile(origin, address));
643+
644+
read_precompile = EVM::precompiles(address);
645+
assert_eq!(read_precompile, PrecompileLabel::default());
646+
});
647+
}

template/node/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ frame-system = { workspace = true }
6666
pallet-transaction-payment = { workspace = true }
6767

6868
# Frontier
69+
pallet-evm = { workspace = true }
6970
fc-cli = { workspace = true }
7071
fc-consensus = { workspace = true }
7172
fc-db = { workspace = true }

template/node/src/chain_spec.rs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use frontier_template_runtime::{
1313
AccountId, EnableManualSeal, GenesisConfig, Signature, WASM_BINARY,
1414
};
1515

16+
use pallet_evm::PrecompileLabel;
17+
1618
// The URL for the telemetry server.
1719
// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
1820

@@ -252,14 +254,49 @@ fn testnet_genesis(
252254
},
253255
precompiles: vec![
254256
// Ethereum precompiles :
255-
(b"ECRecover".to_vec(), H160::from_low_u64_be(1)),
256-
(b"Sha256".to_vec(), H160::from_low_u64_be(2)),
257-
(b"Ripemd160".to_vec(), H160::from_low_u64_be(3)),
258-
(b"Identity".to_vec(), H160::from_low_u64_be(4)),
259-
(b"Modexp".to_vec(), H160::from_low_u64_be(5)),
257+
(
258+
H160::from_low_u64_be(1),
259+
PrecompileLabel {
260+
label: b"ECRecover".to_vec(),
261+
},
262+
),
263+
(
264+
H160::from_low_u64_be(2),
265+
PrecompileLabel {
266+
label: b"Sha256".to_vec(),
267+
},
268+
),
269+
(
270+
H160::from_low_u64_be(3),
271+
PrecompileLabel {
272+
label: b"Ripemd160".to_vec(),
273+
},
274+
),
275+
(
276+
H160::from_low_u64_be(4),
277+
PrecompileLabel {
278+
label: b"Identity".to_vec(),
279+
},
280+
),
281+
(
282+
H160::from_low_u64_be(5),
283+
PrecompileLabel {
284+
label: b"Modexp".to_vec(),
285+
},
286+
),
260287
// Non-Frontier specific nor Ethereum precompiles :
261-
(b"Sha3FIPS256".to_vec(), H160::from_low_u64_be(1024)),
262-
(b"Sha3FIPS256".to_vec(), H160::from_low_u64_be(1025)),
288+
(
289+
H160::from_low_u64_be(1024),
290+
PrecompileLabel {
291+
label: b"Sha3FIPS256".to_vec(),
292+
},
293+
),
294+
(
295+
H160::from_low_u64_be(1025),
296+
PrecompileLabel {
297+
label: b"Sha3FIPS256".to_vec(),
298+
},
299+
),
263300
],
264301
},
265302
ethereum: Default::default(),

template/runtime/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ impl pallet_evm::Config for Runtime {
343343
type OnChargeTransaction = ();
344344
type OnCreate = ();
345345
type FindAuthor = FindAuthorTruncated<Aura>;
346+
type PrecompileModifierOrigin = frame_system::EnsureRoot<Self::AccountId>;
346347
}
347348

348349
parameter_types! {

0 commit comments

Comments
 (0)