pallet_revive/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18#![doc = include_str!("../README.md")]
19#![allow(rustdoc::private_intra_doc_links)]
20#![cfg_attr(not(feature = "std"), no_std)]
21#![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "1024")]
22
23extern crate alloc;
24
25mod address;
26mod benchmarking;
27mod call_builder;
28mod exec;
29mod gas;
30mod impl_fungibles;
31mod limits;
32mod primitives;
33mod storage;
34#[cfg(test)]
35mod tests;
36mod transient_storage;
37mod vm;
38
39pub mod evm;
40pub mod migrations;
41pub mod precompiles;
42pub mod test_utils;
43pub mod tracing;
44pub mod weights;
45
46use crate::{
47	evm::{
48		runtime::GAS_PRICE, CallTracer, GasEncoder, GenericTransaction, PrestateTracer, Trace,
49		Tracer, TracerType, TYPE_EIP1559,
50	},
51	exec::{AccountIdOf, ExecError, Executable, Stack as ExecStack},
52	gas::GasMeter,
53	storage::{meter::Meter as StorageMeter, AccountType, DeletionQueueManager},
54	tracing::if_tracing,
55	vm::{pvm::extract_code_and_data, CodeInfo, ContractBlob, RuntimeCosts},
56};
57use alloc::{boxed::Box, format, vec};
58use codec::{Codec, Decode, Encode};
59use environmental::*;
60use frame_support::{
61	dispatch::{
62		DispatchErrorWithPostInfo, DispatchResultWithPostInfo, GetDispatchInfo, Pays,
63		PostDispatchInfo, RawOrigin,
64	},
65	ensure,
66	pallet_prelude::DispatchClass,
67	traits::{
68		fungible::{Inspect, Mutate, MutateHold},
69		ConstU32, ConstU64, EnsureOrigin, Get, IsType, OriginTrait, Time,
70	},
71	weights::WeightMeter,
72	BoundedVec, RuntimeDebugNoBound,
73};
74use frame_system::{
75	ensure_signed,
76	pallet_prelude::{BlockNumberFor, OriginFor},
77	Pallet as System,
78};
79use pallet_transaction_payment::OnChargeTransaction;
80use scale_info::TypeInfo;
81use sp_runtime::{
82	traits::{Bounded, Convert, Dispatchable, Saturating},
83	AccountId32, DispatchError,
84};
85
86pub use crate::{
87	address::{
88		create1, create2, is_eth_derived, AccountId32Mapper, AddressMapper, TestAccountMapper,
89	},
90	exec::{Key, MomentOf, Origin},
91	pallet::*,
92	storage::{AccountInfo, ContractInfo},
93};
94pub use codec;
95pub use frame_support::{self, dispatch::DispatchInfo, weights::Weight};
96pub use frame_system::{self, limits::BlockWeights};
97pub use pallet_transaction_payment;
98pub use primitives::*;
99pub use sp_core::{H160, H256, U256};
100pub use sp_runtime;
101pub use weights::WeightInfo;
102
103#[cfg(doc)]
104pub use crate::vm::pvm::SyscallDoc;
105
106pub type BalanceOf<T> =
107	<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
108type TrieId = BoundedVec<u8, ConstU32<128>>;
109type ImmutableData = BoundedVec<u8, ConstU32<{ limits::IMMUTABLE_BYTES }>>;
110pub(crate) type OnChargeTransactionBalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as OnChargeTransaction<T>>::Balance;
111
112/// Used as a sentinel value when reading and writing contract memory.
113///
114/// It is usually used to signal `None` to a contract when only a primitive is allowed
115/// and we don't want to go through encoding a full Rust type. Using `u32::Max` is a safe
116/// sentinel because contracts are never allowed to use such a large amount of resources
117/// that this value makes sense for a memory location or length.
118const SENTINEL: u32 = u32::MAX;
119
120/// The target that is used for the log output emitted by this crate.
121///
122/// Hence you can use this target to selectively increase the log level for this crate.
123///
124/// Example: `RUST_LOG=runtime::revive=debug my_code --dev`
125const LOG_TARGET: &str = "runtime::revive";
126
127#[frame_support::pallet]
128pub mod pallet {
129	use super::*;
130	use frame_support::{pallet_prelude::*, traits::FindAuthor};
131	use frame_system::pallet_prelude::*;
132	use sp_core::U256;
133	use sp_runtime::Perbill;
134
135	/// The in-code storage version.
136	pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
137
138	#[pallet::pallet]
139	#[pallet::storage_version(STORAGE_VERSION)]
140	pub struct Pallet<T>(_);
141
142	#[pallet::config(with_default)]
143	pub trait Config: frame_system::Config {
144		/// The time implementation used to supply timestamps to contracts through `seal_now`.
145		type Time: Time;
146
147		/// The fungible in which fees are paid and contract balances are held.
148		#[pallet::no_default]
149		type Currency: Inspect<Self::AccountId>
150			+ Mutate<Self::AccountId>
151			+ MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>;
152
153		/// The overarching event type.
154		#[pallet::no_default_bounds]
155		#[allow(deprecated)]
156		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
157
158		/// The overarching call type.
159		#[pallet::no_default_bounds]
160		type RuntimeCall: Parameter
161			+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin, PostInfo = PostDispatchInfo>
162			+ GetDispatchInfo;
163
164		/// Overarching hold reason.
165		#[pallet::no_default_bounds]
166		type RuntimeHoldReason: From<HoldReason>;
167
168		/// Used to answer contracts' queries regarding the current weight price. This is **not**
169		/// used to calculate the actual fee and is only for informational purposes.
170		#[pallet::no_default_bounds]
171		type WeightPrice: Convert<Weight, BalanceOf<Self>>;
172
173		/// Describes the weights of the dispatchables of this module and is also used to
174		/// construct a default cost schedule.
175		type WeightInfo: WeightInfo;
176
177		/// Type that allows the runtime authors to add new host functions for a contract to call.
178		///
179		/// Pass in a tuple of types that implement [`precompiles::Precompile`].
180		#[pallet::no_default_bounds]
181		#[allow(private_bounds)]
182		type Precompiles: precompiles::Precompiles<Self>;
183
184		/// Find the author of the current block.
185		type FindAuthor: FindAuthor<Self::AccountId>;
186
187		/// The amount of balance a caller has to pay for each byte of storage.
188		///
189		/// # Note
190		///
191		/// It is safe to change this value on a live chain as all refunds are pro rata.
192		#[pallet::constant]
193		#[pallet::no_default_bounds]
194		type DepositPerByte: Get<BalanceOf<Self>>;
195
196		/// The amount of balance a caller has to pay for each storage item.
197		///
198		/// # Note
199		///
200		/// It is safe to change this value on a live chain as all refunds are pro rata.
201		#[pallet::constant]
202		#[pallet::no_default_bounds]
203		type DepositPerItem: Get<BalanceOf<Self>>;
204
205		/// The percentage of the storage deposit that should be held for using a code hash.
206		/// Instantiating a contract, protects the code from being removed. In order to prevent
207		/// abuse these actions are protected with a percentage of the code deposit.
208		#[pallet::constant]
209		type CodeHashLockupDepositPercent: Get<Perbill>;
210
211		/// Use either valid type is [`address::AccountId32Mapper`] or [`address::H160Mapper`].
212		#[pallet::no_default]
213		type AddressMapper: AddressMapper<Self>;
214
215		/// Make contract callable functions marked as `#[unstable]` available.
216		///
217		/// Contracts that use `#[unstable]` functions won't be able to be uploaded unless
218		/// this is set to `true`. This is only meant for testnets and dev nodes in order to
219		/// experiment with new features.
220		///
221		/// # Warning
222		///
223		/// Do **not** set to `true` on productions chains.
224		#[pallet::constant]
225		type UnsafeUnstableInterface: Get<bool>;
226
227		/// Allow EVM bytecode to be uploaded and instantiated.
228		#[pallet::constant]
229		type AllowEVMBytecode: Get<bool>;
230
231		/// Origin allowed to upload code.
232		///
233		/// By default, it is safe to set this to `EnsureSigned`, allowing anyone to upload contract
234		/// code.
235		#[pallet::no_default_bounds]
236		type UploadOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
237
238		/// Origin allowed to instantiate code.
239		///
240		/// # Note
241		///
242		/// This is not enforced when a contract instantiates another contract. The
243		/// [`Self::UploadOrigin`] should make sure that no code is deployed that does unwanted
244		/// instantiations.
245		///
246		/// By default, it is safe to set this to `EnsureSigned`, allowing anyone to instantiate
247		/// contract code.
248		#[pallet::no_default_bounds]
249		type InstantiateOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
250
251		/// The amount of memory in bytes that parachain nodes a lot to the runtime.
252		///
253		/// This is used in [`Pallet::integrity_test`] to make sure that the runtime has enough
254		/// memory to support this pallet if set to the correct value.
255		type RuntimeMemory: Get<u32>;
256
257		/// The amount of memory in bytes that relay chain validators a lot to the PoV.
258		///
259		/// This is used in [`Pallet::integrity_test`] to make sure that the runtime has enough
260		/// memory to support this pallet if set to the correct value.
261		///
262		/// This value is usually higher than [`Self::RuntimeMemory`] to account for the fact
263		/// that validators have to hold all storage items in PvF memory.
264		type PVFMemory: Get<u32>;
265
266		/// The [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID.
267		///
268		/// This is a unique identifier assigned to each blockchain network,
269		/// preventing replay attacks.
270		#[pallet::constant]
271		type ChainId: Get<u64>;
272
273		/// The ratio between the decimal representation of the native token and the ETH token.
274		#[pallet::constant]
275		type NativeToEthRatio: Get<u32>;
276
277		/// Encode and decode Ethereum gas values.
278		/// Only valid value is `()`. See [`GasEncoder`].
279		#[pallet::no_default_bounds]
280		type EthGasEncoder: GasEncoder<BalanceOf<Self>>;
281	}
282
283	/// Container for different types that implement [`DefaultConfig`]` of this pallet.
284	pub mod config_preludes {
285		use super::*;
286		use frame_support::{
287			derive_impl,
288			traits::{ConstBool, ConstU32},
289		};
290		use frame_system::EnsureSigned;
291		use sp_core::parameter_types;
292
293		type Balance = u64;
294		const UNITS: Balance = 10_000_000_000;
295		const CENTS: Balance = UNITS / 100;
296
297		pub const fn deposit(items: u32, bytes: u32) -> Balance {
298			items as Balance * 1 * CENTS + (bytes as Balance) * 1 * CENTS
299		}
300
301		parameter_types! {
302			pub const DepositPerItem: Balance = deposit(1, 0);
303			pub const DepositPerByte: Balance = deposit(0, 1);
304			pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
305		}
306
307		/// A type providing default configurations for this pallet in testing environment.
308		pub struct TestDefaultConfig;
309
310		impl Time for TestDefaultConfig {
311			type Moment = u64;
312			fn now() -> Self::Moment {
313				0u64
314			}
315		}
316
317		impl<T: From<u64>> Convert<Weight, T> for TestDefaultConfig {
318			fn convert(w: Weight) -> T {
319				w.ref_time().into()
320			}
321		}
322
323		#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
324		impl frame_system::DefaultConfig for TestDefaultConfig {}
325
326		#[frame_support::register_default_impl(TestDefaultConfig)]
327		impl DefaultConfig for TestDefaultConfig {
328			#[inject_runtime_type]
329			type RuntimeEvent = ();
330
331			#[inject_runtime_type]
332			type RuntimeHoldReason = ();
333
334			#[inject_runtime_type]
335			type RuntimeCall = ();
336			type Precompiles = ();
337			type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
338			type DepositPerByte = DepositPerByte;
339			type DepositPerItem = DepositPerItem;
340			type Time = Self;
341			type UnsafeUnstableInterface = ConstBool<true>;
342			type AllowEVMBytecode = ConstBool<true>;
343			type UploadOrigin = EnsureSigned<Self::AccountId>;
344			type InstantiateOrigin = EnsureSigned<Self::AccountId>;
345			type WeightInfo = ();
346			type WeightPrice = Self;
347			type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>;
348			type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>;
349			type ChainId = ConstU64<42>;
350			type NativeToEthRatio = ConstU32<1_000_000>;
351			type EthGasEncoder = ();
352			type FindAuthor = ();
353		}
354	}
355
356	#[pallet::event]
357	pub enum Event<T: Config> {
358		/// A custom event emitted by the contract.
359		ContractEmitted {
360			/// The contract that emitted the event.
361			contract: H160,
362			/// Data supplied by the contract. Metadata generated during contract compilation
363			/// is needed to decode it.
364			data: Vec<u8>,
365			/// A list of topics used to index the event.
366			/// Number of topics is capped by [`limits::NUM_EVENT_TOPICS`].
367			topics: Vec<H256>,
368		},
369
370		/// Contract deployed by deployer at the specified address.
371		Instantiated { deployer: H160, contract: H160 },
372	}
373
374	#[pallet::error]
375	#[repr(u8)]
376	pub enum Error<T> {
377		/// Invalid schedule supplied, e.g. with zero weight of a basic operation.
378		InvalidSchedule = 0x01,
379		/// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`.
380		InvalidCallFlags = 0x02,
381		/// The executed contract exhausted its gas limit.
382		OutOfGas = 0x03,
383		/// Performing the requested transfer failed. Probably because there isn't enough
384		/// free balance in the sender's account.
385		TransferFailed = 0x04,
386		/// Performing a call was denied because the calling depth reached the limit
387		/// of what is specified in the schedule.
388		MaxCallDepthReached = 0x05,
389		/// No contract was found at the specified address.
390		ContractNotFound = 0x06,
391		/// No code could be found at the supplied code hash.
392		CodeNotFound = 0x07,
393		/// No code info could be found at the supplied code hash.
394		CodeInfoNotFound = 0x08,
395		/// A buffer outside of sandbox memory was passed to a contract API function.
396		OutOfBounds = 0x09,
397		/// Input passed to a contract API function failed to decode as expected type.
398		DecodingFailed = 0x0A,
399		/// Contract trapped during execution.
400		ContractTrapped = 0x0B,
401		/// Event body or storage item exceeds [`limits::PAYLOAD_BYTES`].
402		ValueTooLarge = 0x0C,
403		/// Termination of a contract is not allowed while the contract is already
404		/// on the call stack. Can be triggered by `seal_terminate`.
405		TerminatedWhileReentrant = 0x0D,
406		/// `seal_call` forwarded this contracts input. It therefore is no longer available.
407		InputForwarded = 0x0E,
408		/// The amount of topics passed to `seal_deposit_events` exceeds the limit.
409		TooManyTopics = 0x0F,
410		/// A contract with the same AccountId already exists.
411		DuplicateContract = 0x12,
412		/// A contract self destructed in its constructor.
413		///
414		/// This can be triggered by a call to `seal_terminate`.
415		TerminatedInConstructor = 0x13,
416		/// A call tried to invoke a contract that is flagged as non-reentrant.
417		ReentranceDenied = 0x14,
418		/// A contract called into the runtime which then called back into this pallet.
419		ReenteredPallet = 0x15,
420		/// A contract attempted to invoke a state modifying API while being in read-only mode.
421		StateChangeDenied = 0x16,
422		/// Origin doesn't have enough balance to pay the required storage deposits.
423		StorageDepositNotEnoughFunds = 0x17,
424		/// More storage was created than allowed by the storage deposit limit.
425		StorageDepositLimitExhausted = 0x18,
426		/// Code removal was denied because the code is still in use by at least one contract.
427		CodeInUse = 0x19,
428		/// The contract ran to completion but decided to revert its storage changes.
429		/// Please note that this error is only returned from extrinsics. When called directly
430		/// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags
431		/// to determine whether a reversion has taken place.
432		ContractReverted = 0x1A,
433		/// The contract failed to compile or is missing the correct entry points.
434		///
435		/// A more detailed error can be found on the node console if debug messages are enabled
436		/// by supplying `-lruntime::revive=debug`.
437		CodeRejected = 0x1B,
438		/// The code blob supplied is larger than [`limits::code::BLOB_BYTES`].
439		BlobTooLarge = 0x1C,
440		/// The contract declares too much memory (ro + rw + stack).
441		StaticMemoryTooLarge = 0x1D,
442		/// The program contains a basic block that is larger than allowed.
443		BasicBlockTooLarge = 0x1E,
444		/// The program contains an invalid instruction.
445		InvalidInstruction = 0x1F,
446		/// The contract has reached its maximum number of delegate dependencies.
447		MaxDelegateDependenciesReached = 0x20,
448		/// The dependency was not found in the contract's delegate dependencies.
449		DelegateDependencyNotFound = 0x21,
450		/// The contract already depends on the given delegate dependency.
451		DelegateDependencyAlreadyExists = 0x22,
452		/// Can not add a delegate dependency to the code hash of the contract itself.
453		CannotAddSelfAsDelegateDependency = 0x23,
454		/// Can not add more data to transient storage.
455		OutOfTransientStorage = 0x24,
456		/// The contract tried to call a syscall which does not exist (at its current api level).
457		InvalidSyscall = 0x25,
458		/// Invalid storage flags were passed to one of the storage syscalls.
459		InvalidStorageFlags = 0x26,
460		/// PolkaVM failed during code execution. Probably due to a malformed program.
461		ExecutionFailed = 0x27,
462		/// Failed to convert a U256 to a Balance.
463		BalanceConversionFailed = 0x28,
464		/// Immutable data can only be set during deploys and only be read during calls.
465		/// Additionally, it is only valid to set the data once and it must not be empty.
466		InvalidImmutableAccess = 0x2A,
467		/// An `AccountID32` account tried to interact with the pallet without having a mapping.
468		///
469		/// Call [`Pallet::map_account`] in order to create a mapping for the account.
470		AccountUnmapped = 0x2B,
471		/// Tried to map an account that is already mapped.
472		AccountAlreadyMapped = 0x2C,
473		/// The transaction used to dry-run a contract is invalid.
474		InvalidGenericTransaction = 0x2D,
475		/// The refcount of a code either over or underflowed.
476		RefcountOverOrUnderflow = 0x2E,
477		/// Unsupported precompile address.
478		UnsupportedPrecompileAddress = 0x2F,
479		/// The calldata exceeds [`limits::CALLDATA_BYTES`].
480		CallDataTooLarge = 0x30,
481		/// The return data exceeds [`limits::CALLDATA_BYTES`].
482		ReturnDataTooLarge = 0x31,
483	}
484
485	/// A reason for the pallet revive placing a hold on funds.
486	#[pallet::composite_enum]
487	pub enum HoldReason {
488		/// The Pallet has reserved it for storing code on-chain.
489		CodeUploadDepositReserve,
490		/// The Pallet has reserved it for storage deposit.
491		StorageDepositReserve,
492		/// Deposit for creating an address mapping in [`OriginalAccount`].
493		AddressMapping,
494	}
495
496	/// A mapping from a contract's code hash to its code.
497	/// The code's size is bounded by [`crate::limits::BLOB_BYTES`] for PVM and
498	/// [`revm::primitives::eip170::MAX_CODE_SIZE`] for EVM bytecode.
499	#[pallet::storage]
500	#[pallet::unbounded]
501	pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, H256, Vec<u8>>;
502
503	/// A mapping from a contract's code hash to its code info.
504	#[pallet::storage]
505	pub(crate) type CodeInfoOf<T: Config> = StorageMap<_, Identity, H256, CodeInfo<T>>;
506
507	/// The data associated to a contract or externally owned account.
508	#[pallet::storage]
509	pub(crate) type AccountInfoOf<T: Config> = StorageMap<_, Identity, H160, AccountInfo<T>>;
510
511	/// The immutable data associated with a given account.
512	#[pallet::storage]
513	pub(crate) type ImmutableDataOf<T: Config> = StorageMap<_, Identity, H160, ImmutableData>;
514
515	/// Evicted contracts that await child trie deletion.
516	///
517	/// Child trie deletion is a heavy operation depending on the amount of storage items
518	/// stored in said trie. Therefore this operation is performed lazily in `on_idle`.
519	#[pallet::storage]
520	pub(crate) type DeletionQueue<T: Config> = StorageMap<_, Twox64Concat, u32, TrieId>;
521
522	/// A pair of monotonic counters used to track the latest contract marked for deletion
523	/// and the latest deleted contract in queue.
524	#[pallet::storage]
525	pub(crate) type DeletionQueueCounter<T: Config> =
526		StorageValue<_, DeletionQueueManager<T>, ValueQuery>;
527
528	/// Map a Ethereum address to its original `AccountId32`.
529	///
530	/// When deriving a `H160` from an `AccountId32` we use a hash function. In order to
531	/// reconstruct the original account we need to store the reverse mapping here.
532	/// Register your `AccountId32` using [`Pallet::map_account`] in order to
533	/// use it with this pallet.
534	#[pallet::storage]
535	pub(crate) type OriginalAccount<T: Config> = StorageMap<_, Identity, H160, AccountId32>;
536
537	#[pallet::genesis_config]
538	#[derive(frame_support::DefaultNoBound)]
539	pub struct GenesisConfig<T: Config> {
540		/// Genesis mapped accounts
541		pub mapped_accounts: Vec<T::AccountId>,
542	}
543
544	#[pallet::genesis_build]
545	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
546		fn build(&self) {
547			if !System::<T>::account_exists(&Pallet::<T>::account_id()) {
548				let _ = T::Currency::mint_into(
549					&Pallet::<T>::account_id(),
550					T::Currency::minimum_balance(),
551				);
552			}
553
554			for id in &self.mapped_accounts {
555				if let Err(err) = T::AddressMapper::map(id) {
556					log::error!(target: LOG_TARGET, "Failed to map account {id:?}: {err:?}");
557				}
558			}
559		}
560	}
561
562	#[pallet::hooks]
563	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
564		fn on_initialize(_block: BlockNumberFor<T>) -> Weight {
565			// Warm up the pallet account.
566			System::<T>::account_exists(&Pallet::<T>::account_id());
567			return T::DbWeight::get().reads(1)
568		}
569		fn on_idle(_block: BlockNumberFor<T>, limit: Weight) -> Weight {
570			let mut meter = WeightMeter::with_limit(limit);
571			ContractInfo::<T>::process_deletion_queue_batch(&mut meter);
572			meter.consumed()
573		}
574
575		fn integrity_test() {
576			assert!(T::ChainId::get() > 0, "ChainId must be greater than 0");
577
578			// The memory available in the block building runtime
579			let max_runtime_mem: u32 = T::RuntimeMemory::get();
580
581			// We only allow 50% of the runtime memory to be utilized by the contracts call
582			// stack, keeping the rest for other facilities, such as PoV, etc.
583			const TOTAL_MEMORY_DEVIDER: u32 = 2;
584
585			// Check that the configured memory limits fit into runtime memory.
586			//
587			// Dynamic allocations are not available, yet. Hence they are not taken into
588			// consideration here.
589			let memory_left = i64::from(max_runtime_mem)
590				.saturating_div(TOTAL_MEMORY_DEVIDER.into())
591				.saturating_sub(limits::MEMORY_REQUIRED.into());
592
593			log::debug!(target: LOG_TARGET, "Integrity check: memory_left={} KB", memory_left / 1024);
594
595			assert!(
596				memory_left >= 0,
597				"Runtime does not have enough memory for current limits. Additional runtime memory required: {} KB",
598				memory_left.saturating_mul(TOTAL_MEMORY_DEVIDER.into()).abs() / 1024
599			);
600
601			// Validators are configured to be able to use more memory than block builders. This is
602			// because in addition to `max_runtime_mem` they need to hold additional data in
603			// memory: PoV in multiple copies (1x encoded + 2x decoded) and all storage which
604			// includes emitted events. The assumption is that storage/events size
605			// can be a maximum of half of the validator runtime memory - max_runtime_mem.
606			let max_block_ref_time = T::BlockWeights::get()
607				.get(DispatchClass::Normal)
608				.max_total
609				.unwrap_or_else(|| T::BlockWeights::get().max_block)
610				.ref_time();
611			let max_payload_size = limits::PAYLOAD_BYTES;
612			let max_key_size =
613				Key::try_from_var(alloc::vec![0u8; limits::STORAGE_KEY_BYTES as usize])
614					.expect("Key of maximal size shall be created")
615					.hash()
616					.len() as u32;
617
618			let max_immutable_key_size = T::AccountId::max_encoded_len() as u32;
619			let max_immutable_size: u32 = ((max_block_ref_time /
620				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetImmutableData(
621					limits::IMMUTABLE_BYTES,
622				))
623				.ref_time()))
624			.saturating_mul(limits::IMMUTABLE_BYTES.saturating_add(max_immutable_key_size) as u64))
625			.try_into()
626			.expect("Immutable data size too big");
627
628			// We can use storage to store items using the available block ref_time with the
629			// `set_storage` host function.
630			let max_storage_size: u32 = ((max_block_ref_time /
631				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetStorage {
632					new_bytes: max_payload_size,
633					old_bytes: 0,
634				})
635				.ref_time()))
636			.saturating_mul(max_payload_size.saturating_add(max_key_size) as u64))
637			.saturating_add(max_immutable_size.into())
638			.try_into()
639			.expect("Storage size too big");
640
641			let max_pvf_mem: u32 = T::PVFMemory::get();
642			let storage_size_limit = max_pvf_mem.saturating_sub(max_runtime_mem) / 2;
643
644			assert!(
645				max_storage_size < storage_size_limit,
646				"Maximal storage size {} exceeds the storage limit {}",
647				max_storage_size,
648				storage_size_limit
649			);
650
651			// We can use storage to store events using the available block ref_time with the
652			// `deposit_event` host function. The overhead of stored events, which is around 100B,
653			// is not taken into account to simplify calculations, as it does not change much.
654			let max_events_size: u32 = ((max_block_ref_time /
655				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::DepositEvent {
656					num_topic: 0,
657					len: max_payload_size,
658				})
659				.saturating_add(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::HostFn))
660				.ref_time()))
661			.saturating_mul(max_payload_size as u64))
662			.try_into()
663			.expect("Events size too big");
664
665			assert!(
666				max_events_size < storage_size_limit,
667				"Maximal events size {} exceeds the events limit {}",
668				max_events_size,
669				storage_size_limit
670			);
671		}
672	}
673
674	#[pallet::call]
675	impl<T: Config> Pallet<T>
676	where
677		BalanceOf<T>: Into<U256> + TryFrom<U256>,
678		MomentOf<T>: Into<U256>,
679		T::Hash: frame_support::traits::IsType<H256>,
680	{
681		/// A raw EVM transaction, typically dispatched by an Ethereum JSON-RPC server.
682		///
683		/// # Parameters
684		///
685		/// * `payload`: The encoded [`crate::evm::TransactionSigned`].
686		/// * `gas_limit`: The gas limit enforced during contract execution.
687		/// * `storage_deposit_limit`: The maximum balance that can be charged to the caller for
688		///   storage usage.
689		///
690		/// # Note
691		///
692		/// This call cannot be dispatched directly; attempting to do so will result in a failed
693		/// transaction. It serves as a wrapper for an Ethereum transaction. When submitted, the
694		/// runtime converts it into a [`sp_runtime::generic::CheckedExtrinsic`] by recovering the
695		/// signer and validating the transaction.
696		#[allow(unused_variables)]
697		#[pallet::call_index(0)]
698		#[pallet::weight(Weight::MAX)]
699		pub fn eth_transact(origin: OriginFor<T>, payload: Vec<u8>) -> DispatchResultWithPostInfo {
700			Err(frame_system::Error::CallFiltered::<T>.into())
701		}
702
703		/// Makes a call to an account, optionally transferring some balance.
704		///
705		/// # Parameters
706		///
707		/// * `dest`: Address of the contract to call.
708		/// * `value`: The balance to transfer from the `origin` to `dest`.
709		/// * `gas_limit`: The gas limit enforced when executing the constructor.
710		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged from the
711		///   caller to pay for the storage consumed.
712		/// * `data`: The input data to pass to the contract.
713		///
714		/// * If the account is a smart-contract account, the associated code will be
715		/// executed and any value will be transferred.
716		/// * If the account is a regular account, any value will be transferred.
717		/// * If no account exists and the call value is not less than `existential_deposit`,
718		/// a regular account will be created and any value will be transferred.
719		#[pallet::call_index(1)]
720		#[pallet::weight(T::WeightInfo::call().saturating_add(*gas_limit))]
721		pub fn call(
722			origin: OriginFor<T>,
723			dest: H160,
724			#[pallet::compact] value: BalanceOf<T>,
725			gas_limit: Weight,
726			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
727			data: Vec<u8>,
728		) -> DispatchResultWithPostInfo {
729			let mut output = Self::bare_call(
730				origin,
731				dest,
732				Pallet::<T>::convert_native_to_evm(value),
733				gas_limit,
734				DepositLimit::Balance(storage_deposit_limit),
735				data,
736			);
737
738			if let Ok(return_value) = &output.result {
739				if return_value.did_revert() {
740					output.result = Err(<Error<T>>::ContractReverted.into());
741				}
742			}
743			dispatch_result(output.result, output.gas_consumed, T::WeightInfo::call())
744		}
745
746		/// Instantiates a contract from a previously deployed vm binary.
747		///
748		/// This function is identical to [`Self::instantiate_with_code`] but without the
749		/// code deployment step. Instead, the `code_hash` of an on-chain deployed vm binary
750		/// must be supplied.
751		#[pallet::call_index(2)]
752		#[pallet::weight(
753			T::WeightInfo::instantiate(data.len() as u32).saturating_add(*gas_limit)
754		)]
755		pub fn instantiate(
756			origin: OriginFor<T>,
757			#[pallet::compact] value: BalanceOf<T>,
758			gas_limit: Weight,
759			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
760			code_hash: sp_core::H256,
761			data: Vec<u8>,
762			salt: Option<[u8; 32]>,
763		) -> DispatchResultWithPostInfo {
764			let data_len = data.len() as u32;
765			let mut output = Self::bare_instantiate(
766				origin,
767				Pallet::<T>::convert_native_to_evm(value),
768				gas_limit,
769				DepositLimit::Balance(storage_deposit_limit),
770				Code::Existing(code_hash),
771				data,
772				salt,
773				BumpNonce::Yes,
774			);
775			if let Ok(retval) = &output.result {
776				if retval.result.did_revert() {
777					output.result = Err(<Error<T>>::ContractReverted.into());
778				}
779			}
780			dispatch_result(
781				output.result.map(|result| result.result),
782				output.gas_consumed,
783				T::WeightInfo::instantiate(data_len),
784			)
785		}
786
787		/// Instantiates a new contract from the supplied `code` optionally transferring
788		/// some balance.
789		///
790		/// This dispatchable has the same effect as calling [`Self::upload_code`] +
791		/// [`Self::instantiate`]. Bundling them together provides efficiency gains. Please
792		/// also check the documentation of [`Self::upload_code`].
793		///
794		/// # Parameters
795		///
796		/// * `value`: The balance to transfer from the `origin` to the newly created contract.
797		/// * `gas_limit`: The gas limit enforced when executing the constructor.
798		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved
799		///   from the caller to pay for the storage consumed.
800		/// * `code`: The contract code to deploy in raw bytes.
801		/// * `data`: The input data to pass to the contract constructor.
802		/// * `salt`: Used for the address derivation. If `Some` is supplied then `CREATE2`
803		/// 	semantics are used. If `None` then `CRATE1` is used.
804		///
805		///
806		/// Instantiation is executed as follows:
807		///
808		/// - The supplied `code` is deployed, and a `code_hash` is created for that code.
809		/// - If the `code_hash` already exists on the chain the underlying `code` will be shared.
810		/// - The destination address is computed based on the sender, code_hash and the salt.
811		/// - The smart-contract account is created at the computed address.
812		/// - The `value` is transferred to the new account.
813		/// - The `deploy` function is executed in the context of the newly-created account.
814		#[pallet::call_index(3)]
815		#[pallet::weight(
816			T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32)
817			.saturating_add(*gas_limit)
818		)]
819		pub fn instantiate_with_code(
820			origin: OriginFor<T>,
821			#[pallet::compact] value: BalanceOf<T>,
822			gas_limit: Weight,
823			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
824			code: Vec<u8>,
825			data: Vec<u8>,
826			salt: Option<[u8; 32]>,
827		) -> DispatchResultWithPostInfo {
828			let code_len = code.len() as u32;
829			let data_len = data.len() as u32;
830			let mut output = Self::bare_instantiate(
831				origin,
832				Pallet::<T>::convert_native_to_evm(value),
833				gas_limit,
834				DepositLimit::Balance(storage_deposit_limit),
835				Code::Upload(code),
836				data,
837				salt,
838				BumpNonce::Yes,
839			);
840			if let Ok(retval) = &output.result {
841				if retval.result.did_revert() {
842					output.result = Err(<Error<T>>::ContractReverted.into());
843				}
844			}
845			dispatch_result(
846				output.result.map(|result| result.result),
847				output.gas_consumed,
848				T::WeightInfo::instantiate_with_code(code_len, data_len),
849			)
850		}
851
852		/// Same as [`Self::instantiate_with_code`], but intended to be dispatched **only**
853		/// by an EVM transaction through the EVM compatibility layer.
854		///
855		/// Calling this dispatchable ensures that the origin's nonce is bumped only once,
856		/// via the `CheckNonce` transaction extension. In contrast, [`Self::instantiate_with_code`]
857		/// also bumps the nonce after contract instantiation, since it may be invoked multiple
858		/// times within a batch call transaction.
859		#[pallet::call_index(10)]
860		#[pallet::weight(
861			T::WeightInfo::eth_instantiate_with_code(code.len() as u32, data.len() as u32, Pallet::<T>::has_dust(*value).into())
862			.saturating_add(*gas_limit)
863		)]
864		pub fn eth_instantiate_with_code(
865			origin: OriginFor<T>,
866			value: U256,
867			gas_limit: Weight,
868			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
869			code: Vec<u8>,
870			data: Vec<u8>,
871		) -> DispatchResultWithPostInfo {
872			let code_len = code.len() as u32;
873			let data_len = data.len() as u32;
874			let mut output = Self::bare_instantiate(
875				origin,
876				value,
877				gas_limit,
878				DepositLimit::Balance(storage_deposit_limit),
879				Code::Upload(code),
880				data,
881				None,
882				BumpNonce::No,
883			);
884
885			if let Ok(retval) = &output.result {
886				if retval.result.did_revert() {
887					output.result = Err(<Error<T>>::ContractReverted.into());
888				}
889			}
890			dispatch_result(
891				output.result.map(|result| result.result),
892				output.gas_consumed,
893				T::WeightInfo::eth_instantiate_with_code(
894					code_len,
895					data_len,
896					Pallet::<T>::has_dust(value).into(),
897				),
898			)
899		}
900
901		/// Same as [`Self::call`], but intended to be dispatched **only**
902		/// by an EVM transaction through the EVM compatibility layer.
903		#[pallet::call_index(11)]
904		#[pallet::weight(T::WeightInfo::eth_call(Pallet::<T>::has_dust(*value).into()).saturating_add(*gas_limit))]
905		pub fn eth_call(
906			origin: OriginFor<T>,
907			dest: H160,
908			value: U256,
909			gas_limit: Weight,
910			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
911			data: Vec<u8>,
912		) -> DispatchResultWithPostInfo {
913			let mut output = Self::bare_call(
914				origin,
915				dest,
916				value,
917				gas_limit,
918				DepositLimit::Balance(storage_deposit_limit),
919				data,
920			);
921
922			if let Ok(return_value) = &output.result {
923				if return_value.did_revert() {
924					output.result = Err(<Error<T>>::ContractReverted.into());
925				}
926			}
927			dispatch_result(
928				output.result,
929				output.gas_consumed,
930				T::WeightInfo::eth_call(Pallet::<T>::has_dust(value).into()),
931			)
932		}
933
934		/// Upload new `code` without instantiating a contract from it.
935		///
936		/// If the code does not already exist a deposit is reserved from the caller
937		/// The size of the reserve depends on the size of the supplied `code`.
938		///
939		/// # Note
940		///
941		/// Anyone can instantiate a contract from any uploaded code and thus prevent its removal.
942		/// To avoid this situation a constructor could employ access control so that it can
943		/// only be instantiated by permissioned entities. The same is true when uploading
944		/// through [`Self::instantiate_with_code`].
945		///
946		/// If the refcount of the code reaches zero after terminating the last contract that
947		/// references this code, the code will be removed automatically.
948		#[pallet::call_index(4)]
949		#[pallet::weight(T::WeightInfo::upload_code(code.len() as u32))]
950		pub fn upload_code(
951			origin: OriginFor<T>,
952			code: Vec<u8>,
953			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
954		) -> DispatchResult {
955			Self::bare_upload_code(origin, code, storage_deposit_limit).map(|_| ())
956		}
957
958		/// Remove the code stored under `code_hash` and refund the deposit to its owner.
959		///
960		/// A code can only be removed by its original uploader (its owner) and only if it is
961		/// not used by any contract.
962		#[pallet::call_index(5)]
963		#[pallet::weight(T::WeightInfo::remove_code())]
964		pub fn remove_code(
965			origin: OriginFor<T>,
966			code_hash: sp_core::H256,
967		) -> DispatchResultWithPostInfo {
968			let origin = ensure_signed(origin)?;
969			<ContractBlob<T>>::remove(&origin, code_hash)?;
970			// we waive the fee because removing unused code is beneficial
971			Ok(Pays::No.into())
972		}
973
974		/// Privileged function that changes the code of an existing contract.
975		///
976		/// This takes care of updating refcounts and all other necessary operations. Returns
977		/// an error if either the `code_hash` or `dest` do not exist.
978		///
979		/// # Note
980		///
981		/// This does **not** change the address of the contract in question. This means
982		/// that the contract address is no longer derived from its code hash after calling
983		/// this dispatchable.
984		#[pallet::call_index(6)]
985		#[pallet::weight(T::WeightInfo::set_code())]
986		pub fn set_code(
987			origin: OriginFor<T>,
988			dest: H160,
989			code_hash: sp_core::H256,
990		) -> DispatchResult {
991			ensure_root(origin)?;
992			<AccountInfoOf<T>>::try_mutate(&dest, |account| {
993				let Some(account) = account else {
994					return Err(<Error<T>>::ContractNotFound.into());
995				};
996
997				let AccountType::Contract(ref mut contract) = account.account_type else {
998					return Err(<Error<T>>::ContractNotFound.into());
999				};
1000
1001				<CodeInfo<T>>::increment_refcount(code_hash)?;
1002				let _ = <CodeInfo<T>>::decrement_refcount(contract.code_hash)?;
1003				contract.code_hash = code_hash;
1004
1005				Ok(())
1006			})
1007		}
1008
1009		/// Register the callers account id so that it can be used in contract interactions.
1010		///
1011		/// This will error if the origin is already mapped or is a eth native `Address20`. It will
1012		/// take a deposit that can be released by calling [`Self::unmap_account`].
1013		#[pallet::call_index(7)]
1014		#[pallet::weight(T::WeightInfo::map_account())]
1015		pub fn map_account(origin: OriginFor<T>) -> DispatchResult {
1016			let origin = ensure_signed(origin)?;
1017			T::AddressMapper::map(&origin)
1018		}
1019
1020		/// Unregister the callers account id in order to free the deposit.
1021		///
1022		/// There is no reason to ever call this function other than freeing up the deposit.
1023		/// This is only useful when the account should no longer be used.
1024		#[pallet::call_index(8)]
1025		#[pallet::weight(T::WeightInfo::unmap_account())]
1026		pub fn unmap_account(origin: OriginFor<T>) -> DispatchResult {
1027			let origin = ensure_signed(origin)?;
1028			T::AddressMapper::unmap(&origin)
1029		}
1030
1031		/// Dispatch an `call` with the origin set to the callers fallback address.
1032		///
1033		/// Every `AccountId32` can control its corresponding fallback account. The fallback account
1034		/// is the `AccountId20` with the last 12 bytes set to `0xEE`. This is essentially a
1035		/// recovery function in case an `AccountId20` was used without creating a mapping first.
1036		#[pallet::call_index(9)]
1037		#[pallet::weight({
1038			let dispatch_info = call.get_dispatch_info();
1039			(
1040				T::WeightInfo::dispatch_as_fallback_account().saturating_add(dispatch_info.call_weight),
1041				dispatch_info.class
1042			)
1043		})]
1044		pub fn dispatch_as_fallback_account(
1045			origin: OriginFor<T>,
1046			call: Box<<T as Config>::RuntimeCall>,
1047		) -> DispatchResultWithPostInfo {
1048			let origin = ensure_signed(origin)?;
1049			let unmapped_account =
1050				T::AddressMapper::to_fallback_account_id(&T::AddressMapper::to_address(&origin));
1051			call.dispatch(RawOrigin::Signed(unmapped_account).into())
1052		}
1053	}
1054}
1055
1056/// Create a dispatch result reflecting the amount of consumed gas.
1057fn dispatch_result<R>(
1058	result: Result<R, DispatchError>,
1059	gas_consumed: Weight,
1060	base_weight: Weight,
1061) -> DispatchResultWithPostInfo {
1062	let post_info = PostDispatchInfo {
1063		actual_weight: Some(gas_consumed.saturating_add(base_weight)),
1064		pays_fee: Default::default(),
1065	};
1066
1067	result
1068		.map(|_| post_info)
1069		.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e })
1070}
1071
1072impl<T: Config> Pallet<T>
1073where
1074	BalanceOf<T>: Into<U256> + TryFrom<U256> + Bounded,
1075	MomentOf<T>: Into<U256>,
1076	T::Hash: frame_support::traits::IsType<H256>,
1077{
1078	/// A generalized version of [`Self::call`].
1079	///
1080	/// Identical to [`Self::call`] but tailored towards being called by other code within the
1081	/// runtime as opposed to from an extrinsic. It returns more information and allows the
1082	/// enablement of features that are not suitable for an extrinsic (debugging, event
1083	/// collection).
1084	pub fn bare_call(
1085		origin: OriginFor<T>,
1086		dest: H160,
1087		evm_value: U256,
1088		gas_limit: Weight,
1089		storage_deposit_limit: DepositLimit<BalanceOf<T>>,
1090		data: Vec<u8>,
1091	) -> ContractResult<ExecReturnValue, BalanceOf<T>> {
1092		let mut gas_meter = GasMeter::new(gas_limit);
1093		let mut storage_deposit = Default::default();
1094
1095		let try_call = || {
1096			let origin = Origin::from_runtime_origin(origin)?;
1097			let mut storage_meter = StorageMeter::new(storage_deposit_limit.limit());
1098			let result = ExecStack::<T, ContractBlob<T>>::run_call(
1099				origin.clone(),
1100				dest,
1101				&mut gas_meter,
1102				&mut storage_meter,
1103				evm_value,
1104				data,
1105				storage_deposit_limit.is_unchecked(),
1106			)?;
1107			storage_deposit = storage_meter
1108				.try_into_deposit(&origin, storage_deposit_limit.is_unchecked())
1109				.inspect_err(|err| {
1110					log::debug!(target: LOG_TARGET, "Failed to transfer deposit: {err:?}");
1111				})?;
1112			Ok(result)
1113		};
1114		let result = Self::run_guarded(try_call);
1115		ContractResult {
1116			result: result.map_err(|r| r.error),
1117			gas_consumed: gas_meter.gas_consumed(),
1118			gas_required: gas_meter.gas_required(),
1119			storage_deposit,
1120		}
1121	}
1122
1123	/// Prepare a dry run for the given account.
1124	///
1125	///
1126	/// This function is public because it is called by the runtime API implementation
1127	/// (see `impl_runtime_apis_plus_revive`).
1128	pub fn prepare_dry_run(account: &T::AccountId) {
1129		// Bump the  nonce to simulate what would happen
1130		// `pre-dispatch` if the transaction was executed.
1131		frame_system::Pallet::<T>::inc_account_nonce(account);
1132	}
1133
1134	/// A generalized version of [`Self::instantiate`] or [`Self::instantiate_with_code`].
1135	///
1136	/// Identical to [`Self::instantiate`] or [`Self::instantiate_with_code`] but tailored towards
1137	/// being called by other code within the runtime as opposed to from an extrinsic. It returns
1138	/// more information to the caller useful to estimate the cost of the operation.
1139	pub fn bare_instantiate(
1140		origin: OriginFor<T>,
1141		evm_value: U256,
1142		gas_limit: Weight,
1143		storage_deposit_limit: DepositLimit<BalanceOf<T>>,
1144		code: Code,
1145		data: Vec<u8>,
1146		salt: Option<[u8; 32]>,
1147		bump_nonce: BumpNonce,
1148	) -> ContractResult<InstantiateReturnValue, BalanceOf<T>> {
1149		let mut gas_meter = GasMeter::new(gas_limit);
1150		let mut storage_deposit = Default::default();
1151		let unchecked_deposit_limit = storage_deposit_limit.is_unchecked();
1152		let mut storage_deposit_limit = storage_deposit_limit.limit();
1153		let try_instantiate = || {
1154			let instantiate_account = T::InstantiateOrigin::ensure_origin(origin.clone())?;
1155
1156			if_tracing(|t| t.instantiate_code(&code, salt.as_ref()));
1157			let (executable, upload_deposit) = match code {
1158				Code::Upload(code) if code.starts_with(&polkavm_common::program::BLOB_MAGIC) => {
1159					let upload_account = T::UploadOrigin::ensure_origin(origin)?;
1160					let (executable, upload_deposit) = Self::try_upload_pvm_code(
1161						upload_account,
1162						code,
1163						storage_deposit_limit,
1164						unchecked_deposit_limit,
1165					)?;
1166					storage_deposit_limit.saturating_reduce(upload_deposit);
1167					(executable, upload_deposit)
1168				},
1169				Code::Upload(code) =>
1170					if T::AllowEVMBytecode::get() {
1171						let origin = T::UploadOrigin::ensure_origin(origin)?;
1172						let executable = ContractBlob::from_evm_init_code(code, origin)?;
1173						(executable, Default::default())
1174					} else {
1175						return Err(<Error<T>>::CodeRejected.into())
1176					},
1177				Code::Existing(code_hash) =>
1178					(ContractBlob::from_storage(code_hash, &mut gas_meter)?, Default::default()),
1179			};
1180			let instantiate_origin = Origin::from_account_id(instantiate_account.clone());
1181			let mut storage_meter = StorageMeter::new(storage_deposit_limit);
1182			let result = ExecStack::<T, ContractBlob<T>>::run_instantiate(
1183				instantiate_account,
1184				executable,
1185				&mut gas_meter,
1186				&mut storage_meter,
1187				evm_value,
1188				data,
1189				salt.as_ref(),
1190				unchecked_deposit_limit,
1191				bump_nonce,
1192			);
1193			storage_deposit = storage_meter
1194				.try_into_deposit(&instantiate_origin, unchecked_deposit_limit)?
1195				.saturating_add(&StorageDeposit::Charge(upload_deposit));
1196			result
1197		};
1198		let output = Self::run_guarded(try_instantiate);
1199		ContractResult {
1200			result: output
1201				.map(|(addr, result)| InstantiateReturnValue { result, addr })
1202				.map_err(|e| e.error),
1203			gas_consumed: gas_meter.gas_consumed(),
1204			gas_required: gas_meter.gas_required(),
1205			storage_deposit,
1206		}
1207	}
1208
1209	/// Dry-run Ethereum calls.
1210	///
1211	/// # Parameters
1212	///
1213	/// - `tx`: The Ethereum transaction to simulate.
1214	/// - `gas_limit`: The gas limit enforced during contract execution.
1215	/// - `tx_fee`: A function that returns the fee for the computed eth_transact and actual
1216	/// dispatched call
1217	pub fn dry_run_eth_transact(
1218		mut tx: GenericTransaction,
1219		gas_limit: Weight,
1220		tx_fee: impl Fn(<T as Config>::RuntimeCall, <T as Config>::RuntimeCall) -> BalanceOf<T>,
1221	) -> Result<EthTransactInfo<BalanceOf<T>>, EthTransactError>
1222	where
1223		<T as frame_system::Config>::RuntimeCall:
1224			Dispatchable<Info = frame_support::dispatch::DispatchInfo>,
1225		T: pallet_transaction_payment::Config,
1226		OnChargeTransactionBalanceOf<T>: Into<BalanceOf<T>>,
1227		<T as Config>::RuntimeCall: From<crate::Call<T>>,
1228		<T as Config>::RuntimeCall: Encode,
1229		T::Nonce: Into<U256>,
1230		T::Hash: frame_support::traits::IsType<H256>,
1231	{
1232		log::trace!(target: LOG_TARGET, "dry_run_eth_transact: {tx:?} gas_limit: {gas_limit:?}");
1233
1234		let from = tx.from.unwrap_or_default();
1235		let origin = T::AddressMapper::to_account_id(&from);
1236		Self::prepare_dry_run(&origin);
1237
1238		let storage_deposit_limit = if tx.gas.is_some() {
1239			DepositLimit::Balance(BalanceOf::<T>::max_value())
1240		} else {
1241			DepositLimit::UnsafeOnlyForDryRun
1242		};
1243
1244		if tx.nonce.is_none() {
1245			tx.nonce = Some(<System<T>>::account_nonce(&origin).into());
1246		}
1247		if tx.chain_id.is_none() {
1248			tx.chain_id = Some(T::ChainId::get().into());
1249		}
1250		if tx.gas_price.is_none() {
1251			tx.gas_price = Some(GAS_PRICE.into());
1252		}
1253		if tx.max_priority_fee_per_gas.is_none() {
1254			tx.max_priority_fee_per_gas = Some(GAS_PRICE.into());
1255		}
1256		if tx.max_fee_per_gas.is_none() {
1257			tx.max_fee_per_gas = Some(GAS_PRICE.into());
1258		}
1259		if tx.gas.is_none() {
1260			tx.gas = Some(Self::evm_block_gas_limit());
1261		}
1262		if tx.r#type.is_none() {
1263			tx.r#type = Some(TYPE_EIP1559.into());
1264		}
1265
1266		// Convert the value to the native balance type.
1267		let value = tx.value.unwrap_or_default();
1268		let input = tx.input.clone().to_vec();
1269
1270		let extract_error = |err| {
1271			if err == Error::<T>::TransferFailed.into() ||
1272				err == Error::<T>::StorageDepositNotEnoughFunds.into() ||
1273				err == Error::<T>::StorageDepositLimitExhausted.into()
1274			{
1275				let balance = Self::evm_balance(&from);
1276				return Err(EthTransactError::Message(format!(
1277					"insufficient funds for gas * price + value: address {from:?} have {balance} (supplied gas {})",
1278					tx.gas.unwrap_or_default()
1279				)));
1280			}
1281
1282			return Err(EthTransactError::Message(format!(
1283				"Failed to instantiate contract: {err:?}"
1284			)));
1285		};
1286
1287		// Dry run the call
1288		let (mut result, dispatch_call) = match tx.to {
1289			// A contract call.
1290			Some(dest) => {
1291				if dest == RUNTIME_PALLETS_ADDR {
1292					let Ok(dispatch_call) = <T as Config>::RuntimeCall::decode(&mut &input[..])
1293					else {
1294						return Err(EthTransactError::Message(format!(
1295							"Failed to decode pallet-call {input:?}"
1296						)));
1297					};
1298
1299					if let Err(err) =
1300						dispatch_call.clone().dispatch(RawOrigin::Signed(origin).into())
1301					{
1302						return Err(EthTransactError::Message(format!(
1303							"Failed to dispatch call: {err:?}"
1304						)));
1305					};
1306
1307					let result = EthTransactInfo {
1308						gas_required: dispatch_call.get_dispatch_info().total_weight(),
1309						..Default::default()
1310					};
1311
1312					(result, dispatch_call)
1313				} else {
1314					// Dry run the call.
1315					let result = crate::Pallet::<T>::bare_call(
1316						T::RuntimeOrigin::signed(origin),
1317						dest,
1318						value,
1319						gas_limit,
1320						storage_deposit_limit,
1321						input.clone(),
1322					);
1323
1324					let data = match result.result {
1325						Ok(return_value) => {
1326							if return_value.did_revert() {
1327								return Err(EthTransactError::Data(return_value.data));
1328							}
1329							return_value.data
1330						},
1331						Err(err) => {
1332							log::debug!(target: LOG_TARGET, "Failed to execute call: {err:?}");
1333							return extract_error(err);
1334						},
1335					};
1336
1337					let result = EthTransactInfo {
1338						gas_required: result.gas_required,
1339						storage_deposit: result.storage_deposit.charge_or_zero(),
1340						data,
1341						eth_gas: Default::default(),
1342					};
1343
1344					let (gas_limit, storage_deposit_limit) = T::EthGasEncoder::as_encoded_values(
1345						result.gas_required,
1346						result.storage_deposit,
1347					);
1348					let dispatch_call: <T as Config>::RuntimeCall = crate::Call::<T>::eth_call {
1349						dest,
1350						value,
1351						gas_limit,
1352						storage_deposit_limit,
1353						data: input.clone(),
1354					}
1355					.into();
1356					(result, dispatch_call)
1357				}
1358			},
1359			// A contract deployment
1360			None => {
1361				// Extract code and data from the input.
1362				let (code, data) = if input.starts_with(&polkavm_common::program::BLOB_MAGIC) {
1363					extract_code_and_data(&input).unwrap_or_else(|| (input, Default::default()))
1364				} else {
1365					(input, vec![])
1366				};
1367
1368				// Dry run the call.
1369				let result = crate::Pallet::<T>::bare_instantiate(
1370					T::RuntimeOrigin::signed(origin),
1371					value,
1372					gas_limit,
1373					storage_deposit_limit,
1374					Code::Upload(code.clone()),
1375					data.clone(),
1376					None,
1377					BumpNonce::No,
1378				);
1379
1380				let returned_data = match result.result {
1381					Ok(return_value) => {
1382						if return_value.result.did_revert() {
1383							return Err(EthTransactError::Data(return_value.result.data));
1384						}
1385						return_value.result.data
1386					},
1387					Err(err) => {
1388						log::debug!(target: LOG_TARGET, "Failed to instantiate: {err:?}");
1389						return extract_error(err);
1390					},
1391				};
1392
1393				let result = EthTransactInfo {
1394					gas_required: result.gas_required,
1395					storage_deposit: result.storage_deposit.charge_or_zero(),
1396					data: returned_data,
1397					eth_gas: Default::default(),
1398				};
1399
1400				// Get the dispatch info of the call.
1401				let (gas_limit, storage_deposit_limit) = T::EthGasEncoder::as_encoded_values(
1402					result.gas_required,
1403					result.storage_deposit,
1404				);
1405				let dispatch_call: <T as Config>::RuntimeCall =
1406					crate::Call::<T>::eth_instantiate_with_code {
1407						value,
1408						gas_limit,
1409						storage_deposit_limit,
1410						code,
1411						data,
1412					}
1413					.into();
1414				(result, dispatch_call)
1415			},
1416		};
1417
1418		let Ok(unsigned_tx) = tx.clone().try_into_unsigned() else {
1419			return Err(EthTransactError::Message("Invalid transaction".into()));
1420		};
1421
1422		let eth_transact_call =
1423			crate::Call::<T>::eth_transact { payload: unsigned_tx.dummy_signed_payload() };
1424		let fee = tx_fee(eth_transact_call.into(), dispatch_call);
1425		let raw_gas = Self::evm_fee_to_gas(fee);
1426		let eth_gas =
1427			T::EthGasEncoder::encode(raw_gas, result.gas_required, result.storage_deposit);
1428
1429		log::trace!(target: LOG_TARGET, "bare_eth_call: raw_gas: {raw_gas:?} eth_gas: {eth_gas:?}");
1430		result.eth_gas = eth_gas;
1431		Ok(result)
1432	}
1433
1434	/// Get the balance with EVM decimals of the given `address`.
1435	pub fn evm_balance(address: &H160) -> U256 {
1436		let balance = AccountInfo::<T>::balance((*address).into());
1437		Self::convert_native_to_evm(balance)
1438	}
1439
1440	/// Get the nonce for the given `address`.
1441	pub fn evm_nonce(address: &H160) -> u32
1442	where
1443		T::Nonce: Into<u32>,
1444	{
1445		let account = T::AddressMapper::to_account_id(&address);
1446		System::<T>::account_nonce(account).into()
1447	}
1448
1449	/// Convert a substrate fee into a gas value, using the fixed `GAS_PRICE`.
1450	/// The gas is calculated as `fee / GAS_PRICE`, rounded up to the nearest integer.
1451	pub fn evm_fee_to_gas(fee: BalanceOf<T>) -> U256 {
1452		let fee = Self::convert_native_to_evm(fee);
1453		let gas_price = GAS_PRICE.into();
1454		let (quotient, remainder) = fee.div_mod(gas_price);
1455		if remainder.is_zero() {
1456			quotient
1457		} else {
1458			quotient + U256::one()
1459		}
1460	}
1461
1462	/// Convert a gas value into a substrate fee
1463	fn evm_gas_to_fee(gas: U256, gas_price: U256) -> Result<BalanceOf<T>, Error<T>> {
1464		let fee = gas.saturating_mul(gas_price);
1465		let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(fee)?;
1466		Ok(value.into_rounded_balance())
1467	}
1468
1469	/// Convert a weight to a gas value.
1470	pub fn evm_gas_from_weight(weight: Weight) -> U256 {
1471		let fee = T::WeightPrice::convert(weight);
1472		Self::evm_fee_to_gas(fee)
1473	}
1474
1475	/// Get the block gas limit.
1476	pub fn evm_block_gas_limit() -> U256
1477	where
1478		<T as frame_system::Config>::RuntimeCall:
1479			Dispatchable<Info = frame_support::dispatch::DispatchInfo>,
1480		T: pallet_transaction_payment::Config,
1481		OnChargeTransactionBalanceOf<T>: Into<BalanceOf<T>>,
1482	{
1483		let max_block_weight = T::BlockWeights::get()
1484			.get(DispatchClass::Normal)
1485			.max_total
1486			.unwrap_or_else(|| T::BlockWeights::get().max_block);
1487
1488		let length_fee = pallet_transaction_payment::Pallet::<T>::length_to_fee(
1489			5 * 1024 * 1024, // 5 MB
1490		);
1491
1492		Self::evm_gas_from_weight(max_block_weight)
1493			.saturating_add(Self::evm_fee_to_gas(length_fee.into()))
1494	}
1495
1496	/// Get the gas price.
1497	pub fn evm_gas_price() -> U256 {
1498		GAS_PRICE.into()
1499	}
1500
1501	/// Build an EVM tracer from the given tracer type.
1502	pub fn evm_tracer(tracer_type: TracerType) -> Tracer<T>
1503	where
1504		T::Nonce: Into<u32>,
1505	{
1506		match tracer_type {
1507			TracerType::CallTracer(config) => CallTracer::new(
1508				config.unwrap_or_default(),
1509				Self::evm_gas_from_weight as fn(Weight) -> U256,
1510			)
1511			.into(),
1512			TracerType::PrestateTracer(config) =>
1513				PrestateTracer::new(config.unwrap_or_default()).into(),
1514		}
1515	}
1516
1517	/// A generalized version of [`Self::upload_code`].
1518	///
1519	/// It is identical to [`Self::upload_code`] and only differs in the information it returns.
1520	pub fn bare_upload_code(
1521		origin: OriginFor<T>,
1522		code: Vec<u8>,
1523		storage_deposit_limit: BalanceOf<T>,
1524	) -> CodeUploadResult<BalanceOf<T>> {
1525		let origin = T::UploadOrigin::ensure_origin(origin)?;
1526		let (module, deposit) =
1527			Self::try_upload_pvm_code(origin, code, storage_deposit_limit, false)?;
1528		Ok(CodeUploadReturnValue { code_hash: *module.code_hash(), deposit })
1529	}
1530
1531	/// Query storage of a specified contract under a specified key.
1532	pub fn get_storage(address: H160, key: [u8; 32]) -> GetStorageResult {
1533		let contract_info =
1534			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
1535
1536		let maybe_value = contract_info.read(&Key::from_fixed(key));
1537		Ok(maybe_value)
1538	}
1539
1540	/// Query storage of a specified contract under a specified variable-sized key.
1541	pub fn get_storage_var_key(address: H160, key: Vec<u8>) -> GetStorageResult {
1542		let contract_info =
1543			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
1544
1545		let maybe_value = contract_info.read(
1546			&Key::try_from_var(key)
1547				.map_err(|_| ContractAccessError::KeyDecodingFailed)?
1548				.into(),
1549		);
1550		Ok(maybe_value)
1551	}
1552
1553	/// Uploads new code and returns the Vm binary contract blob and deposit amount collected.
1554	fn try_upload_pvm_code(
1555		origin: T::AccountId,
1556		code: Vec<u8>,
1557		storage_deposit_limit: BalanceOf<T>,
1558		skip_transfer: bool,
1559	) -> Result<(ContractBlob<T>, BalanceOf<T>), DispatchError> {
1560		let mut module = ContractBlob::from_pvm_code(code, origin)?;
1561		let deposit = module.store_code(skip_transfer)?;
1562		ensure!(storage_deposit_limit >= deposit, <Error<T>>::StorageDepositLimitExhausted);
1563		Ok((module, deposit))
1564	}
1565
1566	/// Run the supplied function `f` if no other instance of this pallet is on the stack.
1567	fn run_guarded<R, F: FnOnce() -> Result<R, ExecError>>(f: F) -> Result<R, ExecError> {
1568		executing_contract::using_once(&mut false, || {
1569			executing_contract::with(|f| {
1570				// Fail if already entered contract execution
1571				if *f {
1572					return Err(())
1573				}
1574				// We are entering contract execution
1575				*f = true;
1576				Ok(())
1577			})
1578				.expect("Returns `Ok` if called within `using_once`. It is syntactically obvious that this is the case; qed")
1579				.map_err(|_| <Error<T>>::ReenteredPallet.into())
1580				.map(|_| f())
1581				.and_then(|r| r)
1582		})
1583	}
1584
1585	/// Convert a native balance to EVM balance.
1586	pub fn convert_native_to_evm(value: impl Into<BalanceWithDust<BalanceOf<T>>>) -> U256 {
1587		let (value, dust) = value.into().deconstruct();
1588		value
1589			.into()
1590			.saturating_mul(T::NativeToEthRatio::get().into())
1591			.saturating_add(dust.into())
1592	}
1593}
1594
1595impl<T: Config> Pallet<T> {
1596	/// Pallet account, used to hold funds for contracts upload deposit.
1597	pub fn account_id() -> T::AccountId {
1598		use frame_support::PalletId;
1599		use sp_runtime::traits::AccountIdConversion;
1600		PalletId(*b"py/reviv").into_account_truncating()
1601	}
1602
1603	/// Returns true if the evm value carries dust.
1604	fn has_dust(value: U256) -> bool {
1605		value % U256::from(<T>::NativeToEthRatio::get()) != U256::zero()
1606	}
1607
1608	/// Returns true if the evm value carries balance.
1609	fn has_balance(value: U256) -> bool {
1610		value >= U256::from(<T>::NativeToEthRatio::get())
1611	}
1612
1613	/// Return the existential deposit of [`Config::Currency`].
1614	fn min_balance() -> BalanceOf<T> {
1615		<T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
1616	}
1617
1618	/// Deposit a pallet revive event.
1619	fn deposit_event(event: Event<T>) {
1620		<frame_system::Pallet<T>>::deposit_event(<T as Config>::RuntimeEvent::from(event))
1621	}
1622
1623	/// The address of the validator that produced the current block.
1624	pub fn block_author() -> Option<H160> {
1625		use frame_support::traits::FindAuthor;
1626
1627		let digest = <frame_system::Pallet<T>>::digest();
1628		let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime());
1629
1630		let account_id = T::FindAuthor::find_author(pre_runtime_digests)?;
1631		Some(T::AddressMapper::to_address(&account_id))
1632	}
1633
1634	/// Returns the code at `address`.
1635	///
1636	/// This takes pre-compiles into account.
1637	pub fn code(address: &H160) -> Vec<u8> {
1638		use precompiles::{All, Precompiles};
1639		if let Some(code) = <All<T>>::code(address.as_fixed_bytes()) {
1640			return code.into()
1641		}
1642		AccountInfo::<T>::load_contract(&address)
1643			.and_then(|contract| <PristineCode<T>>::get(contract.code_hash))
1644			.map(|code| code.into())
1645			.unwrap_or_default()
1646	}
1647}
1648
1649/// The address used to call the runtime's pallets dispatchables
1650///
1651/// Note:
1652/// computed with PalletId(*b"py/paddr").into_account_truncating();
1653pub const RUNTIME_PALLETS_ADDR: H160 =
1654	H160(hex_literal::hex!("6d6f646c70792f70616464720000000000000000"));
1655
1656// Set up a global reference to the boolean flag used for the re-entrancy guard.
1657environmental!(executing_contract: bool);
1658
1659sp_api::decl_runtime_apis! {
1660	/// The API used to dry-run contract interactions.
1661	#[api_version(1)]
1662	pub trait ReviveApi<AccountId, Balance, Nonce, BlockNumber> where
1663		AccountId: Codec,
1664		Balance: Codec,
1665		Nonce: Codec,
1666		BlockNumber: Codec,
1667	{
1668		/// Returns the block gas limit.
1669		fn block_gas_limit() -> U256;
1670
1671		/// Returns the free balance of the given `[H160]` address, using EVM decimals.
1672		fn balance(address: H160) -> U256;
1673
1674		/// Returns the gas price.
1675		fn gas_price() -> U256;
1676
1677		/// Returns the nonce of the given `[H160]` address.
1678		fn nonce(address: H160) -> Nonce;
1679
1680		/// Perform a call from a specified account to a given contract.
1681		///
1682		/// See [`crate::Pallet::bare_call`].
1683		fn call(
1684			origin: AccountId,
1685			dest: H160,
1686			value: Balance,
1687			gas_limit: Option<Weight>,
1688			storage_deposit_limit: Option<Balance>,
1689			input_data: Vec<u8>,
1690		) -> ContractResult<ExecReturnValue, Balance>;
1691
1692		/// Instantiate a new contract.
1693		///
1694		/// See `[crate::Pallet::bare_instantiate]`.
1695		fn instantiate(
1696			origin: AccountId,
1697			value: Balance,
1698			gas_limit: Option<Weight>,
1699			storage_deposit_limit: Option<Balance>,
1700			code: Code,
1701			data: Vec<u8>,
1702			salt: Option<[u8; 32]>,
1703		) -> ContractResult<InstantiateReturnValue, Balance>;
1704
1705
1706		/// Perform an Ethereum call.
1707		///
1708		/// See [`crate::Pallet::dry_run_eth_transact`]
1709		fn eth_transact(tx: GenericTransaction) -> Result<EthTransactInfo<Balance>, EthTransactError>;
1710
1711		/// Upload new code without instantiating a contract from it.
1712		///
1713		/// See [`crate::Pallet::bare_upload_code`].
1714		fn upload_code(
1715			origin: AccountId,
1716			code: Vec<u8>,
1717			storage_deposit_limit: Option<Balance>,
1718		) -> CodeUploadResult<Balance>;
1719
1720		/// Query a given storage key in a given contract.
1721		///
1722		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
1723		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
1724		/// doesn't exist, or doesn't have a contract then `Err` is returned.
1725		fn get_storage(
1726			address: H160,
1727			key: [u8; 32],
1728		) -> GetStorageResult;
1729
1730		/// Query a given variable-sized storage key in a given contract.
1731		///
1732		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
1733		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
1734		/// doesn't exist, or doesn't have a contract then `Err` is returned.
1735		fn get_storage_var_key(
1736			address: H160,
1737			key: Vec<u8>,
1738		) -> GetStorageResult;
1739
1740		/// Traces the execution of an entire block and returns call traces.
1741		///
1742		/// This is intended to be called through `state_call` to replay the block from the
1743		/// parent block.
1744		///
1745		/// See eth-rpc `debug_traceBlockByNumber` for usage.
1746		fn trace_block(
1747			block: Block,
1748			config: TracerType
1749		) -> Vec<(u32, Trace)>;
1750
1751		/// Traces the execution of a specific transaction within a block.
1752		///
1753		/// This is intended to be called through `state_call` to replay the block from the
1754		/// parent hash up to the transaction.
1755		///
1756		/// See eth-rpc `debug_traceTransaction` for usage.
1757		fn trace_tx(
1758			block: Block,
1759			tx_index: u32,
1760			config: TracerType
1761		) -> Option<Trace>;
1762
1763		/// Dry run and return the trace of the given call.
1764		///
1765		/// See eth-rpc `debug_traceCall` for usage.
1766		fn trace_call(tx: GenericTransaction, config: TracerType) -> Result<Trace, EthTransactError>;
1767
1768		/// The address of the validator that produced the current block.
1769		fn block_author() -> Option<H160>;
1770
1771		/// Get the H160 address associated to this account id
1772		fn address(account_id: AccountId) -> H160;
1773
1774		/// The address used to call the runtime's pallets dispatchables
1775		fn runtime_pallets_address() -> H160;
1776
1777		/// The code at the specified address taking pre-compiles into account.
1778		fn code(address: H160) -> Vec<u8>;
1779	}
1780}
1781
1782/// This macro wraps substrate's `impl_runtime_apis!` and implements `pallet_revive` runtime APIs.
1783///
1784/// # Parameters
1785/// - `$Runtime`: The runtime type to implement the APIs for.
1786/// - `$Executive`: The Executive type of the runtime.
1787/// - `$EthExtra`: Type for additional Ethereum runtime extension.
1788/// - `$($rest:tt)*`: Remaining input to be forwarded to the underlying `impl_runtime_apis!`.
1789#[macro_export]
1790macro_rules! impl_runtime_apis_plus_revive {
1791	($Runtime: ty, $Executive: ty, $EthExtra: ty, $($rest:tt)*) => {
1792
1793		impl_runtime_apis! {
1794			$($rest)*
1795
1796			impl pallet_revive::ReviveApi<Block, AccountId, Balance, Nonce, BlockNumber> for $Runtime {
1797				fn balance(address: $crate::H160) -> $crate::U256 {
1798					$crate::Pallet::<Self>::evm_balance(&address)
1799				}
1800
1801				fn block_author() -> Option<$crate::H160> {
1802					$crate::Pallet::<Self>::block_author()
1803				}
1804
1805				fn block_gas_limit() -> $crate::U256 {
1806					$crate::Pallet::<Self>::evm_block_gas_limit()
1807				}
1808
1809				fn gas_price() -> $crate::U256 {
1810					$crate::Pallet::<Self>::evm_gas_price()
1811				}
1812
1813				fn nonce(address: $crate::H160) -> Nonce {
1814					use $crate::AddressMapper;
1815					let account = <Self as $crate::Config>::AddressMapper::to_account_id(&address);
1816					$crate::frame_system::Pallet::<Self>::account_nonce(account)
1817				}
1818
1819				fn address(account_id: AccountId) -> $crate::H160 {
1820					use $crate::AddressMapper;
1821					<Self as $crate::Config>::AddressMapper::to_address(&account_id)
1822				}
1823
1824				fn eth_transact(
1825					tx: $crate::evm::GenericTransaction,
1826				) -> Result<$crate::EthTransactInfo<Balance>, $crate::EthTransactError> {
1827					use $crate::{
1828						codec::Encode, evm::runtime::EthExtra, frame_support::traits::Get,
1829						sp_runtime::traits::TransactionExtension,
1830						sp_runtime::traits::Block as BlockT
1831					};
1832
1833					let tx_fee = |call: <Self as $crate::frame_system::Config>::RuntimeCall, dispatch_call: <Self as $crate::frame_system::Config>::RuntimeCall| {
1834						use $crate::frame_support::dispatch::GetDispatchInfo;
1835
1836						// Get the dispatch info of the actual call dispatched
1837						let mut dispatch_info = dispatch_call.get_dispatch_info();
1838						dispatch_info.extension_weight =
1839							<$EthExtra>::get_eth_extension(0, 0u32.into()).weight(&dispatch_call);
1840
1841						// Build the extrinsic
1842						let uxt: <Block as BlockT>::Extrinsic =
1843							$crate::sp_runtime::generic::UncheckedExtrinsic::new_bare(call).into();
1844
1845						// Compute the fee of the extrinsic
1846						$crate::pallet_transaction_payment::Pallet::<Self>::compute_fee(
1847							uxt.encoded_size() as u32,
1848							&dispatch_info,
1849							0u32.into(),
1850						)
1851					};
1852
1853					let blockweights: $crate::BlockWeights =
1854						<Self as $crate::frame_system::Config>::BlockWeights::get();
1855					$crate::Pallet::<Self>::dry_run_eth_transact(tx, blockweights.max_block, tx_fee)
1856				}
1857
1858				fn call(
1859					origin: AccountId,
1860					dest: $crate::H160,
1861					value: Balance,
1862					gas_limit: Option<$crate::Weight>,
1863					storage_deposit_limit: Option<Balance>,
1864					input_data: Vec<u8>,
1865				) -> $crate::ContractResult<$crate::ExecReturnValue, Balance> {
1866					use $crate::frame_support::traits::Get;
1867					let blockweights: $crate::BlockWeights =
1868						<Self as $crate::frame_system::Config>::BlockWeights::get();
1869
1870					$crate::Pallet::<Self>::prepare_dry_run(&origin);
1871					$crate::Pallet::<Self>::bare_call(
1872						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin),
1873						dest,
1874						$crate::Pallet::<Self>::convert_native_to_evm(value),
1875						gas_limit.unwrap_or(blockweights.max_block),
1876						$crate::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)),
1877						input_data,
1878					)
1879				}
1880
1881				fn instantiate(
1882					origin: AccountId,
1883					value: Balance,
1884					gas_limit: Option<$crate::Weight>,
1885					storage_deposit_limit: Option<Balance>,
1886					code: $crate::Code,
1887					data: Vec<u8>,
1888					salt: Option<[u8; 32]>,
1889				) -> $crate::ContractResult<$crate::InstantiateReturnValue, Balance> {
1890					use $crate::frame_support::traits::Get;
1891					let blockweights: $crate::BlockWeights =
1892						<Self as $crate::frame_system::Config>::BlockWeights::get();
1893
1894					$crate::Pallet::<Self>::prepare_dry_run(&origin);
1895					$crate::Pallet::<Self>::bare_instantiate(
1896						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin),
1897						$crate::Pallet::<Self>::convert_native_to_evm(value),
1898						gas_limit.unwrap_or(blockweights.max_block),
1899						$crate::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)),
1900						code,
1901						data,
1902						salt,
1903						$crate::BumpNonce::Yes,
1904					)
1905				}
1906
1907				fn upload_code(
1908					origin: AccountId,
1909					code: Vec<u8>,
1910					storage_deposit_limit: Option<Balance>,
1911				) -> $crate::CodeUploadResult<Balance> {
1912					let origin =
1913						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin);
1914					$crate::Pallet::<Self>::bare_upload_code(
1915						origin,
1916						code,
1917						storage_deposit_limit.unwrap_or(u128::MAX),
1918					)
1919				}
1920
1921				fn get_storage_var_key(
1922					address: $crate::H160,
1923					key: Vec<u8>,
1924				) -> $crate::GetStorageResult {
1925					$crate::Pallet::<Self>::get_storage_var_key(address, key)
1926				}
1927
1928				fn get_storage(address: $crate::H160, key: [u8; 32]) -> $crate::GetStorageResult {
1929					$crate::Pallet::<Self>::get_storage(address, key)
1930				}
1931
1932				fn trace_block(
1933					block: Block,
1934					tracer_type: $crate::evm::TracerType,
1935				) -> Vec<(u32, $crate::evm::Trace)> {
1936					use $crate::{sp_runtime::traits::Block, tracing::trace};
1937					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type);
1938					let mut traces = vec![];
1939					let (header, extrinsics) = block.deconstruct();
1940					<$Executive>::initialize_block(&header);
1941					for (index, ext) in extrinsics.into_iter().enumerate() {
1942						let t = tracer.as_tracing();
1943						let _ = trace(t, || <$Executive>::apply_extrinsic(ext));
1944
1945						if let Some(tx_trace) = tracer.collect_trace() {
1946							traces.push((index as u32, tx_trace));
1947						}
1948					}
1949
1950					traces
1951				}
1952
1953				fn trace_tx(
1954					block: Block,
1955					tx_index: u32,
1956					tracer_type: $crate::evm::TracerType,
1957				) -> Option<$crate::evm::Trace> {
1958					use $crate::{sp_runtime::traits::Block, tracing::trace};
1959
1960					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type);
1961					let (header, extrinsics) = block.deconstruct();
1962
1963					<$Executive>::initialize_block(&header);
1964					for (index, ext) in extrinsics.into_iter().enumerate() {
1965						if index as u32 == tx_index {
1966							let t = tracer.as_tracing();
1967							let _ = trace(t, || <$Executive>::apply_extrinsic(ext));
1968							break;
1969						} else {
1970							let _ = <$Executive>::apply_extrinsic(ext);
1971						}
1972					}
1973
1974					tracer.collect_trace()
1975				}
1976
1977				fn trace_call(
1978					tx: $crate::evm::GenericTransaction,
1979					tracer_type: $crate::evm::TracerType,
1980				) -> Result<$crate::evm::Trace, $crate::EthTransactError> {
1981					use $crate::tracing::trace;
1982					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type);
1983					let t = tracer.as_tracing();
1984
1985					t.watch_address(&tx.from.unwrap_or_default());
1986					t.watch_address(&$crate::Pallet::<Self>::block_author().unwrap_or_default());
1987					let result = trace(t, || Self::eth_transact(tx));
1988
1989					if let Some(trace) = tracer.collect_trace() {
1990						Ok(trace)
1991					} else if let Err(err) = result {
1992						Err(err)
1993					} else {
1994						Ok(tracer.empty_trace())
1995					}
1996				}
1997
1998				fn runtime_pallets_address() -> $crate::H160 {
1999					$crate::RUNTIME_PALLETS_ADDR
2000				}
2001
2002				fn code(address: $crate::H160) -> Vec<u8> {
2003					$crate::Pallet::<Self>::code(&address)
2004				}
2005			}
2006		}
2007	};
2008}