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