Skip to main content

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;
27#[cfg(any(feature = "runtime-benchmarks", test))]
28pub mod call_builder;
29mod debug;
30mod exec;
31mod impl_fungibles;
32mod limits;
33mod metering;
34mod primitives;
35mod storage;
36#[cfg(test)]
37mod tests;
38mod transient_storage;
39mod vm;
40mod weightinfo_extension;
41
42pub mod evm;
43pub mod migrations;
44pub mod mock;
45pub mod precompiles;
46pub mod test_utils;
47pub mod tracing;
48pub mod weights;
49
50use crate::{
51	evm::{
52		CallTracer, CreateCallMode, ExecutionTracer, GenericTransaction, PrestateTracer,
53		TYPE_EIP1559, Trace, Tracer, TracerType, block_hash::EthereumBlockBuilderIR, block_storage,
54		fees::InfoT as FeeInfo, runtime::SetWeightLimit,
55	},
56	exec::{AccountIdOf, ExecError, ReentrancyProtection, Stack as ExecStack},
57	sp_runtime::TransactionOutcome,
58	storage::{AccountType, DeletionQueueManager},
59	tracing::if_tracing,
60	vm::{CodeInfo, RuntimeCosts, pvm::extract_code_and_data},
61	weightinfo_extension::OnFinalizeBlockParts,
62};
63use alloc::{boxed::Box, format, vec};
64use codec::{Codec, Decode, Encode};
65use environmental::*;
66use frame_support::{
67	BoundedVec,
68	dispatch::{
69		DispatchErrorWithPostInfo, DispatchResult, DispatchResultWithPostInfo, GetDispatchInfo,
70		Pays, PostDispatchInfo, RawOrigin,
71	},
72	ensure,
73	pallet_prelude::DispatchClass,
74	storage::with_transaction,
75	traits::{
76		ConstU32, ConstU64, EnsureOrigin, Get, IsSubType, IsType, OnUnbalanced, OriginTrait,
77		fungible::{Balanced, Credit, Inspect, Mutate, MutateHold},
78		tokens::Balance,
79	},
80	weights::WeightMeter,
81};
82use frame_system::{
83	Pallet as System, ensure_signed,
84	pallet_prelude::{BlockNumberFor, OriginFor},
85};
86use scale_info::TypeInfo;
87use sp_runtime::{
88	AccountId32, DispatchError, FixedPointNumber, FixedU128, SaturatedConversion,
89	traits::{
90		BadOrigin, Bounded, Convert, Dispatchable, Saturating, UniqueSaturatedFrom,
91		UniqueSaturatedInto, Zero,
92	},
93};
94
95pub use crate::{
96	address::{
97		AccountId32Mapper, AddressMapper, TestAccountMapper, create1, create2, is_eth_derived,
98	},
99	debug::DebugSettings,
100	evm::{
101		Address as EthAddress, Block as EthBlock, DryRunConfig, ReceiptInfo,
102		block_hash::ReceiptGasInfo,
103	},
104	exec::{CallResources, DelegateInfo, Executable, Key, MomentOf, Origin as ExecOrigin},
105	limits::TRANSIENT_STORAGE_BYTES as TRANSIENT_STORAGE_LIMIT,
106	metering::{
107		EthTxInfo, FrameMeter, ResourceMeter, Token as WeightToken, TransactionLimits,
108		TransactionMeter,
109	},
110	pallet::{genesis, *},
111	storage::{AccountInfo, ContractInfo},
112	transient_storage::{MeterEntry, StorageMeter as TransientStorageMeter, TransientStorage},
113	vm::{BytecodeType, ContractBlob},
114};
115pub use codec;
116pub use frame_support::{self, dispatch::DispatchInfo, traits::Time, weights::Weight};
117pub use frame_system::{self, limits::BlockWeights};
118pub use primitives::*;
119pub use sp_core::{H160, H256, U256, keccak_256};
120pub use sp_runtime;
121pub use weights::WeightInfo;
122
123#[cfg(doc)]
124pub use crate::vm::pvm::SyscallDoc;
125
126pub type BalanceOf<T> = <T as Config>::Balance;
127pub type CreditOf<T> = Credit<<T as frame_system::Config>::AccountId, <T as Config>::Currency>;
128type TrieId = BoundedVec<u8, ConstU32<128>>;
129type ImmutableData = BoundedVec<u8, ConstU32<{ limits::IMMUTABLE_BYTES }>>;
130type CallOf<T> = <T as Config>::RuntimeCall;
131
132/// Used as a sentinel value when reading and writing contract memory.
133///
134/// It is usually used to signal `None` to a contract when only a primitive is allowed
135/// and we don't want to go through encoding a full Rust type. Using `u32::Max` is a safe
136/// sentinel because contracts are never allowed to use such a large amount of resources
137/// that this value makes sense for a memory location or length.
138const SENTINEL: u32 = u32::MAX;
139
140/// The target that is used for the log output emitted by this crate.
141///
142/// Hence you can use this target to selectively increase the log level for this crate.
143///
144/// Example: `RUST_LOG=runtime::revive=debug my_code --dev`
145const LOG_TARGET: &str = "runtime::revive";
146
147#[frame_support::pallet]
148pub mod pallet {
149	use super::*;
150	use frame_support::{pallet_prelude::*, traits::FindAuthor};
151	use frame_system::pallet_prelude::*;
152	use sp_core::U256;
153	use sp_runtime::Perbill;
154
155	/// The in-code storage version.
156	pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
157
158	#[pallet::pallet]
159	#[pallet::storage_version(STORAGE_VERSION)]
160	pub struct Pallet<T>(_);
161
162	#[pallet::config(with_default)]
163	pub trait Config: frame_system::Config {
164		/// The time implementation used to supply timestamps to contracts through `seal_now`.
165		type Time: Time<Moment: Into<U256>>;
166
167		/// The balance type of [`Self::Currency`].
168		///
169		/// Just added here to add additional trait bounds.
170		#[pallet::no_default]
171		type Balance: Balance
172			+ TryFrom<U256>
173			+ Into<U256>
174			+ Bounded
175			+ UniqueSaturatedInto<u64>
176			+ UniqueSaturatedFrom<u64>
177			+ UniqueSaturatedInto<u128>;
178
179		/// The fungible in which fees are paid and contract balances are held.
180		#[pallet::no_default]
181		type Currency: Inspect<Self::AccountId, Balance = Self::Balance>
182			+ Mutate<Self::AccountId>
183			+ MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>
184			+ Balanced<Self::AccountId>;
185
186		/// Handler for burned native currency (e.g. gas rounding).
187		///
188		/// When EVM gas accounting rounds up the transaction cost, the small rounding
189		/// difference is withdrawn from the caller and forwarded to this handler.
190		/// Use this to redirect burned value to a treasury or DAP instead of silently
191		/// destroying it.
192		#[pallet::no_default_bounds]
193		type OnBurn: OnUnbalanced<CreditOf<Self>>;
194
195		/// The overarching event type.
196		#[pallet::no_default_bounds]
197		#[allow(deprecated)]
198		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
199
200		/// The overarching call type.
201		#[pallet::no_default_bounds]
202		type RuntimeCall: Parameter
203			+ Dispatchable<
204				RuntimeOrigin = OriginFor<Self>,
205				Info = DispatchInfo,
206				PostInfo = PostDispatchInfo,
207			> + IsType<<Self as frame_system::Config>::RuntimeCall>
208			+ From<Call<Self>>
209			+ IsSubType<Call<Self>>
210			+ GetDispatchInfo;
211
212		/// The overarching origin type.
213		#[pallet::no_default_bounds]
214		type RuntimeOrigin: IsType<OriginFor<Self>>
215			+ From<Origin<Self>>
216			+ Into<Result<Origin<Self>, OriginFor<Self>>>;
217
218		/// Overarching hold reason.
219		#[pallet::no_default_bounds]
220		type RuntimeHoldReason: From<HoldReason>;
221
222		/// Describes the weights of the dispatchables of this module and is also used to
223		/// construct a default cost schedule.
224		type WeightInfo: WeightInfo;
225
226		/// Type that allows the runtime authors to add new host functions for a contract to call.
227		///
228		/// Pass in a tuple of types that implement [`precompiles::Precompile`].
229		#[pallet::no_default_bounds]
230		#[allow(private_bounds)]
231		type Precompiles: precompiles::Precompiles<Self>;
232
233		/// Find the author of the current block.
234		type FindAuthor: FindAuthor<Self::AccountId>;
235
236		/// The amount of balance a caller has to pay for each byte of storage.
237		///
238		/// # Note
239		///
240		/// It is safe to change this value on a live chain as all refunds are pro rata.
241		#[pallet::constant]
242		#[pallet::no_default_bounds]
243		type DepositPerByte: Get<BalanceOf<Self>>;
244
245		/// The amount of balance a caller has to pay for each storage item.
246		///
247		/// # Note
248		///
249		/// It is safe to change this value on a live chain as all refunds are pro rata.
250		#[pallet::constant]
251		#[pallet::no_default_bounds]
252		type DepositPerItem: Get<BalanceOf<Self>>;
253
254		/// The amount of balance a caller has to pay for each child trie storage item.
255		///
256		/// Those are the items created by a contract. In Solidity each value is a single
257		/// storage item. This is why we need to set a lower value here than for the main
258		/// trie items. Otherwise the storage deposit is too high.
259		///
260		/// # Note
261		///
262		/// It is safe to change this value on a live chain as all refunds are pro rata.
263		#[pallet::constant]
264		#[pallet::no_default_bounds]
265		type DepositPerChildTrieItem: Get<BalanceOf<Self>>;
266
267		/// The percentage of the storage deposit that should be held for using a code hash.
268		/// Instantiating a contract, protects the code from being removed. In order to prevent
269		/// abuse these actions are protected with a percentage of the code deposit.
270		#[pallet::constant]
271		type CodeHashLockupDepositPercent: Get<Perbill>;
272
273		/// Use either valid type is [`address::AccountId32Mapper`] or [`address::H160Mapper`].
274		#[pallet::no_default]
275		type AddressMapper: AddressMapper<Self>;
276
277		/// Allow EVM bytecode to be uploaded and instantiated.
278		#[pallet::constant]
279		type AllowEVMBytecode: Get<bool>;
280
281		/// Origin allowed to upload code.
282		///
283		/// By default, it is safe to set this to `EnsureSigned`, allowing anyone to upload contract
284		/// code.
285		#[pallet::no_default_bounds]
286		type UploadOrigin: EnsureOrigin<OriginFor<Self>, Success = Self::AccountId>;
287
288		/// Origin allowed to instantiate code.
289		///
290		/// # Note
291		///
292		/// This is not enforced when a contract instantiates another contract. The
293		/// [`Self::UploadOrigin`] should make sure that no code is deployed that does unwanted
294		/// instantiations.
295		///
296		/// By default, it is safe to set this to `EnsureSigned`, allowing anyone to instantiate
297		/// contract code.
298		#[pallet::no_default_bounds]
299		type InstantiateOrigin: EnsureOrigin<OriginFor<Self>, Success = Self::AccountId>;
300
301		/// The amount of memory in bytes that parachain nodes a lot to the runtime.
302		///
303		/// This is used in [`Pallet::integrity_test`] to make sure that the runtime has enough
304		/// memory to support this pallet if set to the correct value.
305		type RuntimeMemory: Get<u32>;
306
307		/// The amount of memory in bytes that relay chain validators a lot to the PoV.
308		///
309		/// This is used in [`Pallet::integrity_test`] to make sure that the runtime has enough
310		/// memory to support this pallet if set to the correct value.
311		///
312		/// This value is usually higher than [`Self::RuntimeMemory`] to account for the fact
313		/// that validators have to hold all storage items in PvF memory.
314		type PVFMemory: Get<u32>;
315
316		/// The [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID.
317		///
318		/// This is a unique identifier assigned to each blockchain network,
319		/// preventing replay attacks.
320		#[pallet::constant]
321		type ChainId: Get<u64>;
322
323		/// The ratio between the decimal representation of the native token and the ETH token.
324		#[pallet::constant]
325		type NativeToEthRatio: Get<u32>;
326
327		/// Set to [`crate::evm::fees::Info`] for a production runtime.
328		///
329		/// For mock runtimes that do not need to interact with any eth compat functionality
330		/// the default value of `()` will suffice.
331		#[pallet::no_default_bounds]
332		type FeeInfo: FeeInfo<Self>;
333
334		/// The fraction the maximum extrinsic weight `eth_transact` extrinsics are capped to.
335		///
336		/// This is not a security measure but a requirement due to how we map gas to `(Weight,
337		/// StorageDeposit)`. The mapping might derive a `Weight` that is too large to fit into an
338		/// extrinsic. In this case we cap it to the limit specified here.
339		///
340		/// `eth_transact` transactions that use more weight than specified will fail with an out of
341		/// gas error during execution. Larger fractions will allow more transactions to run.
342		/// Smaller values waste less block space: Choose as small as possible and as large as
343		/// necessary.
344		///
345		///  Default: `0.5`.
346		#[pallet::constant]
347		type MaxEthExtrinsicWeight: Get<FixedU128>;
348
349		/// Allows debug-mode configuration, such as enabling unlimited contract size.
350		#[pallet::constant]
351		type DebugEnabled: Get<bool>;
352
353		/// This determines the relative scale of our gas price and gas estimates.
354		///
355		/// By default, the gas price (in wei) is `FeeInfo::next_fee_multiplier()` multiplied by
356		/// `NativeToEthRatio`. `GasScale` allows to scale this value: the actual gas price is the
357		/// default gas price multiplied by `GasScale`.
358		///
359		/// As a consequence, gas cost (gas estimates and actual gas usage during transaction) is
360		/// scaled down by the same factor. Thus, the total transaction cost is not affected by
361		/// `GasScale` – apart from rounding differences: the transaction cost is always a multiple
362		/// of the gas price and is derived by rounded up, so that with higher `GasScales` this can
363		/// lead to higher gas cost as the rounding difference would be larger.
364		///
365		/// The main purpose of changing the `GasScale` is to tune the gas cost so that it is closer
366		/// to standard EVM gas cost and contracts will not run out of gas when tools or code
367		/// assume hard coded gas limits.
368		///
369		/// Requirement: `GasScale` must not be 0
370		#[pallet::constant]
371		#[pallet::no_default_bounds]
372		type GasScale: Get<u32>;
373	}
374
375	/// Container for different types that implement [`DefaultConfig`]` of this pallet.
376	pub mod config_preludes {
377		use super::*;
378		use frame_support::{
379			derive_impl,
380			traits::{ConstBool, ConstU32},
381		};
382		use frame_system::EnsureSigned;
383		use sp_core::parameter_types;
384
385		type Balance = u64;
386
387		pub const DOLLARS: Balance = 1_000_000_000_000;
388		pub const CENTS: Balance = DOLLARS / 100;
389		pub const MILLICENTS: Balance = CENTS / 1_000;
390
391		pub const fn deposit(items: u32, bytes: u32) -> Balance {
392			items as Balance * 20 * CENTS + (bytes as Balance) * MILLICENTS
393		}
394
395		parameter_types! {
396			pub const DepositPerItem: Balance = deposit(1, 0);
397			pub const DepositPerChildTrieItem: Balance = deposit(1, 0) / 100;
398			pub const DepositPerByte: Balance = deposit(0, 1);
399			pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
400			pub const MaxEthExtrinsicWeight: FixedU128 = FixedU128::from_rational(9, 10);
401			pub const GasScale: u32 = 10u32;
402		}
403
404		/// A type providing default configurations for this pallet in testing environment.
405		pub struct TestDefaultConfig;
406
407		impl Time for TestDefaultConfig {
408			type Moment = u64;
409			fn now() -> Self::Moment {
410				0u64
411			}
412		}
413
414		impl<T: From<u64>> Convert<Weight, T> for TestDefaultConfig {
415			fn convert(w: Weight) -> T {
416				w.ref_time().into()
417			}
418		}
419
420		#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
421		impl frame_system::DefaultConfig for TestDefaultConfig {}
422
423		#[frame_support::register_default_impl(TestDefaultConfig)]
424		impl DefaultConfig for TestDefaultConfig {
425			#[inject_runtime_type]
426			type RuntimeEvent = ();
427
428			#[inject_runtime_type]
429			type RuntimeHoldReason = ();
430
431			#[inject_runtime_type]
432			type RuntimeCall = ();
433
434			#[inject_runtime_type]
435			type RuntimeOrigin = ();
436
437			type Precompiles = ();
438			type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
439			type DepositPerByte = DepositPerByte;
440			type DepositPerItem = DepositPerItem;
441			type DepositPerChildTrieItem = DepositPerChildTrieItem;
442			type Time = Self;
443			type AllowEVMBytecode = ConstBool<true>;
444			type UploadOrigin = EnsureSigned<Self::AccountId>;
445			type InstantiateOrigin = EnsureSigned<Self::AccountId>;
446			type WeightInfo = ();
447			type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>;
448			type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>;
449			type ChainId = ConstU64<42>;
450			type NativeToEthRatio = ConstU32<1_000_000>;
451			type FindAuthor = ();
452			type FeeInfo = ();
453			type MaxEthExtrinsicWeight = MaxEthExtrinsicWeight;
454			type DebugEnabled = ConstBool<false>;
455			type GasScale = GasScale;
456			type OnBurn = ();
457		}
458	}
459
460	#[pallet::event]
461	pub enum Event<T: Config> {
462		/// A custom event emitted by the contract.
463		ContractEmitted {
464			/// The contract that emitted the event.
465			contract: H160,
466			/// Data supplied by the contract. Metadata generated during contract compilation
467			/// is needed to decode it.
468			data: Vec<u8>,
469			/// A list of topics used to index the event.
470			/// Number of topics is capped by [`limits::NUM_EVENT_TOPICS`].
471			topics: Vec<H256>,
472		},
473
474		/// Contract deployed by deployer at the specified address.
475		Instantiated { deployer: H160, contract: H160 },
476
477		/// Emitted when an Ethereum transaction reverts.
478		///
479		/// Ethereum transactions always complete successfully at the extrinsic level,
480		/// as even reverted calls must store their `ReceiptInfo`.
481		/// To distinguish reverted calls from successful ones, this event is emitted
482		/// for failed Ethereum transactions.
483		EthExtrinsicRevert { dispatch_error: DispatchError },
484	}
485
486	#[pallet::error]
487	#[repr(u8)]
488	pub enum Error<T> {
489		/// Invalid schedule supplied, e.g. with zero weight of a basic operation.
490		InvalidSchedule = 0x01,
491		/// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`.
492		InvalidCallFlags = 0x02,
493		/// The executed contract exhausted its gas limit.
494		OutOfGas = 0x03,
495		/// Performing the requested transfer failed. Probably because there isn't enough
496		/// free balance in the sender's account.
497		TransferFailed = 0x04,
498		/// Performing a call was denied because the calling depth reached the limit
499		/// of what is specified in the schedule.
500		MaxCallDepthReached = 0x05,
501		/// No contract was found at the specified address.
502		ContractNotFound = 0x06,
503		/// No code could be found at the supplied code hash.
504		CodeNotFound = 0x07,
505		/// No code info could be found at the supplied code hash.
506		CodeInfoNotFound = 0x08,
507		/// A buffer outside of sandbox memory was passed to a contract API function.
508		OutOfBounds = 0x09,
509		/// Input passed to a contract API function failed to decode as expected type.
510		DecodingFailed = 0x0A,
511		/// Contract trapped during execution.
512		ContractTrapped = 0x0B,
513		/// Event body or storage item exceeds [`limits::STORAGE_BYTES`].
514		ValueTooLarge = 0x0C,
515		/// Termination of a contract is not allowed while the contract is already
516		/// on the call stack. Can be triggered by `seal_terminate`.
517		TerminatedWhileReentrant = 0x0D,
518		/// `seal_call` forwarded this contracts input. It therefore is no longer available.
519		InputForwarded = 0x0E,
520		/// The amount of topics passed to `seal_deposit_events` exceeds the limit.
521		TooManyTopics = 0x0F,
522		/// A contract with the same AccountId already exists.
523		DuplicateContract = 0x12,
524		/// A contract self destructed in its constructor.
525		///
526		/// This can be triggered by a call to `seal_terminate`.
527		TerminatedInConstructor = 0x13,
528		/// A call tried to invoke a contract that is flagged as non-reentrant.
529		ReentranceDenied = 0x14,
530		/// A contract called into the runtime which then called back into this pallet.
531		ReenteredPallet = 0x15,
532		/// A contract attempted to invoke a state modifying API while being in read-only mode.
533		StateChangeDenied = 0x16,
534		/// Origin doesn't have enough balance to pay the required storage deposits.
535		StorageDepositNotEnoughFunds = 0x17,
536		/// More storage was created than allowed by the storage deposit limit.
537		StorageDepositLimitExhausted = 0x18,
538		/// Code removal was denied because the code is still in use by at least one contract.
539		CodeInUse = 0x19,
540		/// The contract ran to completion but decided to revert its storage changes.
541		/// Please note that this error is only returned from extrinsics. When called directly
542		/// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags
543		/// to determine whether a reversion has taken place.
544		ContractReverted = 0x1A,
545		/// The contract failed to compile or is missing the correct entry points.
546		///
547		/// A more detailed error can be found on the node console if debug messages are enabled
548		/// by supplying `-lruntime::revive=debug`.
549		CodeRejected = 0x1B,
550		/// The code blob supplied is larger than [`limits::code::BLOB_BYTES`].
551		BlobTooLarge = 0x1C,
552		/// The contract declares too much memory (ro + rw + stack).
553		StaticMemoryTooLarge = 0x1D,
554		/// The program contains a basic block that is larger than allowed.
555		BasicBlockTooLarge = 0x1E,
556		/// The program contains an invalid instruction.
557		InvalidInstruction = 0x1F,
558		/// The contract has reached its maximum number of delegate dependencies.
559		MaxDelegateDependenciesReached = 0x20,
560		/// The dependency was not found in the contract's delegate dependencies.
561		DelegateDependencyNotFound = 0x21,
562		/// The contract already depends on the given delegate dependency.
563		DelegateDependencyAlreadyExists = 0x22,
564		/// Can not add a delegate dependency to the code hash of the contract itself.
565		CannotAddSelfAsDelegateDependency = 0x23,
566		/// Can not add more data to transient storage.
567		OutOfTransientStorage = 0x24,
568		/// The contract tried to call a syscall which does not exist (at its current api level).
569		InvalidSyscall = 0x25,
570		/// Invalid storage flags were passed to one of the storage syscalls.
571		InvalidStorageFlags = 0x26,
572		/// PolkaVM failed during code execution. Probably due to a malformed program.
573		ExecutionFailed = 0x27,
574		/// Failed to convert a U256 to a Balance.
575		BalanceConversionFailed = 0x28,
576		/// Immutable data can only be set during deploys and only be read during calls.
577		/// Additionally, it is only valid to set the data once and it must not be empty.
578		InvalidImmutableAccess = 0x2A,
579		/// An `AccountID32` account tried to interact with the pallet without having a mapping.
580		///
581		/// Call [`Pallet::map_account`] in order to create a mapping for the account.
582		AccountUnmapped = 0x2B,
583		/// Tried to map an account that is already mapped.
584		AccountAlreadyMapped = 0x2C,
585		/// The transaction used to dry-run a contract is invalid.
586		InvalidGenericTransaction = 0x2D,
587		/// The refcount of a code either over or underflowed.
588		RefcountOverOrUnderflow = 0x2E,
589		/// Unsupported precompile address.
590		UnsupportedPrecompileAddress = 0x2F,
591		/// The calldata exceeds [`limits::CALLDATA_BYTES`].
592		CallDataTooLarge = 0x30,
593		/// The return data exceeds [`limits::CALLDATA_BYTES`].
594		ReturnDataTooLarge = 0x31,
595		/// Invalid jump destination. Dynamic jumps points to invalid not jumpdest opcode.
596		InvalidJump = 0x32,
597		/// Attempting to pop a value from an empty stack.
598		StackUnderflow = 0x33,
599		/// Attempting to push a value onto a full stack.
600		StackOverflow = 0x34,
601		/// Too much deposit was drawn from the shared txfee and deposit credit.
602		///
603		/// This happens if the passed `gas` inside the ethereum transaction is too low.
604		TxFeeOverdraw = 0x35,
605		/// When calling an EVM constructor `data` has to be empty.
606		///
607		/// EVM constructors do not accept data. Their input data is part of the code blob itself.
608		EvmConstructorNonEmptyData = 0x36,
609		/// Tried to construct an EVM contract via code hash.
610		///
611		/// EVM contracts can only be instantiated via code upload as no initcode is
612		/// stored on-chain.
613		EvmConstructedFromHash = 0x37,
614		/// The contract does not have enough balance to refund the storage deposit.
615		///
616		/// This is a bug and should never happen. It means the accounting got out of sync.
617		StorageRefundNotEnoughFunds = 0x38,
618		/// This means there are locks on the contracts storage deposit that prevents refunding it.
619		///
620		/// This would be the case if the contract used its storage deposits for governance
621		/// or other pallets that allow creating locks over held balance.
622		StorageRefundLocked = 0x39,
623		/// Called a pre-compile that is not allowed to be delegate called.
624		///
625		/// Some pre-compile functions will trap the caller context if being delegate
626		/// called or if their caller was being delegate called.
627		PrecompileDelegateDenied = 0x40,
628		/// ECDSA public key recovery failed. Most probably wrong recovery id or signature.
629		EcdsaRecoveryFailed = 0x41,
630		/// Benchmarking only error.
631		#[cfg(feature = "runtime-benchmarks")]
632		BenchmarkingError = 0xFF,
633	}
634
635	/// A reason for the pallet revive placing a hold on funds.
636	#[pallet::composite_enum]
637	pub enum HoldReason {
638		/// The Pallet has reserved it for storing code on-chain.
639		CodeUploadDepositReserve,
640		/// The Pallet has reserved it for storage deposit.
641		StorageDepositReserve,
642		/// Deposit for creating an address mapping in [`OriginalAccount`].
643		AddressMapping,
644	}
645
646	#[derive(
647		PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug,
648	)]
649	#[pallet::origin]
650	pub enum Origin<T: Config> {
651		EthTransaction(T::AccountId),
652	}
653
654	/// A mapping from a contract's code hash to its code.
655	/// The code's size is bounded by [`crate::limits::BLOB_BYTES`] for PVM and
656	/// [`revm::primitives::eip170::MAX_CODE_SIZE`] for EVM bytecode.
657	#[pallet::storage]
658	#[pallet::unbounded]
659	pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, H256, Vec<u8>>;
660
661	/// A mapping from a contract's code hash to its code info.
662	#[pallet::storage]
663	pub(crate) type CodeInfoOf<T: Config> = StorageMap<_, Identity, H256, CodeInfo<T>>;
664
665	/// The data associated to a contract or externally owned account.
666	#[pallet::storage]
667	pub(crate) type AccountInfoOf<T: Config> = StorageMap<_, Identity, H160, AccountInfo<T>>;
668
669	/// The immutable data associated with a given account.
670	#[pallet::storage]
671	pub(crate) type ImmutableDataOf<T: Config> = StorageMap<_, Identity, H160, ImmutableData>;
672
673	/// Evicted contracts that await child trie deletion.
674	///
675	/// Child trie deletion is a heavy operation depending on the amount of storage items
676	/// stored in said trie. Therefore this operation is performed lazily in `on_idle`.
677	#[pallet::storage]
678	pub(crate) type DeletionQueue<T: Config> = StorageMap<_, Twox64Concat, u32, TrieId>;
679
680	/// A pair of monotonic counters used to track the latest contract marked for deletion
681	/// and the latest deleted contract in queue.
682	#[pallet::storage]
683	pub(crate) type DeletionQueueCounter<T: Config> =
684		StorageValue<_, DeletionQueueManager<T>, ValueQuery>;
685
686	/// Map a Ethereum address to its original `AccountId32`.
687	///
688	/// When deriving a `H160` from an `AccountId32` we use a hash function. In order to
689	/// reconstruct the original account we need to store the reverse mapping here.
690	/// Register your `AccountId32` using [`Pallet::map_account`] in order to
691	/// use it with this pallet.
692	#[pallet::storage]
693	pub(crate) type OriginalAccount<T: Config> = StorageMap<_, Identity, H160, AccountId32>;
694
695	/// The current Ethereum block that is stored in the `on_finalize` method.
696	///
697	/// # Note
698	///
699	/// This could be further optimized into the future to store only the minimum
700	/// information needed to reconstruct the Ethereum block at the RPC level.
701	///
702	/// Since the block is convenient to have around, and the extra details are capped
703	/// by a few hashes and the vector of transaction hashes, we store the block here.
704	#[pallet::storage]
705	#[pallet::unbounded]
706	pub(crate) type EthereumBlock<T> = StorageValue<_, EthBlock, ValueQuery>;
707
708	/// Mapping for block number and hashes.
709	///
710	/// The maximum number of elements stored is capped by the block hash count `BLOCK_HASH_COUNT`.
711	#[pallet::storage]
712	pub(crate) type BlockHash<T: Config> =
713		StorageMap<_, Identity, BlockNumberFor<T>, H256, ValueQuery>;
714
715	/// The details needed to reconstruct the receipt info offchain.
716	///
717	/// This contains valuable information about the gas used by the transaction.
718	///
719	/// NOTE: The item is unbound and should therefore never be read on chain.
720	/// It could otherwise inflate the PoV size of a block.
721	#[pallet::storage]
722	#[pallet::unbounded]
723	pub(crate) type ReceiptInfoData<T: Config> = StorageValue<_, Vec<ReceiptGasInfo>, ValueQuery>;
724
725	/// Incremental ethereum block builder.
726	#[pallet::storage]
727	#[pallet::unbounded]
728	pub(crate) type EthBlockBuilderIR<T: Config> =
729		StorageValue<_, EthereumBlockBuilderIR<T>, ValueQuery>;
730
731	/// The first transaction and receipt of the ethereum block.
732	///
733	/// These values are moved out of the `EthBlockBuilderIR` to avoid serializing and
734	/// deserializing them on every transaction. Instead, they are loaded when needed.
735	#[pallet::storage]
736	#[pallet::unbounded]
737	pub(crate) type EthBlockBuilderFirstValues<T: Config> =
738		StorageValue<_, Option<(Vec<u8>, Vec<u8>)>, ValueQuery>;
739
740	/// Debugging settings that can be configured when DebugEnabled config is true.
741	#[pallet::storage]
742	pub(crate) type DebugSettingsOf<T: Config> = StorageValue<_, DebugSettings, ValueQuery>;
743
744	pub mod genesis {
745		use super::*;
746		use crate::evm::Bytes32;
747
748		/// Genesis configuration for contract-specific data.
749		#[derive(Clone, PartialEq, Debug, Default, serde::Serialize, serde::Deserialize)]
750		pub struct ContractData {
751			/// Contract code.
752			pub code: crate::evm::Bytes,
753			/// Initial storage entries as 32-byte key/value pairs.
754			pub storage: alloc::collections::BTreeMap<Bytes32, Bytes32>,
755		}
756
757		/// Genesis configuration for a contract account.
758		#[derive(PartialEq, Default, Debug, Clone, serde::Serialize, serde::Deserialize)]
759		pub struct Account<T: Config> {
760			/// Contract address.
761			pub address: H160,
762			/// Contract balance.
763			#[serde(default)]
764			pub balance: U256,
765			/// Account nonce
766			#[serde(default)]
767			pub nonce: T::Nonce,
768			/// Contract-specific data (code and storage). None for EOAs.
769			#[serde(flatten, skip_serializing_if = "Option::is_none")]
770			pub contract_data: Option<ContractData>,
771		}
772	}
773
774	#[pallet::genesis_config]
775	#[derive(Debug, PartialEq, frame_support::DefaultNoBound)]
776	pub struct GenesisConfig<T: Config> {
777		/// List of native Substrate accounts (typically `AccountId32`) to be mapped at genesis
778		/// block, enabling them to interact with smart contracts.
779		#[serde(default, skip_serializing_if = "Vec::is_empty")]
780		pub mapped_accounts: Vec<T::AccountId>,
781
782		/// Account entries (both EOAs and contracts)
783		#[serde(default, skip_serializing_if = "Vec::is_empty")]
784		pub accounts: Vec<genesis::Account<T>>,
785
786		/// Optional debugging settings applied at genesis.
787		#[serde(default, skip_serializing_if = "Option::is_none")]
788		pub debug_settings: Option<DebugSettings>,
789	}
790
791	#[pallet::genesis_build]
792	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
793		fn build(&self) {
794			use crate::{exec::Key, vm::ContractBlob};
795			use frame_support::traits::fungible::Mutate;
796
797			if !System::<T>::account_exists(&Pallet::<T>::account_id()) {
798				let _ = T::Currency::mint_into(
799					&Pallet::<T>::account_id(),
800					T::Currency::minimum_balance(),
801				);
802			}
803
804			for id in &self.mapped_accounts {
805				if let Err(err) = T::AddressMapper::map_no_deposit(id) {
806					log::error!(target: LOG_TARGET, "Failed to map account {id:?}: {err:?}");
807				}
808			}
809
810			let owner = Pallet::<T>::account_id();
811
812			for genesis::Account { address, balance, nonce, contract_data } in &self.accounts {
813				let account_id = T::AddressMapper::to_account_id(address);
814
815				if !System::<T>::account_exists(&account_id) {
816					let _ = T::Currency::mint_into(&account_id, T::Currency::minimum_balance());
817				}
818
819				frame_system::Account::<T>::mutate(&account_id, |info| {
820					info.nonce = (*nonce).into();
821				});
822
823				match contract_data {
824					None => {
825						AccountInfoOf::<T>::insert(
826							address,
827							AccountInfo { account_type: AccountType::EOA, dust: 0 },
828						);
829					},
830					Some(genesis::ContractData { code, storage }) => {
831						let blob = if code.0.starts_with(&polkavm_common::program::BLOB_MAGIC) {
832							ContractBlob::<T>::from_pvm_code(code.0.clone(), owner.clone())
833								.inspect_err(|err| {
834									log::error!(target: LOG_TARGET, "Failed to create PVM ContractBlob for {address:?}: {err:?}");
835								})
836						} else {
837							ContractBlob::<T>::from_evm_runtime_code(code.0.clone(), account_id)
838								.inspect_err(|err| {
839									log::error!(target: LOG_TARGET, "Failed to create EVM ContractBlob for {address:?}: {err:?}");
840								})
841						};
842
843						let Ok(blob) = blob else {
844							continue;
845						};
846
847						let code_hash = *blob.code_hash();
848						let Ok(info) = <ContractInfo<T>>::new(&address, 0u32.into(), code_hash)
849							.inspect_err(|err| {
850								log::error!(target: LOG_TARGET, "Failed to create ContractInfo for {address:?}: {err:?}");
851							})
852						else {
853							continue;
854						};
855
856						AccountInfoOf::<T>::insert(
857							address,
858							AccountInfo { account_type: info.clone().into(), dust: 0 },
859						);
860
861						<PristineCode<T>>::insert(blob.code_hash(), code.0.clone());
862						<CodeInfoOf<T>>::insert(blob.code_hash(), blob.code_info().clone());
863						for (k, v) in storage {
864							let _ = info.write(&Key::from_fixed(k.0), Some(v.0.to_vec()), None, false).inspect_err(|err| {
865								log::error!(target: LOG_TARGET, "Failed to write genesis storage for {address:?} at key {k:?}: {err:?}");
866							});
867						}
868					},
869				}
870
871				let _ = Pallet::<T>::set_evm_balance(address, *balance).inspect_err(|err| {
872					log::error!(target: LOG_TARGET, "Failed to set EVM balance for {address:?}: {err:?}");
873				});
874			}
875
876			// Build genesis block
877			block_storage::on_finalize_build_eth_block::<T>(
878				// Make sure to use the block number from storage instead of the hardcoded 0.
879				// This enables testing tools like anvil to customise the genesis block number.
880				frame_system::Pallet::<T>::block_number(),
881			);
882
883			// Set debug settings.
884			if let Some(settings) = self.debug_settings.as_ref() {
885				settings.write_to_storage::<T>()
886			}
887		}
888	}
889
890	#[pallet::hooks]
891	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
892		fn on_idle(_block: BlockNumberFor<T>, limit: Weight) -> Weight {
893			let mut meter = WeightMeter::with_limit(limit);
894			ContractInfo::<T>::process_deletion_queue_batch(&mut meter);
895			meter.consumed()
896		}
897
898		fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
899			// Kill related ethereum block storage items.
900			block_storage::on_initialize::<T>();
901
902			// Warm up the pallet account.
903			System::<T>::account_exists(&Pallet::<T>::account_id());
904			// Account for the fixed part of the costs incurred in `on_finalize`.
905			<T as Config>::WeightInfo::on_finalize_block_fixed()
906		}
907
908		fn on_finalize(block_number: BlockNumberFor<T>) {
909			// Build the ethereum block and place it in storage.
910			block_storage::on_finalize_build_eth_block::<T>(block_number);
911		}
912
913		fn integrity_test() {
914			assert!(T::ChainId::get() > 0, "ChainId must be greater than 0");
915
916			assert!(T::GasScale::get() > 0u32.into(), "GasScale must not be 0");
917
918			T::FeeInfo::integrity_test();
919
920			// The memory available in the block building runtime
921			let max_runtime_mem: u64 = T::RuntimeMemory::get().into();
922
923			// We only allow 50% of the runtime memory to be utilized by the contracts call
924			// stack, keeping the rest for other facilities, such as PoV, etc.
925			const TOTAL_MEMORY_DEVIDER: u64 = 2;
926
927			// Validators are configured to be able to use more memory than block builders. This is
928			// because in addition to `max_runtime_mem` they need to hold additional data in
929			// memory: PoV in multiple copies (1x encoded + 2x decoded) and all storage which
930			// includes emitted events. The assumption is that storage/events size
931			// can be a maximum of half of the validator runtime memory - max_runtime_mem.
932			let max_block_weight = T::BlockWeights::get()
933				.get(DispatchClass::Normal)
934				.max_total
935				.unwrap_or_else(|| T::BlockWeights::get().max_block);
936			let max_key_size: u64 =
937				Key::try_from_var(alloc::vec![0u8; limits::STORAGE_KEY_BYTES as usize])
938					.expect("Key of maximal size shall be created")
939					.hash()
940					.len()
941					.try_into()
942					.unwrap();
943
944			let max_immutable_key_size: u64 = T::AccountId::max_encoded_len().try_into().unwrap();
945			let max_immutable_size: u64 = max_block_weight
946				.checked_div_per_component(&<RuntimeCosts as WeightToken<T>>::weight(
947					&RuntimeCosts::SetImmutableData(limits::IMMUTABLE_BYTES),
948				))
949				.unwrap()
950				.saturating_mul(
951					u64::from(limits::IMMUTABLE_BYTES)
952						.saturating_add(max_immutable_key_size)
953						.into(),
954				);
955
956			let max_pvf_mem: u64 = T::PVFMemory::get().into();
957			let storage_size_limit = max_pvf_mem.saturating_sub(max_runtime_mem) / 2;
958
959			// We can use storage to store events using the available block ref_time with the
960			// `deposit_event` host function. The overhead of stored events, which is around 100B,
961			// is not taken into account to simplify calculations, as it does not change much.
962			let max_events_size = max_block_weight
963				.checked_div_per_component(
964					&(<RuntimeCosts as WeightToken<T>>::weight(&RuntimeCosts::DepositEvent {
965						num_topic: 0,
966						len: limits::EVENT_BYTES,
967					})
968					.saturating_add(<RuntimeCosts as WeightToken<T>>::weight(
969						&RuntimeCosts::HostFn,
970					))),
971				)
972				.unwrap()
973				.saturating_mul(limits::EVENT_BYTES.into());
974
975			assert!(
976				max_events_size <= storage_size_limit,
977				"Maximal events size {} exceeds the events limit {}",
978				max_events_size,
979				storage_size_limit
980			);
981
982			// The incremental block builder uses 3 x maximum entry size for receipts and
983			// for transactions. Transactions are bounded to `MAX_TRANSACTION_PAYLOAD_SIZE`.
984			//
985			// To determine the maximum size of the receipts, we know the following:
986			// - (I) first receipt is stored into pallet storage and not given to the hasher until
987			//   finalization.
988			// - (II) the hasher will not consume more memory than the receipts we are giving it.
989			// - (III) the hasher is capped by 3 x maximum entry for 3 or more transactions.
990			//
991			// # Case 1. One transaction with maximum receipts
992			//
993			// The worst case scenario for having one single transaction is for the transaction
994			// to emit the maximum receipt size (ie `max_events_size`). In this case,
995			// the maximum storage (and memory) consumed is bounded by `max_events_size` (II). The
996			// receipt is stored in pallet storage, and loaded from storage in the
997			// `on_finalize` hook (I).
998			//
999			// # Case 2. Two transactions
1000			//
1001			// The sum of the receipt size of both transactions cannot exceed `max_events_size`,
1002			// otherwise one transaction will be reverted. From (II), the bytes utilized
1003			// by the builder are capped to `max_events_size`.
1004			//
1005			// # Case 3. Three or more transactions
1006			//
1007			// Similar to the above case, the sum of all receipt size is bounded to
1008			// `max_events_size`. Therefore, the bytes are capped to `max_events_size`.
1009			//
1010			// On average, a transaction could emit `max_events_size / num_tx`. The would
1011			// consume `max_events_size / num_tx * 3` bytes, which is lower than
1012			// `max_events_size` for more than 3 transactions.
1013			//
1014			// In practice, the builder will consume even lower amounts considering
1015			// it is unlikely for a transaction to utilize all the weight of the block for events.
1016			let max_eth_block_builder_bytes =
1017				block_storage::block_builder_bytes_usage(max_events_size.try_into().unwrap());
1018
1019			log::debug!(
1020				target: LOG_TARGET,
1021				"Integrity check: max_eth_block_builder_bytes={} KB using max_events_size={} KB",
1022				max_eth_block_builder_bytes / 1024,
1023				max_events_size / 1024,
1024			);
1025
1026			// Check that the configured memory limits fit into runtime memory.
1027			//
1028			// Dynamic allocations are not available, yet. Hence they are not taken into
1029			// consideration here.
1030			let memory_left = i128::from(max_runtime_mem)
1031				.saturating_div(TOTAL_MEMORY_DEVIDER.into())
1032				.saturating_sub(limits::MEMORY_REQUIRED.into())
1033				.saturating_sub(max_eth_block_builder_bytes.into());
1034
1035			log::debug!(target: LOG_TARGET, "Integrity check: memory_left={} KB", memory_left / 1024);
1036
1037			assert!(
1038				memory_left >= 0,
1039				"Runtime does not have enough memory for current limits. Additional runtime memory required: {} KB",
1040				memory_left.saturating_mul(TOTAL_MEMORY_DEVIDER.into()).abs() / 1024
1041			);
1042
1043			// We can use storage to store items using the available block ref_time with the
1044			// `set_storage` host function.
1045			let max_storage_size = max_block_weight
1046				.checked_div_per_component(
1047					&<RuntimeCosts as WeightToken<T>>::weight(&RuntimeCosts::SetStorage {
1048						new_bytes: limits::STORAGE_BYTES,
1049						old_bytes: 0,
1050					})
1051					.saturating_mul(u64::from(limits::STORAGE_BYTES).saturating_add(max_key_size)),
1052				)
1053				.unwrap()
1054				.saturating_add(max_immutable_size.into())
1055				.saturating_add(max_eth_block_builder_bytes.into());
1056
1057			assert!(
1058				max_storage_size <= storage_size_limit,
1059				"Maximal storage size {} exceeds the storage limit {}",
1060				max_storage_size,
1061				storage_size_limit
1062			);
1063		}
1064	}
1065
1066	#[pallet::call]
1067	impl<T: Config> Pallet<T> {
1068		/// A raw EVM transaction, typically dispatched by an Ethereum JSON-RPC server.
1069		///
1070		/// # Parameters
1071		///
1072		/// * `payload`: The encoded [`crate::evm::TransactionSigned`].
1073		///
1074		/// # Note
1075		///
1076		/// This call cannot be dispatched directly; attempting to do so will result in a failed
1077		/// transaction. It serves as a wrapper for an Ethereum transaction. When submitted, the
1078		/// runtime converts it into a [`sp_runtime::generic::CheckedExtrinsic`] by recovering the
1079		/// signer and validating the transaction.
1080		#[allow(unused_variables)]
1081		#[pallet::call_index(0)]
1082		#[pallet::weight(Weight::MAX)]
1083		pub fn eth_transact(origin: OriginFor<T>, payload: Vec<u8>) -> DispatchResultWithPostInfo {
1084			Err(frame_system::Error::CallFiltered::<T>.into())
1085		}
1086
1087		/// Makes a call to an account, optionally transferring some balance.
1088		///
1089		/// # Parameters
1090		///
1091		/// * `dest`: Address of the contract to call.
1092		/// * `value`: The balance to transfer from the `origin` to `dest`.
1093		/// * `weight_limit`: The weight limit enforced when executing the constructor.
1094		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged from the
1095		///   caller to pay for the storage consumed.
1096		/// * `data`: The input data to pass to the contract.
1097		///
1098		/// * If the account is a smart-contract account, the associated code will be
1099		/// executed and any value will be transferred.
1100		/// * If the account is a regular account, any value will be transferred.
1101		/// * If no account exists and the call value is not less than `existential_deposit`,
1102		/// a regular account will be created and any value will be transferred.
1103		#[pallet::call_index(1)]
1104		#[pallet::weight(<T as Config>::WeightInfo::call().saturating_add(*weight_limit))]
1105		pub fn call(
1106			origin: OriginFor<T>,
1107			dest: H160,
1108			#[pallet::compact] value: BalanceOf<T>,
1109			weight_limit: Weight,
1110			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
1111			data: Vec<u8>,
1112		) -> DispatchResultWithPostInfo {
1113			Self::ensure_non_contract_if_signed(&origin)?;
1114			let mut output = Self::bare_call(
1115				origin,
1116				dest,
1117				Pallet::<T>::convert_native_to_evm(value),
1118				TransactionLimits::WeightAndDeposit {
1119					weight_limit,
1120					deposit_limit: storage_deposit_limit,
1121				},
1122				data,
1123				&ExecConfig::new_substrate_tx(),
1124			);
1125
1126			if let Ok(return_value) = &output.result &&
1127				return_value.did_revert()
1128			{
1129				output.result = Err(<Error<T>>::ContractReverted.into());
1130			}
1131			dispatch_result(
1132				output.result,
1133				output.weight_consumed,
1134				<T as Config>::WeightInfo::call(),
1135			)
1136		}
1137
1138		/// Instantiates a contract from a previously deployed vm binary.
1139		///
1140		/// This function is identical to [`Self::instantiate_with_code`] but without the
1141		/// code deployment step. Instead, the `code_hash` of an on-chain deployed vm binary
1142		/// must be supplied.
1143		#[pallet::call_index(2)]
1144		#[pallet::weight(
1145			<T as Config>::WeightInfo::instantiate(data.len() as u32).saturating_add(*weight_limit)
1146		)]
1147		pub fn instantiate(
1148			origin: OriginFor<T>,
1149			#[pallet::compact] value: BalanceOf<T>,
1150			weight_limit: Weight,
1151			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
1152			code_hash: sp_core::H256,
1153			data: Vec<u8>,
1154			salt: Option<[u8; 32]>,
1155		) -> DispatchResultWithPostInfo {
1156			Self::ensure_non_contract_if_signed(&origin)?;
1157			let data_len = data.len() as u32;
1158			let mut output = Self::bare_instantiate(
1159				origin,
1160				Pallet::<T>::convert_native_to_evm(value),
1161				TransactionLimits::WeightAndDeposit {
1162					weight_limit,
1163					deposit_limit: storage_deposit_limit,
1164				},
1165				Code::Existing(code_hash),
1166				data,
1167				salt,
1168				&ExecConfig::new_substrate_tx(),
1169			);
1170			if let Ok(retval) = &output.result &&
1171				retval.result.did_revert()
1172			{
1173				output.result = Err(<Error<T>>::ContractReverted.into());
1174			}
1175			dispatch_result(
1176				output.result.map(|result| result.result),
1177				output.weight_consumed,
1178				<T as Config>::WeightInfo::instantiate(data_len),
1179			)
1180		}
1181
1182		/// Instantiates a new contract from the supplied `code` optionally transferring
1183		/// some balance.
1184		///
1185		/// This dispatchable has the same effect as calling [`Self::upload_code`] +
1186		/// [`Self::instantiate`]. Bundling them together provides efficiency gains. Please
1187		/// also check the documentation of [`Self::upload_code`].
1188		///
1189		/// # Parameters
1190		///
1191		/// * `value`: The balance to transfer from the `origin` to the newly created contract.
1192		/// * `weight_limit`: The weight limit enforced when executing the constructor.
1193		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved
1194		///   from the caller to pay for the storage consumed.
1195		/// * `code`: The contract code to deploy in raw bytes.
1196		/// * `data`: The input data to pass to the contract constructor.
1197		/// * `salt`: Used for the address derivation. If `Some` is supplied then `CREATE2`
1198		/// 	semantics are used. If `None` then `CRATE1` is used.
1199		///
1200		///
1201		/// Instantiation is executed as follows:
1202		///
1203		/// - The supplied `code` is deployed, and a `code_hash` is created for that code.
1204		/// - If the `code_hash` already exists on the chain the underlying `code` will be shared.
1205		/// - The destination address is computed based on the sender, code_hash and the salt.
1206		/// - The smart-contract account is created at the computed address.
1207		/// - The `value` is transferred to the new account.
1208		/// - The `deploy` function is executed in the context of the newly-created account.
1209		#[pallet::call_index(3)]
1210		#[pallet::weight(
1211			<T as Config>::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32)
1212			.saturating_add(*weight_limit)
1213		)]
1214		pub fn instantiate_with_code(
1215			origin: OriginFor<T>,
1216			#[pallet::compact] value: BalanceOf<T>,
1217			weight_limit: Weight,
1218			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
1219			code: Vec<u8>,
1220			data: Vec<u8>,
1221			salt: Option<[u8; 32]>,
1222		) -> DispatchResultWithPostInfo {
1223			Self::ensure_non_contract_if_signed(&origin)?;
1224			let code_len = code.len() as u32;
1225			let data_len = data.len() as u32;
1226			let mut output = Self::bare_instantiate(
1227				origin,
1228				Pallet::<T>::convert_native_to_evm(value),
1229				TransactionLimits::WeightAndDeposit {
1230					weight_limit,
1231					deposit_limit: storage_deposit_limit,
1232				},
1233				Code::Upload(code),
1234				data,
1235				salt,
1236				&ExecConfig::new_substrate_tx(),
1237			);
1238			if let Ok(retval) = &output.result &&
1239				retval.result.did_revert()
1240			{
1241				output.result = Err(<Error<T>>::ContractReverted.into());
1242			}
1243			dispatch_result(
1244				output.result.map(|result| result.result),
1245				output.weight_consumed,
1246				<T as Config>::WeightInfo::instantiate_with_code(code_len, data_len),
1247			)
1248		}
1249
1250		/// Same as [`Self::instantiate_with_code`], but intended to be dispatched **only**
1251		/// by an EVM transaction through the EVM compatibility layer.
1252		///
1253		/// # Parameters
1254		///
1255		/// * `value`: The balance to transfer from the `origin` to the newly created contract.
1256		/// * `weight_limit`: The gas limit used to derive the transaction weight for transaction
1257		///   payment
1258		/// * `eth_gas_limit`: The Ethereum gas limit governing the resource usage of the execution
1259		/// * `code`: The contract code to deploy in raw bytes.
1260		/// * `data`: The input data to pass to the contract constructor.
1261		/// * `transaction_encoded`: The RLP encoding of the signed Ethereum transaction,
1262		///   represented as [crate::evm::TransactionSigned], provided by the Ethereum wallet. This
1263		///   is used for building the Ethereum transaction root.
1264		/// * effective_gas_price: the price of a unit of gas
1265		/// * encoded len: the byte code size of the `eth_transact` extrinsic
1266		///
1267		/// Calling this dispatchable ensures that the origin's nonce is bumped only once,
1268		/// via the `CheckNonce` transaction extension. In contrast, [`Self::instantiate_with_code`]
1269		/// also bumps the nonce after contract instantiation, since it may be invoked multiple
1270		/// times within a batch call transaction.
1271		#[pallet::call_index(10)]
1272		#[pallet::weight(
1273			<T as Config>::WeightInfo::eth_instantiate_with_code(code.len() as u32, data.len() as u32, Pallet::<T>::has_dust(*value).into())
1274			.saturating_add(*weight_limit)
1275		)]
1276		pub fn eth_instantiate_with_code(
1277			origin: OriginFor<T>,
1278			value: U256,
1279			weight_limit: Weight,
1280			eth_gas_limit: U256,
1281			code: Vec<u8>,
1282			data: Vec<u8>,
1283			transaction_encoded: Vec<u8>,
1284			effective_gas_price: U256,
1285			encoded_len: u32,
1286		) -> DispatchResultWithPostInfo {
1287			let signer = Self::ensure_eth_signed(origin)?;
1288			let origin = OriginFor::<T>::signed(signer.clone());
1289			Self::ensure_non_contract_if_signed(&origin)?;
1290			let mut call = Call::<T>::eth_instantiate_with_code {
1291				value,
1292				weight_limit,
1293				eth_gas_limit,
1294				code: code.clone(),
1295				data: data.clone(),
1296				transaction_encoded: transaction_encoded.clone(),
1297				effective_gas_price,
1298				encoded_len,
1299			}
1300			.into();
1301			let info = T::FeeInfo::dispatch_info(&call);
1302			let base_info = T::FeeInfo::base_dispatch_info(&mut call);
1303			drop(call);
1304
1305			block_storage::with_ethereum_context::<T>(transaction_encoded, || {
1306				let extra_weight = base_info.total_weight();
1307				let output = Self::bare_instantiate(
1308					origin,
1309					value,
1310					TransactionLimits::EthereumGas {
1311						eth_gas_limit: eth_gas_limit.saturated_into(),
1312						weight_limit,
1313						eth_tx_info: EthTxInfo::new(encoded_len, extra_weight),
1314					},
1315					Code::Upload(code),
1316					data,
1317					None,
1318					&ExecConfig::new_eth_tx(effective_gas_price, encoded_len, extra_weight),
1319				);
1320
1321				block_storage::EthereumCallResult::new::<T>(
1322					signer,
1323					output.map_result(|r| r.result),
1324					base_info.call_weight,
1325					encoded_len,
1326					&info,
1327					effective_gas_price,
1328				)
1329			})
1330		}
1331
1332		/// Same as [`Self::call`], but intended to be dispatched **only**
1333		/// by an EVM transaction through the EVM compatibility layer.
1334		///
1335		/// # Parameters
1336		///
1337		/// * `dest`: The Ethereum address of the account to be called
1338		/// * `value`: The balance to transfer from the `origin` to the newly created contract.
1339		/// * `weight_limit`: The gas limit used to derive the transaction weight for transaction
1340		///   payment
1341		/// * `eth_gas_limit`: The Ethereum gas limit governing the resource usage of the execution
1342		/// * `data`: The input data to pass to the contract constructor.
1343		/// * `transaction_encoded`: The RLP encoding of the signed Ethereum transaction,
1344		///   represented as [crate::evm::TransactionSigned], provided by the Ethereum wallet. This
1345		///   is used for building the Ethereum transaction root.
1346		/// * effective_gas_price: the price of a unit of gas
1347		/// * encoded len: the byte code size of the `eth_transact` extrinsic
1348		#[pallet::call_index(11)]
1349		#[pallet::weight(
1350			T::WeightInfo::eth_call(Pallet::<T>::has_dust(*value).into())
1351			.saturating_add(*weight_limit)
1352			.saturating_add(T::WeightInfo::on_finalize_block_per_tx(transaction_encoded.len() as u32))
1353		)]
1354		pub fn eth_call(
1355			origin: OriginFor<T>,
1356			dest: H160,
1357			value: U256,
1358			weight_limit: Weight,
1359			eth_gas_limit: U256,
1360			data: Vec<u8>,
1361			transaction_encoded: Vec<u8>,
1362			effective_gas_price: U256,
1363			encoded_len: u32,
1364		) -> DispatchResultWithPostInfo {
1365			let signer = Self::ensure_eth_signed(origin)?;
1366			let origin = OriginFor::<T>::signed(signer.clone());
1367
1368			Self::ensure_non_contract_if_signed(&origin)?;
1369			let mut call = Call::<T>::eth_call {
1370				dest,
1371				value,
1372				weight_limit,
1373				eth_gas_limit,
1374				data: data.clone(),
1375				transaction_encoded: transaction_encoded.clone(),
1376				effective_gas_price,
1377				encoded_len,
1378			}
1379			.into();
1380			let info = T::FeeInfo::dispatch_info(&call);
1381			let base_info = T::FeeInfo::base_dispatch_info(&mut call);
1382			drop(call);
1383
1384			block_storage::with_ethereum_context::<T>(transaction_encoded, || {
1385				let extra_weight = base_info.total_weight();
1386				let output = Self::bare_call(
1387					origin,
1388					dest,
1389					value,
1390					TransactionLimits::EthereumGas {
1391						eth_gas_limit: eth_gas_limit.saturated_into(),
1392						weight_limit,
1393						eth_tx_info: EthTxInfo::new(encoded_len, extra_weight),
1394					},
1395					data,
1396					&ExecConfig::new_eth_tx(effective_gas_price, encoded_len, extra_weight),
1397				);
1398
1399				block_storage::EthereumCallResult::new::<T>(
1400					signer,
1401					output,
1402					base_info.call_weight,
1403					encoded_len,
1404					&info,
1405					effective_gas_price,
1406				)
1407			})
1408		}
1409
1410		/// Executes a Substrate runtime call from an Ethereum transaction.
1411		///
1412		/// This dispatchable is intended to be called **only** through the EVM compatibility
1413		/// layer. The provided call will be dispatched using `RawOrigin::Signed`.
1414		///
1415		/// # Parameters
1416		///
1417		/// * `origin`: Must be an [`Origin::EthTransaction`] origin.
1418		/// * `call`: The Substrate runtime call to execute.
1419		/// * `transaction_encoded`: The RLP encoding of the Ethereum transaction,
1420		#[pallet::call_index(12)]
1421		#[pallet::weight(T::WeightInfo::eth_substrate_call(transaction_encoded.len() as u32).saturating_add(call.get_dispatch_info().call_weight))]
1422		pub fn eth_substrate_call(
1423			origin: OriginFor<T>,
1424			call: Box<<T as Config>::RuntimeCall>,
1425			transaction_encoded: Vec<u8>,
1426		) -> DispatchResultWithPostInfo {
1427			// Note that the inner dispatch uses `RawOrigin::Signed`, which cannot
1428			// re-enter `eth_substrate_call` (which requires `Origin::EthTransaction`).
1429			let signer = Self::ensure_eth_signed(origin)?;
1430			let weight_overhead =
1431				T::WeightInfo::eth_substrate_call(transaction_encoded.len() as u32);
1432
1433			block_storage::with_ethereum_context::<T>(transaction_encoded, || {
1434				let call_weight = call.get_dispatch_info().call_weight;
1435				let mut call_result = call.dispatch(RawOrigin::Signed(signer).into());
1436
1437				// Add extrinsic_overhead to the actual weight in PostDispatchInfo
1438				match &mut call_result {
1439					Ok(post_info) | Err(DispatchErrorWithPostInfo { post_info, .. }) => {
1440						post_info.actual_weight = Some(
1441							post_info
1442								.actual_weight
1443								.unwrap_or_else(|| call_weight)
1444								.saturating_add(weight_overhead),
1445						);
1446					},
1447				}
1448
1449				// Return zero EVM gas (Substrate dispatch, not EVM contract call).
1450				// Actual weight is in `post_info.actual_weight`.
1451				block_storage::EthereumCallResult {
1452					receipt_gas_info: ReceiptGasInfo::default(),
1453					result: call_result,
1454				}
1455			})
1456		}
1457
1458		/// Upload new `code` without instantiating a contract from it.
1459		///
1460		/// If the code does not already exist a deposit is reserved from the caller
1461		/// The size of the reserve depends on the size of the supplied `code`.
1462		///
1463		/// # Note
1464		///
1465		/// Anyone can instantiate a contract from any uploaded code and thus prevent its removal.
1466		/// To avoid this situation a constructor could employ access control so that it can
1467		/// only be instantiated by permissioned entities. The same is true when uploading
1468		/// through [`Self::instantiate_with_code`].
1469		///
1470		/// If the refcount of the code reaches zero after terminating the last contract that
1471		/// references this code, the code will be removed automatically.
1472		#[pallet::call_index(4)]
1473		#[pallet::weight(<T as Config>::WeightInfo::upload_code(code.len() as u32))]
1474		pub fn upload_code(
1475			origin: OriginFor<T>,
1476			code: Vec<u8>,
1477			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
1478		) -> DispatchResult {
1479			Self::ensure_non_contract_if_signed(&origin)?;
1480			Self::bare_upload_code(origin, code, storage_deposit_limit).map(|_| ())
1481		}
1482
1483		/// Remove the code stored under `code_hash` and refund the deposit to its owner.
1484		///
1485		/// A code can only be removed by its original uploader (its owner) and only if it is
1486		/// not used by any contract.
1487		#[pallet::call_index(5)]
1488		#[pallet::weight(<T as Config>::WeightInfo::remove_code())]
1489		pub fn remove_code(
1490			origin: OriginFor<T>,
1491			code_hash: sp_core::H256,
1492		) -> DispatchResultWithPostInfo {
1493			let origin = ensure_signed(origin)?;
1494			<ContractBlob<T>>::remove(&origin, code_hash)?;
1495			// we waive the fee because removing unused code is beneficial
1496			Ok(Pays::No.into())
1497		}
1498
1499		/// Privileged function that changes the code of an existing contract.
1500		///
1501		/// This takes care of updating refcounts and all other necessary operations. Returns
1502		/// an error if either the `code_hash` or `dest` do not exist.
1503		///
1504		/// # Note
1505		///
1506		/// This does **not** change the address of the contract in question. This means
1507		/// that the contract address is no longer derived from its code hash after calling
1508		/// this dispatchable.
1509		#[pallet::call_index(6)]
1510		#[pallet::weight(<T as Config>::WeightInfo::set_code())]
1511		pub fn set_code(
1512			origin: OriginFor<T>,
1513			dest: H160,
1514			code_hash: sp_core::H256,
1515		) -> DispatchResult {
1516			ensure_root(origin)?;
1517			<AccountInfoOf<T>>::try_mutate(&dest, |account| {
1518				let Some(account) = account else {
1519					return Err(<Error<T>>::ContractNotFound.into());
1520				};
1521
1522				let AccountType::Contract(ref mut contract) = account.account_type else {
1523					return Err(<Error<T>>::ContractNotFound.into());
1524				};
1525
1526				<CodeInfo<T>>::increment_refcount(code_hash)?;
1527				let _ = <CodeInfo<T>>::decrement_refcount(contract.code_hash)?;
1528				contract.code_hash = code_hash;
1529
1530				Ok(())
1531			})
1532		}
1533
1534		/// Register the callers account id so that it can be used in contract interactions.
1535		///
1536		/// This will error if the origin is already mapped or is a eth native `Address20`. It will
1537		/// take a deposit that can be released by calling [`Self::unmap_account`].
1538		#[pallet::call_index(7)]
1539		#[pallet::weight(<T as Config>::WeightInfo::map_account())]
1540		pub fn map_account(origin: OriginFor<T>) -> DispatchResult {
1541			Self::ensure_non_contract_if_signed(&origin)?;
1542			let origin = ensure_signed(origin)?;
1543			T::AddressMapper::map(&origin)
1544		}
1545
1546		/// Unregister the callers account id in order to free the deposit.
1547		///
1548		/// There is no reason to ever call this function other than freeing up the deposit.
1549		/// This is only useful when the account should no longer be used.
1550		#[pallet::call_index(8)]
1551		#[pallet::weight(<T as Config>::WeightInfo::unmap_account())]
1552		pub fn unmap_account(origin: OriginFor<T>) -> DispatchResult {
1553			let origin = ensure_signed(origin)?;
1554			T::AddressMapper::unmap(&origin)
1555		}
1556
1557		/// Dispatch an `call` with the origin set to the callers fallback address.
1558		///
1559		/// Every `AccountId32` can control its corresponding fallback account. The fallback account
1560		/// is the `AccountId20` with the last 12 bytes set to `0xEE`. This is essentially a
1561		/// recovery function in case an `AccountId20` was used without creating a mapping first.
1562		#[pallet::call_index(9)]
1563		#[pallet::weight({
1564			let dispatch_info = call.get_dispatch_info();
1565			(
1566				<T as Config>::WeightInfo::dispatch_as_fallback_account().saturating_add(dispatch_info.call_weight),
1567				dispatch_info.class
1568			)
1569		})]
1570		pub fn dispatch_as_fallback_account(
1571			origin: OriginFor<T>,
1572			call: Box<<T as Config>::RuntimeCall>,
1573		) -> DispatchResultWithPostInfo {
1574			Self::ensure_non_contract_if_signed(&origin)?;
1575			let origin = ensure_signed(origin)?;
1576			let unmapped_account =
1577				T::AddressMapper::to_fallback_account_id(&T::AddressMapper::to_address(&origin));
1578			call.dispatch(RawOrigin::Signed(unmapped_account).into())
1579		}
1580	}
1581}
1582
1583/// Create a dispatch result reflecting the amount of consumed weight.
1584fn dispatch_result<R>(
1585	result: Result<R, DispatchError>,
1586	weight_consumed: Weight,
1587	base_weight: Weight,
1588) -> DispatchResultWithPostInfo {
1589	let post_info = PostDispatchInfo {
1590		actual_weight: Some(weight_consumed.saturating_add(base_weight)),
1591		pays_fee: Default::default(),
1592	};
1593
1594	result
1595		.map(|_| post_info)
1596		.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e })
1597}
1598
1599impl<T: Config> Pallet<T> {
1600	/// A generalized version of [`Self::call`].
1601	///
1602	/// Identical to [`Self::call`] but tailored towards being called by other code within the
1603	/// runtime as opposed to from an extrinsic. It returns more information and allows the
1604	/// enablement of features that are not suitable for an extrinsic (debugging, event
1605	/// collection).
1606	pub fn bare_call(
1607		origin: OriginFor<T>,
1608		dest: H160,
1609		evm_value: U256,
1610		transaction_limits: TransactionLimits<T>,
1611		data: Vec<u8>,
1612		exec_config: &ExecConfig<T>,
1613	) -> ContractResult<ExecReturnValue, BalanceOf<T>> {
1614		let mut transaction_meter = match TransactionMeter::new(transaction_limits) {
1615			Ok(transaction_meter) => transaction_meter,
1616			Err(error) => return ContractResult { result: Err(error), ..Default::default() },
1617		};
1618		let mut storage_deposit = Default::default();
1619
1620		let try_call = || {
1621			let origin = ExecOrigin::from_runtime_origin(origin)?;
1622			let result = ExecStack::<T, ContractBlob<T>>::run_call(
1623				origin.clone(),
1624				dest,
1625				&mut transaction_meter,
1626				evm_value,
1627				data,
1628				&exec_config,
1629			)?;
1630
1631			storage_deposit = transaction_meter
1632				.execute_postponed_deposits(&origin, &exec_config)
1633				.inspect_err(|err| {
1634				log::debug!(target: LOG_TARGET, "Failed to transfer deposit: {err:?}");
1635			})?;
1636
1637			Ok(result)
1638		};
1639		let result = Self::run_guarded(try_call);
1640
1641		log::trace!(target: LOG_TARGET, "Bare call ends: \
1642			result={result:?}, \
1643			weight_consumed={:?}, \
1644			weight_required={:?}, \
1645			storage_deposit={:?}, \
1646			gas_consumed={:?}, \
1647			max_storage_deposit={:?}",
1648			transaction_meter.weight_consumed(),
1649			transaction_meter.weight_required(),
1650			storage_deposit,
1651			transaction_meter.total_consumed_gas(),
1652			transaction_meter.deposit_required()
1653		);
1654
1655		ContractResult {
1656			result: result.map_err(|r| r.error),
1657			weight_consumed: transaction_meter.weight_consumed(),
1658			weight_required: transaction_meter.weight_required(),
1659			storage_deposit,
1660			gas_consumed: transaction_meter.total_consumed_gas(),
1661			max_storage_deposit: transaction_meter.deposit_required(),
1662		}
1663	}
1664
1665	/// Prepare a dry run for the given account.
1666	///
1667	///
1668	/// This function is public because it is called by the runtime API implementation
1669	/// (see `impl_runtime_apis_plus_revive`).
1670	pub fn prepare_dry_run(account: &T::AccountId) {
1671		// Bump the  nonce to simulate what would happen
1672		// `pre-dispatch` if the transaction was executed.
1673		frame_system::Pallet::<T>::inc_account_nonce(account);
1674	}
1675
1676	/// A generalized version of [`Self::instantiate`] or [`Self::instantiate_with_code`].
1677	///
1678	/// Identical to [`Self::instantiate`] or [`Self::instantiate_with_code`] but tailored towards
1679	/// being called by other code within the runtime as opposed to from an extrinsic. It returns
1680	/// more information to the caller useful to estimate the cost of the operation.
1681	pub fn bare_instantiate(
1682		origin: OriginFor<T>,
1683		evm_value: U256,
1684		transaction_limits: TransactionLimits<T>,
1685		code: Code,
1686		data: Vec<u8>,
1687		salt: Option<[u8; 32]>,
1688		exec_config: &ExecConfig<T>,
1689	) -> ContractResult<InstantiateReturnValue, BalanceOf<T>> {
1690		let mut transaction_meter = match TransactionMeter::new(transaction_limits) {
1691			Ok(transaction_meter) => transaction_meter,
1692			Err(error) => return ContractResult { result: Err(error), ..Default::default() },
1693		};
1694
1695		let mut storage_deposit = Default::default();
1696
1697		let try_instantiate = || {
1698			let instantiate_account = T::InstantiateOrigin::ensure_origin(origin.clone())?;
1699
1700			if_tracing(|t| t.instantiate_code(&code, salt.as_ref()));
1701			let executable = match code {
1702				Code::Upload(code) if code.starts_with(&polkavm_common::program::BLOB_MAGIC) => {
1703					let upload_account = T::UploadOrigin::ensure_origin(origin)?;
1704					let executable = Self::try_upload_code(
1705						upload_account,
1706						code,
1707						BytecodeType::Pvm,
1708						&mut transaction_meter,
1709						&exec_config,
1710					)?;
1711					executable
1712				},
1713				Code::Upload(code) => {
1714					if T::AllowEVMBytecode::get() {
1715						ensure!(data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
1716						let origin = T::UploadOrigin::ensure_origin(origin)?;
1717						let executable = ContractBlob::from_evm_init_code(code, origin)?;
1718						executable
1719					} else {
1720						return Err(<Error<T>>::CodeRejected.into());
1721					}
1722				},
1723				Code::Existing(code_hash) => {
1724					let executable = ContractBlob::from_storage(code_hash, &mut transaction_meter)?;
1725					ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
1726					executable
1727				},
1728			};
1729			let instantiate_origin = ExecOrigin::from_account_id(instantiate_account.clone());
1730			let result = ExecStack::<T, ContractBlob<T>>::run_instantiate(
1731				instantiate_account,
1732				executable,
1733				&mut transaction_meter,
1734				evm_value,
1735				data,
1736				salt.as_ref(),
1737				&exec_config,
1738			);
1739
1740			storage_deposit = transaction_meter
1741				.execute_postponed_deposits(&instantiate_origin, &exec_config)
1742				.inspect_err(|err| {
1743					log::debug!(target: LOG_TARGET, "Failed to transfer deposit: {err:?}");
1744				})?;
1745			result
1746		};
1747		let output = Self::run_guarded(try_instantiate);
1748
1749		log::trace!(target: LOG_TARGET, "Bare instantiate ends: weight_consumed={:?}\
1750			weight_required={:?} \
1751			storage_deposit={:?} \
1752			gas_consumed={:?} \
1753			max_storage_deposit={:?}",
1754			transaction_meter.weight_consumed(),
1755			transaction_meter.weight_required(),
1756			storage_deposit,
1757			transaction_meter.total_consumed_gas(),
1758			transaction_meter.deposit_required()
1759		);
1760
1761		ContractResult {
1762			result: output
1763				.map(|(addr, result)| InstantiateReturnValue { result, addr })
1764				.map_err(|e| e.error),
1765			weight_consumed: transaction_meter.weight_consumed(),
1766			weight_required: transaction_meter.weight_required(),
1767			storage_deposit,
1768			gas_consumed: transaction_meter.total_consumed_gas(),
1769			max_storage_deposit: transaction_meter.deposit_required(),
1770		}
1771	}
1772
1773	/// Estimates the amount of gas that a transactions requires.
1774	///
1775	/// This function estimates the gas of the transaction according to the same binary search
1776	/// algorithm that's implemented in Geth. It stops when with an acceptable error ratio of
1777	/// 1.5% so that the algorithm terminates early.
1778	///
1779	/// # Note
1780	///
1781	/// All calls to [`Self::dry_run_eth_transact`] need to happen inside of a [`with_transaction`]
1782	/// with state rollback to ensure that dry runs subsequent to the first one preserve the correct
1783	/// amount of storage deposits needed without any kind of caching from the previous dry runs.
1784	pub fn eth_estimate_gas(
1785		tx: GenericTransaction,
1786		config: DryRunConfig<<<T as Config>::Time as Time>::Moment>,
1787	) -> Result<U256, EthTransactError>
1788	where
1789		T::Nonce: Into<U256>,
1790		CallOf<T>: SetWeightLimit,
1791	{
1792		log::debug!(target: LOG_TARGET, "eth_estimate_gas: {tx:?}");
1793
1794		let mut low = U256::zero();
1795		let mut high = Self::evm_block_gas_limit();
1796
1797		log::trace!(target: LOG_TARGET, "eth_estimate_gas starting with low={low}, high={high}");
1798
1799		// If the user has specified a gas limit then this is the limit we use as the high bound for
1800		// the binary search. Also, if the user didn't specify a gas limit then we need to skip the
1801		// balance checks.
1802		let perform_balance_checks = if let Some(gas_limit) = tx.gas {
1803			high = gas_limit;
1804			log::trace!(target: LOG_TARGET, "eth_estimate_gas high limited by the gas limit high={high}");
1805			true
1806		} else {
1807			false
1808		};
1809
1810		// Cap the high bound of the binary search based on the account's balance if it can be done.
1811		let fee_cap = tx.max_fee_per_gas.or(tx.gas_price);
1812		if let (Some(fee_cap), Some(from), true) = (fee_cap, tx.from, perform_balance_checks) {
1813			let mut available_balance = Self::evm_balance(&from);
1814			if let Some(value) = tx.value {
1815				available_balance = available_balance.checked_sub(value).ok_or_else(|| {
1816					EthTransactError::Message("insufficient funds for value transfer".into())
1817				})?;
1818			}
1819			if let Some(allowance) = available_balance.checked_div(fee_cap) {
1820				if high > allowance && allowance != U256::zero() {
1821					log::trace!(target: LOG_TARGET, "eth_estimate_gas high limited by the user's allowance high={high} allowance={allowance}");
1822					high = allowance
1823				}
1824			}
1825		}
1826
1827		// TODO: Implement a short circuit for simple transfers. We just need to determine the gas
1828		// needed for it.
1829
1830		// Perform the first dry run with the gas limit of the binary search's high bound. If it
1831		// fails then we attempt again with the max extrinsic weight in gas which we do since some
1832		// transactions fail the dry run with the highest gas limit. If both of these fail then we
1833		// return early as it means that the transaction simply can't succeed.
1834		let dry_run_results = [high, Self::evm_max_extrinsic_weight_in_gas()].map(|gas_limit| {
1835			let mut transaction = tx.clone();
1836			transaction.gas = Some(gas_limit);
1837			let eth_transact_result = with_transaction(|| {
1838				TransactionOutcome::Rollback(Ok::<_, DispatchError>(Self::dry_run_eth_transact(
1839					transaction,
1840					config.with_perform_balance_checks(perform_balance_checks),
1841				)))
1842			})
1843			.expect("Rollback shouldn't error out");
1844			(gas_limit, eth_transact_result)
1845		});
1846		let (gas_limit, first_dry_run_result) = match dry_run_results {
1847			[(gas_limit1, Ok(dry_run_result1)), (gas_limit2, Ok(dry_run_result2))] => {
1848				if dry_run_result2.eth_gas >= gas_limit2 {
1849					(gas_limit1, dry_run_result1)
1850				} else {
1851					(gas_limit2, dry_run_result2)
1852				}
1853			},
1854			[(gas_limit, Ok(dry_run_result)), (_, Err(_))] |
1855			[(_, Err(_)), (gas_limit, Ok(dry_run_result))] => (gas_limit, dry_run_result),
1856			[(_, Err(err)), (_, Err(..))] => return Err(err),
1857		};
1858		log::trace!(
1859			target: LOG_TARGET,
1860			"eth_estimate_gas first dry run succeeded with gas_limit={} consumed={}",
1861			gas_limit,
1862			first_dry_run_result.eth_gas
1863		);
1864		low = first_dry_run_result.eth_gas;
1865		high = gas_limit;
1866
1867		while low + U256::one() < high {
1868			log::trace!(target: LOG_TARGET, "eth_estimate_gas estimation iteration with low={low} high={high}");
1869			let error_ratio = high
1870				.checked_sub(low)
1871				.and_then(|value| value.checked_mul(U256::from(1000)))
1872				.and_then(|value| value.checked_div(high))
1873				.ok_or_else(|| {
1874					EthTransactError::Message(
1875						"failed to calculate error ratio in gas estimation".into(),
1876					)
1877				})?;
1878			if error_ratio <= U256::from(15) {
1879				log::trace!(
1880					target: LOG_TARGET,
1881					"eth_estimate_gas finished due to error ratio being less than 1.5% high={}",
1882					high
1883				);
1884				break;
1885			}
1886
1887			let mut midpoint = high
1888				.checked_sub(low)
1889				.and_then(|value| value.checked_div(U256::from(2)))
1890				.and_then(|value| value.checked_add(low))
1891				.ok_or_else(|| {
1892					EthTransactError::Message(
1893						"failed to calculate midpoint in gas estimation".into(),
1894					)
1895				})?;
1896
1897			if let Some(other_midpoint) = low.checked_mul(U256::from(2)) {
1898				if other_midpoint != U256::zero() {
1899					midpoint = midpoint.min(other_midpoint)
1900				}
1901			};
1902
1903			let mut transaction = tx.clone();
1904			transaction.gas = Some(midpoint);
1905			let dry_run_result = with_transaction(|| {
1906				TransactionOutcome::Rollback(Ok::<_, DispatchError>(Self::dry_run_eth_transact(
1907					transaction,
1908					config.with_perform_balance_checks(perform_balance_checks),
1909				)))
1910			})
1911			.expect("Rollback shouldn't error out");
1912			log::trace!(target: LOG_TARGET, "eth_estimate_gas dry run result with midpoint={midpoint} is dry_run_result={dry_run_result:?}");
1913			match dry_run_result {
1914				Ok(..) => {
1915					log::trace!(target: LOG_TARGET, "eth_estimate_gas dry run succeeded, new high={midpoint}");
1916					high = midpoint
1917				},
1918				Err(..) => {
1919					log::trace!(target: LOG_TARGET, "eth_estimate_gas dry run failed, new low={midpoint}");
1920					low = midpoint
1921				},
1922			}
1923		}
1924
1925		log::trace!(target: LOG_TARGET, "eth_estimate_gas completed. high={high}");
1926		Ok(high)
1927	}
1928
1929	/// Dry-run Ethereum calls.
1930	///
1931	/// # Parameters
1932	///
1933	/// - `tx`: The Ethereum transaction to simulate.
1934	pub fn dry_run_eth_transact(
1935		mut tx: GenericTransaction,
1936		dry_run_config: DryRunConfig<<<T as Config>::Time as Time>::Moment>,
1937	) -> Result<EthTransactInfo<BalanceOf<T>>, EthTransactError>
1938	where
1939		T::Nonce: Into<U256>,
1940		CallOf<T>: SetWeightLimit,
1941	{
1942		log::debug!(target: LOG_TARGET, "dry_run_eth_transact: {tx:?}");
1943
1944		let origin = T::AddressMapper::to_account_id(&tx.from.unwrap_or_default());
1945		Self::prepare_dry_run(&origin);
1946
1947		let base_fee = Self::evm_base_fee();
1948		let effective_gas_price = tx.effective_gas_price(base_fee).unwrap_or(base_fee);
1949
1950		if effective_gas_price < base_fee {
1951			Err(EthTransactError::Message(format!(
1952				"Effective gas price {effective_gas_price:?} lower than base fee {base_fee:?}"
1953			)))?;
1954		}
1955
1956		if tx.nonce.is_none() {
1957			tx.nonce = Some(<System<T>>::account_nonce(&origin).into());
1958		}
1959		if tx.chain_id.is_none() {
1960			tx.chain_id = Some(T::ChainId::get().into());
1961		}
1962
1963		// tx.into_call expects tx.gas_price to be the effective gas price
1964		tx.gas_price = Some(effective_gas_price);
1965		// we don't support priority fee for now as the tipping system in pallet-transaction-payment
1966		// works differently and the total tip needs to be known pre dispatch
1967		tx.max_priority_fee_per_gas = Some(0.into());
1968		if tx.max_fee_per_gas.is_none() {
1969			tx.max_fee_per_gas = Some(effective_gas_price);
1970		}
1971
1972		let gas = tx.gas;
1973		if tx.gas.is_none() {
1974			tx.gas = Some(Self::evm_block_gas_limit());
1975		}
1976		if tx.r#type.is_none() {
1977			tx.r#type = Some(TYPE_EIP1559.into());
1978		}
1979
1980		// Store values before moving the tx
1981		let value = tx.value.unwrap_or_default();
1982		let input = tx.input.clone().to_vec();
1983		let from = tx.from;
1984		let to = tx.to;
1985
1986		// we need to parse the weight from the transaction so that it is run
1987		// using the exact weight limit passed by the eth wallet
1988		let mut call_info = tx
1989			.into_call::<T>(CreateCallMode::DryRun)
1990			.map_err(|err| EthTransactError::Message(format!("Invalid call: {err:?}")))?;
1991
1992		// the dry-run might leave out certain fields
1993		// in those cases we skip the check that the caller has enough balance
1994		// to pay for the fees
1995		let base_info = T::FeeInfo::base_dispatch_info(&mut call_info.call);
1996		let base_weight = base_info.total_weight();
1997		let exec_config =
1998			ExecConfig::new_eth_tx(effective_gas_price, call_info.encoded_len, base_weight)
1999				.with_dry_run(dry_run_config);
2000
2001		// emulate transaction behavior
2002		let fees = call_info.tx_fee.saturating_add(call_info.storage_deposit);
2003		if let Some(from) = &from {
2004			let fees =
2005				if gas.is_some() && matches!(dry_run_config.perform_balance_checks, Some(true)) {
2006					fees
2007				} else {
2008					Zero::zero()
2009				};
2010			let balance = Self::evm_balance(from);
2011			if balance < Pallet::<T>::convert_native_to_evm(fees).saturating_add(value) {
2012				return Err(EthTransactError::Message(format!(
2013					"insufficient funds for gas * price + value ({fees:?}): address {from:?} have {balance:?} (supplied gas {gas:?})",
2014				)));
2015			}
2016		}
2017
2018		// the deposit is done when the transaction is transformed from an `eth_transact`
2019		// we emulate this behavior for the dry-run here
2020		T::FeeInfo::deposit_txfee(T::Currency::issue(fees));
2021
2022		let extract_error = |err| {
2023			if err == Error::<T>::StorageDepositNotEnoughFunds.into() {
2024				Err(EthTransactError::Message(format!("Not enough gas supplied: {err:?}")))
2025			} else {
2026				Err(EthTransactError::Message(format!("failed to run contract: {err:?}")))
2027			}
2028		};
2029
2030		let transaction_limits = TransactionLimits::EthereumGas {
2031			eth_gas_limit: call_info.eth_gas_limit.saturated_into(),
2032			weight_limit: Self::evm_max_extrinsic_weight(),
2033			eth_tx_info: EthTxInfo::new(call_info.encoded_len, base_weight),
2034		};
2035
2036		// Dry run the call
2037		let mut dry_run = match to {
2038			// A contract call.
2039			Some(dest) => {
2040				if dest == RUNTIME_PALLETS_ADDR {
2041					let Ok(dispatch_call) = <CallOf<T>>::decode(&mut &input[..]) else {
2042						return Err(EthTransactError::Message(format!(
2043							"Failed to decode pallet-call {input:?}"
2044						)));
2045					};
2046
2047					if let Err(result) =
2048						dispatch_call.clone().dispatch(RawOrigin::Signed(origin).into())
2049					{
2050						return Err(EthTransactError::Message(format!(
2051							"Failed to dispatch call: {:?}",
2052							result.error,
2053						)));
2054					};
2055
2056					Default::default()
2057				} else {
2058					// Dry run the call.
2059					let result = crate::Pallet::<T>::bare_call(
2060						OriginFor::<T>::signed(origin),
2061						dest,
2062						value,
2063						transaction_limits,
2064						input.clone(),
2065						&exec_config,
2066					);
2067
2068					let data = match result.result {
2069						Ok(return_value) => {
2070							if return_value.did_revert() {
2071								return Err(EthTransactError::Data(return_value.data));
2072							}
2073							return_value.data
2074						},
2075						Err(err) => {
2076							log::debug!(target: LOG_TARGET, "Failed to execute call: {err:?}");
2077							return extract_error(err);
2078						},
2079					};
2080
2081					EthTransactInfo {
2082						weight_required: result.weight_required,
2083						storage_deposit: result.storage_deposit.charge_or_zero(),
2084						max_storage_deposit: result.max_storage_deposit.charge_or_zero(),
2085						data,
2086						eth_gas: Default::default(),
2087					}
2088				}
2089			},
2090			// A contract deployment
2091			None => {
2092				// Extract code and data from the input.
2093				let (code, data) = if input.starts_with(&polkavm_common::program::BLOB_MAGIC) {
2094					extract_code_and_data(&input).unwrap_or_else(|| (input, Default::default()))
2095				} else {
2096					(input, vec![])
2097				};
2098
2099				// Dry run the call.
2100				let result = crate::Pallet::<T>::bare_instantiate(
2101					OriginFor::<T>::signed(origin),
2102					value,
2103					transaction_limits,
2104					Code::Upload(code.clone()),
2105					data.clone(),
2106					None,
2107					&exec_config,
2108				);
2109
2110				let returned_data = match result.result {
2111					Ok(return_value) => {
2112						if return_value.result.did_revert() {
2113							return Err(EthTransactError::Data(return_value.result.data));
2114						}
2115						return_value.result.data
2116					},
2117					Err(err) => {
2118						log::debug!(target: LOG_TARGET, "Failed to instantiate: {err:?}");
2119						return extract_error(err);
2120					},
2121				};
2122
2123				EthTransactInfo {
2124					weight_required: result.weight_required,
2125					storage_deposit: result.storage_deposit.charge_or_zero(),
2126					max_storage_deposit: result.max_storage_deposit.charge_or_zero(),
2127					data: returned_data,
2128					eth_gas: Default::default(),
2129				}
2130			},
2131		};
2132
2133		// replace the weight passed in the transaction with the dry_run result
2134		call_info.call.set_weight_limit(dry_run.weight_required);
2135
2136		// we notify the wallet that the tx would not fit
2137		let total_weight = T::FeeInfo::dispatch_info(&call_info.call).total_weight();
2138		let max_weight = Self::evm_max_extrinsic_weight();
2139		if total_weight.any_gt(max_weight) {
2140			log::debug!(target: LOG_TARGET, "Transaction weight estimate exceeds extrinsic maximum: \
2141				total_weight={total_weight:?} \
2142				max_weight={max_weight:?}",
2143			);
2144
2145			Err(EthTransactError::Message(format!(
2146				"\
2147				The transaction consumes more than the allowed weight. \
2148				needed={total_weight} \
2149				allowed={max_weight} \
2150				overweight_by={}\
2151				",
2152				total_weight.saturating_sub(max_weight),
2153			)))?;
2154		}
2155
2156		// not enough gas supplied to pay for both the tx fees and the storage deposit
2157		let transaction_fee = T::FeeInfo::tx_fee(call_info.encoded_len, &call_info.call);
2158		let available_fee = T::FeeInfo::remaining_txfee();
2159		if transaction_fee > available_fee {
2160			Err(EthTransactError::Message(format!(
2161				"Not enough gas supplied: Off by: {:?}",
2162				transaction_fee.saturating_sub(available_fee),
2163			)))?;
2164		}
2165
2166		let total_cost = transaction_fee.saturating_add(dry_run.max_storage_deposit);
2167		let total_cost_wei = Pallet::<T>::convert_native_to_evm(total_cost);
2168		let (mut eth_gas, rest) = total_cost_wei.div_mod(base_fee);
2169		if !rest.is_zero() {
2170			eth_gas = eth_gas.saturating_add(1_u32.into());
2171		}
2172
2173		log::debug!(target: LOG_TARGET, "\
2174			dry_run_eth_transact finished: \
2175			weight_limit={}, \
2176			total_weight={total_weight}, \
2177			max_weight={max_weight}, \
2178			weight_left={}, \
2179			eth_gas={eth_gas}, \
2180			encoded_len={}, \
2181			tx_fee={transaction_fee:?}, \
2182			storage_deposit={:?}, \
2183			max_storage_deposit={:?}\
2184			",
2185			dry_run.weight_required,
2186			max_weight.saturating_sub(total_weight),
2187			call_info.encoded_len,
2188			dry_run.storage_deposit,
2189			dry_run.max_storage_deposit,
2190
2191		);
2192		dry_run.eth_gas = eth_gas;
2193		Ok(dry_run)
2194	}
2195
2196	/// Get the balance with EVM decimals of the given `address`.
2197	///
2198	/// Returns the spendable balance excluding the existential deposit.
2199	pub fn evm_balance(address: &H160) -> U256 {
2200		let balance = AccountInfo::<T>::balance_of((*address).into());
2201		Self::convert_native_to_evm(balance)
2202	}
2203
2204	/// Get the current Ethereum block from storage.
2205	pub fn eth_block() -> EthBlock {
2206		EthereumBlock::<T>::get()
2207	}
2208
2209	/// Convert the Ethereum block number into the Ethereum block hash.
2210	///
2211	/// # Note
2212	///
2213	/// The Ethereum block number is identical to the Substrate block number.
2214	/// If the provided block number is outside of the pruning None is returned.
2215	pub fn eth_block_hash_from_number(number: U256) -> Option<H256> {
2216		let number = BlockNumberFor::<T>::try_from(number).ok()?;
2217		let hash = <BlockHash<T>>::get(number);
2218		if hash == H256::zero() { None } else { Some(hash) }
2219	}
2220
2221	/// The details needed to reconstruct the receipt information offchain.
2222	pub fn eth_receipt_data() -> Vec<ReceiptGasInfo> {
2223		ReceiptInfoData::<T>::get()
2224	}
2225
2226	/// Set the EVM balance of an account.
2227	///
2228	/// The account's total balance becomes the EVM value plus the existential deposit,
2229	/// consistent with `evm_balance` which returns the spendable balance excluding the existential
2230	/// deposit.
2231	pub fn set_evm_balance(address: &H160, evm_value: U256) -> Result<(), Error<T>> {
2232		let (balance, dust) = Self::new_balance_with_dust(evm_value)
2233			.map_err(|_| <Error<T>>::BalanceConversionFailed)?;
2234		let account_id = T::AddressMapper::to_account_id(&address);
2235		T::Currency::set_balance(&account_id, balance);
2236		AccountInfoOf::<T>::mutate(&address, |account| {
2237			if let Some(account) = account {
2238				account.dust = dust;
2239			} else {
2240				*account = Some(AccountInfo { dust, ..Default::default() });
2241			}
2242		});
2243
2244		Ok(())
2245	}
2246
2247	/// Construct native balance from EVM balance.
2248	///
2249	/// Adds the existential deposit and returns the native balance plus the dust.
2250	pub fn new_balance_with_dust(
2251		evm_value: U256,
2252	) -> Result<(BalanceOf<T>, u32), BalanceConversionError> {
2253		let ed = T::Currency::minimum_balance();
2254		let balance_with_dust = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(evm_value)?;
2255		let (value, dust) = balance_with_dust.deconstruct();
2256
2257		Ok((ed.saturating_add(value), dust))
2258	}
2259
2260	/// Get the nonce for the given `address`.
2261	pub fn evm_nonce(address: &H160) -> u32
2262	where
2263		T::Nonce: Into<u32>,
2264	{
2265		let account = T::AddressMapper::to_account_id(&address);
2266		System::<T>::account_nonce(account).into()
2267	}
2268
2269	/// Get the block gas limit.
2270	pub fn evm_block_gas_limit() -> U256 {
2271		// We just return `u64::MAX` because the gas cost of a transaction can get very large when
2272		// the transaction executes many storage deposits (in theory a contract can behave like a
2273		// factory, procedurally create code and make contract creation calls to store that as
2274		// code). It is too brittle to estimate a maximally possible amount here.
2275		// On the other hand, the data type `u64` seems to be the "common denominator" as the
2276		// typical data type tools and Ethereum implementations use to represent gas amounts.
2277		u64::MAX.into()
2278	}
2279
2280	/// Returns the maximum value of gas that can be represented in weights.
2281	pub fn evm_max_extrinsic_weight_in_gas() -> U256 {
2282		let max_extrinsic_fee = T::FeeInfo::weight_to_fee(&Self::evm_max_extrinsic_weight());
2283		let gas_scale: BalanceOf<T> = T::GasScale::get().into();
2284		(max_extrinsic_fee / gas_scale).into()
2285	}
2286
2287	/// The maximum weight an `eth_transact` is allowed to consume.
2288	pub fn evm_max_extrinsic_weight() -> Weight {
2289		let factor = <T as Config>::MaxEthExtrinsicWeight::get();
2290		let max_weight = <T as frame_system::Config>::BlockWeights::get()
2291			.get(DispatchClass::Normal)
2292			.max_extrinsic
2293			.unwrap_or_else(|| <T as frame_system::Config>::BlockWeights::get().max_block);
2294		Weight::from_parts(
2295			factor.saturating_mul_int(max_weight.ref_time()),
2296			factor.saturating_mul_int(max_weight.proof_size()),
2297		)
2298	}
2299
2300	/// Get the base gas price.
2301	pub fn evm_base_fee() -> U256 {
2302		let gas_scale = <T as Config>::GasScale::get();
2303		let multiplier = T::FeeInfo::next_fee_multiplier();
2304		multiplier
2305			.saturating_mul_int::<u128>(T::NativeToEthRatio::get().into())
2306			.saturating_mul(gas_scale.saturated_into())
2307			.into()
2308	}
2309
2310	/// Build an EVM tracer from the given tracer type.
2311	pub fn evm_tracer(tracer_type: TracerType) -> Tracer<T>
2312	where
2313		T::Nonce: Into<u32>,
2314	{
2315		match tracer_type {
2316			TracerType::CallTracer(config) => CallTracer::new(config.unwrap_or_default()).into(),
2317			TracerType::PrestateTracer(config) => {
2318				PrestateTracer::new(config.unwrap_or_default()).into()
2319			},
2320			TracerType::ExecutionTracer(config) => {
2321				ExecutionTracer::new(config.unwrap_or_default()).into()
2322			},
2323		}
2324	}
2325
2326	/// A generalized version of [`Self::upload_code`].
2327	///
2328	/// It is identical to [`Self::upload_code`] and only differs in the information it returns.
2329	pub fn bare_upload_code(
2330		origin: OriginFor<T>,
2331		code: Vec<u8>,
2332		storage_deposit_limit: BalanceOf<T>,
2333	) -> CodeUploadResult<BalanceOf<T>> {
2334		let origin = T::UploadOrigin::ensure_origin(origin)?;
2335
2336		let bytecode_type = if code.starts_with(&polkavm_common::program::BLOB_MAGIC) {
2337			BytecodeType::Pvm
2338		} else {
2339			if !T::AllowEVMBytecode::get() {
2340				return Err(<Error<T>>::CodeRejected.into());
2341			}
2342			BytecodeType::Evm
2343		};
2344
2345		let mut meter = TransactionMeter::new(TransactionLimits::WeightAndDeposit {
2346			weight_limit: Default::default(),
2347			deposit_limit: storage_deposit_limit,
2348		})?;
2349
2350		let module = Self::try_upload_code(
2351			origin,
2352			code,
2353			bytecode_type,
2354			&mut meter,
2355			&ExecConfig::new_substrate_tx(),
2356		)?;
2357		Ok(CodeUploadReturnValue {
2358			code_hash: *module.code_hash(),
2359			deposit: meter.deposit_consumed().charge_or_zero(),
2360		})
2361	}
2362
2363	/// Query storage of a specified contract under a specified key.
2364	pub fn get_storage(address: H160, key: [u8; 32]) -> GetStorageResult {
2365		let contract_info =
2366			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
2367
2368		let maybe_value = contract_info.read(&Key::from_fixed(key));
2369		Ok(maybe_value)
2370	}
2371
2372	/// Get the immutable data of a specified contract.
2373	///
2374	/// Returns `None` if the contract does not exist or has no immutable data.
2375	pub fn get_immutables(address: H160) -> Option<ImmutableData> {
2376		let immutable_data = <ImmutableDataOf<T>>::get(address);
2377		immutable_data
2378	}
2379
2380	/// Sets immutable data of a contract
2381	///
2382	/// Returns an error if the contract does not exist.
2383	///
2384	/// # Warning
2385	///
2386	/// Does not collect any storage deposit. Not safe to be called by user controlled code.
2387	pub fn set_immutables(address: H160, data: ImmutableData) -> Result<(), ContractAccessError> {
2388		AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
2389		<ImmutableDataOf<T>>::insert(address, data);
2390		Ok(())
2391	}
2392
2393	/// Query storage of a specified contract under a specified variable-sized key.
2394	pub fn get_storage_var_key(address: H160, key: Vec<u8>) -> GetStorageResult {
2395		let contract_info =
2396			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
2397
2398		let maybe_value = contract_info.read(
2399			&Key::try_from_var(key)
2400				.map_err(|_| ContractAccessError::KeyDecodingFailed)?
2401				.into(),
2402		);
2403		Ok(maybe_value)
2404	}
2405
2406	/// Convert a native balance to EVM balance.
2407	pub fn convert_native_to_evm(value: impl Into<BalanceWithDust<BalanceOf<T>>>) -> U256 {
2408		let (value, dust) = value.into().deconstruct();
2409		value
2410			.into()
2411			.saturating_mul(T::NativeToEthRatio::get().into())
2412			.saturating_add(dust.into())
2413	}
2414
2415	/// Set storage of a specified contract under a specified key.
2416	///
2417	/// If the `value` is `None`, the storage entry is deleted.
2418	///
2419	/// Returns an error if the contract does not exist or if the write operation fails.
2420	///
2421	/// # Warning
2422	///
2423	/// Does not collect any storage deposit. Not safe to be called by user controlled code.
2424	pub fn set_storage(address: H160, key: [u8; 32], value: Option<Vec<u8>>) -> SetStorageResult {
2425		let contract_info =
2426			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
2427
2428		contract_info
2429			.write(&Key::from_fixed(key), value, None, false)
2430			.map_err(ContractAccessError::StorageWriteFailed)
2431	}
2432
2433	/// Set the storage of a specified contract under a specified variable-sized key.
2434	///
2435	/// If the `value` is `None`, the storage entry is deleted.
2436	///
2437	/// Returns an error if the contract does not exist, if the key decoding fails,
2438	/// or if the write operation fails.
2439	///
2440	/// # Warning
2441	///
2442	/// Does not collect any storage deposit. Not safe to be called by user controlled code.
2443	pub fn set_storage_var_key(
2444		address: H160,
2445		key: Vec<u8>,
2446		value: Option<Vec<u8>>,
2447	) -> SetStorageResult {
2448		let contract_info =
2449			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
2450
2451		contract_info
2452			.write(
2453				&Key::try_from_var(key)
2454					.map_err(|_| ContractAccessError::KeyDecodingFailed)?
2455					.into(),
2456				value,
2457				None,
2458				false,
2459			)
2460			.map_err(ContractAccessError::StorageWriteFailed)
2461	}
2462
2463	/// Pallet account, used to hold funds for contracts upload deposit.
2464	pub fn account_id() -> T::AccountId {
2465		use frame_support::PalletId;
2466		use sp_runtime::traits::AccountIdConversion;
2467		PalletId(*b"py/reviv").into_account_truncating()
2468	}
2469
2470	/// The address of the validator that produced the current block.
2471	pub fn block_author() -> H160 {
2472		use frame_support::traits::FindAuthor;
2473
2474		let digest = <frame_system::Pallet<T>>::digest();
2475		let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime());
2476
2477		T::FindAuthor::find_author(pre_runtime_digests)
2478			.map(|account_id| T::AddressMapper::to_address(&account_id))
2479			.unwrap_or_default()
2480	}
2481
2482	/// Returns the code at `address`.
2483	///
2484	/// This takes pre-compiles into account.
2485	pub fn code(address: &H160) -> Vec<u8> {
2486		use precompiles::{All, Precompiles};
2487		if let Some(code) = <All<T>>::code(address.as_fixed_bytes()) {
2488			return code.into();
2489		}
2490		AccountInfo::<T>::load_contract(&address)
2491			.and_then(|contract| <PristineCode<T>>::get(contract.code_hash))
2492			.map(|code| code.into())
2493			.unwrap_or_default()
2494	}
2495
2496	/// Uploads new code and returns the Vm binary contract blob and deposit amount collected.
2497	pub fn try_upload_code(
2498		origin: T::AccountId,
2499		code: Vec<u8>,
2500		code_type: BytecodeType,
2501		meter: &mut TransactionMeter<T>,
2502		exec_config: &ExecConfig<T>,
2503	) -> Result<ContractBlob<T>, DispatchError> {
2504		let mut module = match code_type {
2505			BytecodeType::Pvm => ContractBlob::from_pvm_code(code, origin)?,
2506			BytecodeType::Evm => ContractBlob::from_evm_runtime_code(code, origin)?,
2507		};
2508		module.store_code(exec_config, meter)?;
2509		Ok(module)
2510	}
2511
2512	/// Run the supplied function `f` if no other instance of this pallet is on the stack.
2513	fn run_guarded<R, F: FnOnce() -> Result<R, ExecError>>(f: F) -> Result<R, ExecError> {
2514		executing_contract::using_once(&mut false, || {
2515			executing_contract::with(|f| {
2516				// Fail if already entered contract execution
2517				if *f {
2518					return Err(())
2519				}
2520				// We are entering contract execution
2521				*f = true;
2522				Ok(())
2523			})
2524				.expect("Returns `Ok` if called within `using_once`. It is syntactically obvious that this is the case; qed")
2525				.map_err(|_| <Error<T>>::ReenteredPallet.into())
2526				.map(|_| f())
2527				.and_then(|r| r)
2528		})
2529	}
2530
2531	/// Transfer a deposit from some account to another.
2532	///
2533	/// `from` is usually the transaction origin and `to` a contract or
2534	/// the pallets own account.
2535	fn charge_deposit(
2536		hold_reason: Option<HoldReason>,
2537		from: &T::AccountId,
2538		to: &T::AccountId,
2539		amount: BalanceOf<T>,
2540		exec_config: &ExecConfig<T>,
2541	) -> DispatchResult {
2542		use frame_support::traits::tokens::{Fortitude, Precision, Preservation};
2543
2544		if amount.is_zero() {
2545			return Ok(());
2546		}
2547
2548		match (exec_config.collect_deposit_from_hold.is_some(), hold_reason) {
2549			(true, hold_reason) => {
2550				T::FeeInfo::withdraw_txfee(amount)
2551					.ok_or(())
2552					.and_then(|credit| T::Currency::resolve(to, credit).map_err(|_| ()))
2553					.and_then(|_| {
2554						if let Some(hold_reason) = hold_reason {
2555							T::Currency::hold(&hold_reason.into(), to, amount).map_err(|_| ())?;
2556						}
2557						Ok(())
2558					})
2559					.map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
2560			},
2561			(false, Some(hold_reason)) => {
2562				T::Currency::transfer_and_hold(
2563					&hold_reason.into(),
2564					from,
2565					to,
2566					amount,
2567					Precision::Exact,
2568					Preservation::Preserve,
2569					Fortitude::Polite,
2570				)
2571				.map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
2572			},
2573			(false, None) => {
2574				T::Currency::transfer(from, to, amount, Preservation::Preserve)
2575					.map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
2576			},
2577		}
2578		Ok(())
2579	}
2580
2581	/// Refund a deposit.
2582	///
2583	/// `to` is usually the transaction origin and `from` a contract or
2584	/// the pallets own account.
2585	fn refund_deposit(
2586		hold_reason: HoldReason,
2587		from: &T::AccountId,
2588		to: &T::AccountId,
2589		amount: BalanceOf<T>,
2590		exec_config: Option<&ExecConfig<T>>,
2591	) -> Result<(), DispatchError> {
2592		use frame_support::traits::{
2593			fungible::InspectHold,
2594			tokens::{Fortitude, Precision, Preservation, Restriction},
2595		};
2596
2597		if amount.is_zero() {
2598			return Ok(());
2599		}
2600
2601		let hold_reason = hold_reason.into();
2602		let result = if exec_config.map(|c| c.collect_deposit_from_hold.is_some()).unwrap_or(false)
2603		{
2604			T::Currency::release(&hold_reason, from, amount, Precision::Exact)
2605				.and_then(|amount| {
2606					T::Currency::withdraw(
2607						from,
2608						amount,
2609						Precision::Exact,
2610						Preservation::Preserve,
2611						Fortitude::Polite,
2612					)
2613				})
2614				.map(T::FeeInfo::deposit_txfee)
2615		} else {
2616			T::Currency::transfer_on_hold(
2617				&hold_reason,
2618				from,
2619				to,
2620				amount,
2621				Precision::Exact,
2622				Restriction::Free,
2623				Fortitude::Polite,
2624			)
2625			.map(|_| ())
2626		};
2627
2628		result.map_err(|_| {
2629			let available = T::Currency::balance_on_hold(&hold_reason, from);
2630			if available < amount {
2631				// The storage deposit accounting got out of sync with the balance: This would be a
2632				// straight up bug in this pallet.
2633				log::error!(
2634					target: LOG_TARGET,
2635					"Failed to refund storage deposit {:?} from contract {:?} to origin {:?}. Not enough deposit: {:?}. This is a bug.",
2636					amount, from, to, available,
2637				);
2638				Error::<T>::StorageRefundNotEnoughFunds.into()
2639			} else {
2640				// There are some locks preventing the refund. This could be the case if the
2641				// contract participates in government. The consequence is that if a contract votes
2642				// with its storage deposit it would no longer be possible to remove storage without first
2643				// reducing the lock.
2644				log::warn!(
2645					target: LOG_TARGET,
2646					"Failed to refund storage deposit {:?} from contract {:?} to origin {:?}. First remove locks (staking, governance) from the contracts account.",
2647					amount, from, to,
2648				);
2649				Error::<T>::StorageRefundLocked.into()
2650			}
2651		})
2652	}
2653
2654	/// Returns true if the evm value carries dust.
2655	fn has_dust(value: U256) -> bool {
2656		value % U256::from(<T>::NativeToEthRatio::get()) != U256::zero()
2657	}
2658
2659	/// Returns true if the evm value carries balance.
2660	fn has_balance(value: U256) -> bool {
2661		value >= U256::from(<T>::NativeToEthRatio::get())
2662	}
2663
2664	/// Return the existential deposit of [`Config::Currency`].
2665	fn min_balance() -> BalanceOf<T> {
2666		<T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
2667	}
2668
2669	/// Deposit a pallet revive event.
2670	///
2671	/// This method will be called by the EVM to deposit events emitted by the contract.
2672	/// Therefore all events must be contract emitted events.
2673	fn deposit_event(event: Event<T>) {
2674		<frame_system::Pallet<T>>::deposit_event(<T as Config>::RuntimeEvent::from(event))
2675	}
2676
2677	// Returns Ok with the account that signed the eth transaction.
2678	fn ensure_eth_signed(origin: OriginFor<T>) -> Result<AccountIdOf<T>, DispatchError> {
2679		match <T as Config>::RuntimeOrigin::from(origin).into() {
2680			Ok(Origin::EthTransaction(signer)) => Ok(signer),
2681			_ => Err(BadOrigin.into()),
2682		}
2683	}
2684
2685	/// Ensure that the origin is neither a pre-compile nor a contract.
2686	///
2687	/// This enforces EIP-3607.
2688	fn ensure_non_contract_if_signed(origin: &OriginFor<T>) -> DispatchResult {
2689		if DebugSettings::bypass_eip_3607::<T>() {
2690			return Ok(());
2691		}
2692		let Some(address) = origin
2693			.as_system_ref()
2694			.and_then(|o| o.as_signed())
2695			.map(<T::AddressMapper as AddressMapper<T>>::to_address)
2696		else {
2697			return Ok(());
2698		};
2699		if exec::is_precompile::<T, ContractBlob<T>>(&address) ||
2700			<AccountInfo<T>>::is_contract(&address)
2701		{
2702			log::debug!(
2703				target: crate::LOG_TARGET,
2704				"EIP-3607: reject tx as pre-compile or account exist at {address:?}",
2705			);
2706			Err(DispatchError::BadOrigin)
2707		} else {
2708			Ok(())
2709		}
2710	}
2711}
2712
2713/// The address used to call the runtime's pallets dispatchables
2714///
2715/// Note:
2716/// computed with PalletId(*b"py/paddr").into_account_truncating();
2717pub const RUNTIME_PALLETS_ADDR: H160 =
2718	H160(hex_literal::hex!("6d6f646c70792f70616464720000000000000000"));
2719
2720// Set up a global reference to the boolean flag used for the re-entrancy guard.
2721environmental!(executing_contract: bool);
2722
2723sp_api::decl_runtime_apis! {
2724	/// The API used to dry-run contract interactions.
2725	#[api_version(1)]
2726	pub trait ReviveApi<AccountId, Balance, Nonce, BlockNumber, Moment> where
2727		AccountId: Codec,
2728		Balance: Codec,
2729		Nonce: Codec,
2730		BlockNumber: Codec,
2731		Moment: Codec,
2732	{
2733		/// Returns the current ETH block.
2734		///
2735		/// This is one block behind the substrate block.
2736		fn eth_block() -> EthBlock;
2737
2738		/// Returns the ETH block hash for the given block number.
2739		fn eth_block_hash(number: U256) -> Option<H256>;
2740
2741		/// The details needed to reconstruct the receipt information offchain.
2742		///
2743		/// # Note
2744		///
2745		/// Each entry corresponds to the appropriate Ethereum transaction in the current block.
2746		fn eth_receipt_data() -> Vec<ReceiptGasInfo>;
2747
2748		/// Returns the block gas limit.
2749		fn block_gas_limit() -> U256;
2750
2751		/// Returns the block gas limit as calculated from the weights.
2752		fn max_extrinsic_weight_in_gas() -> U256;
2753
2754		/// Returns the free balance of the given `[H160]` address, using EVM decimals.
2755		fn balance(address: H160) -> U256;
2756
2757		/// Returns the gas price.
2758		fn gas_price() -> U256;
2759
2760		/// Returns the nonce of the given `[H160]` address.
2761		fn nonce(address: H160) -> Nonce;
2762
2763		/// Perform a call from a specified account to a given contract.
2764		///
2765		/// See [`crate::Pallet::bare_call`].
2766		fn call(
2767			origin: AccountId,
2768			dest: H160,
2769			value: Balance,
2770			gas_limit: Option<Weight>,
2771			storage_deposit_limit: Option<Balance>,
2772			input_data: Vec<u8>,
2773		) -> ContractResult<ExecReturnValue, Balance>;
2774
2775		/// Instantiate a new contract.
2776		///
2777		/// See `[crate::Pallet::bare_instantiate]`.
2778		fn instantiate(
2779			origin: AccountId,
2780			value: Balance,
2781			gas_limit: Option<Weight>,
2782			storage_deposit_limit: Option<Balance>,
2783			code: Code,
2784			data: Vec<u8>,
2785			salt: Option<[u8; 32]>,
2786		) -> ContractResult<InstantiateReturnValue, Balance>;
2787
2788
2789		/// Perform an Ethereum call.
2790		///
2791		/// Deprecated use `v2` version instead.
2792		/// See [`crate::Pallet::dry_run_eth_transact`]
2793		fn eth_transact(tx: GenericTransaction) -> Result<EthTransactInfo<Balance>, EthTransactError>;
2794
2795		/// Perform an Ethereum call.
2796		///
2797		/// See [`crate::Pallet::dry_run_eth_transact`]
2798		fn eth_transact_with_config(
2799			tx: GenericTransaction,
2800			config: DryRunConfig<Moment>,
2801		) -> Result<EthTransactInfo<Balance>, EthTransactError>;
2802
2803		/// Estimates the amount of gas that a transactions requires.
2804		///
2805		/// This function estimates the gas of the transaction according to the same binary search
2806		/// algorithm that's implemented in Geth. It stops when with an acceptable error ratio of
2807		/// 1.5% so that the algorithm terminates early.
2808		fn eth_estimate_gas(
2809			tx: GenericTransaction,
2810			config: DryRunConfig<Moment>
2811		) -> Result<U256, EthTransactError>;
2812
2813		/// Upload new code without instantiating a contract from it.
2814		///
2815		/// See [`crate::Pallet::bare_upload_code`].
2816		fn upload_code(
2817			origin: AccountId,
2818			code: Vec<u8>,
2819			storage_deposit_limit: Option<Balance>,
2820		) -> CodeUploadResult<Balance>;
2821
2822		/// Query a given storage key in a given contract.
2823		///
2824		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
2825		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
2826		/// doesn't exist, or doesn't have a contract then `Err` is returned.
2827		fn get_storage(
2828			address: H160,
2829			key: [u8; 32],
2830		) -> GetStorageResult;
2831
2832		/// Query a given variable-sized storage key in a given contract.
2833		///
2834		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
2835		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
2836		/// doesn't exist, or doesn't have a contract then `Err` is returned.
2837		fn get_storage_var_key(
2838			address: H160,
2839			key: Vec<u8>,
2840		) -> GetStorageResult;
2841
2842		/// Traces the execution of an entire block and returns call traces.
2843		///
2844		/// This is intended to be called through `state_call` to replay the block from the
2845		/// parent block.
2846		///
2847		/// See eth-rpc `debug_traceBlockByNumber` for usage.
2848		fn trace_block(
2849			block: Block,
2850			config: TracerType
2851		) -> Vec<(u32, Trace)>;
2852
2853		/// Traces the execution of a specific transaction within a block.
2854		///
2855		/// This is intended to be called through `state_call` to replay the block from the
2856		/// parent hash up to the transaction.
2857		///
2858		/// See eth-rpc `debug_traceTransaction` for usage.
2859		fn trace_tx(
2860			block: Block,
2861			tx_index: u32,
2862			config: TracerType
2863		) -> Option<Trace>;
2864
2865		/// Dry run and return the trace of the given call.
2866		///
2867		/// See eth-rpc `debug_traceCall` for usage.
2868		fn trace_call(tx: GenericTransaction, config: TracerType) -> Result<Trace, EthTransactError>;
2869
2870		/// The address of the validator that produced the current block.
2871		fn block_author() -> H160;
2872
2873		/// Get the H160 address associated to this account id
2874		fn address(account_id: AccountId) -> H160;
2875
2876		/// Get the account id associated to this H160 address.
2877		fn account_id(address: H160) -> AccountId;
2878
2879		/// The address used to call the runtime's pallets dispatchables
2880		fn runtime_pallets_address() -> H160;
2881
2882		/// The code at the specified address taking pre-compiles into account.
2883		fn code(address: H160) -> Vec<u8>;
2884
2885		/// Construct the new balance and dust components of this EVM balance.
2886		fn new_balance_with_dust(balance: U256) -> Result<(Balance, u32), BalanceConversionError>;
2887	}
2888}
2889
2890/// This macro wraps substrate's `impl_runtime_apis!` and implements `pallet_revive` runtime APIs
2891/// and other required traits.
2892///
2893/// # Note
2894///
2895/// This also implements [`SetWeightLimit`] for the runtime call.
2896///
2897/// # Parameters
2898/// - `$Runtime`: The runtime type to implement the APIs for.
2899/// - `$Revive`: The name under which revive is declared in `construct_runtime`.
2900/// - `$Executive`: The Executive type of the runtime.
2901/// - `$EthExtra`: Type for additional Ethereum runtime extension.
2902/// - `$($rest:tt)*`: Remaining input to be forwarded to the underlying `impl_runtime_apis!`.
2903#[macro_export]
2904macro_rules! impl_runtime_apis_plus_revive_traits {
2905	($Runtime: ty, $Revive: ident, $Executive: ty, $EthExtra: ty, $($rest:tt)*) => {
2906
2907		type __ReviveMacroMoment = <<$Runtime as $crate::Config>::Time as $crate::Time>::Moment;
2908
2909		impl $crate::evm::runtime::SetWeightLimit for RuntimeCall {
2910			fn set_weight_limit(&mut self, new_weight_limit: Weight) -> Weight {
2911				use $crate::pallet::Call as ReviveCall;
2912				match self {
2913					Self::$Revive(
2914						ReviveCall::eth_call{ weight_limit, .. } |
2915						ReviveCall::eth_instantiate_with_code{ weight_limit, .. }
2916					) => {
2917						let old = *weight_limit;
2918						*weight_limit = new_weight_limit;
2919						old
2920					},
2921					_ => Weight::default(),
2922				}
2923			}
2924		}
2925
2926		impl_runtime_apis! {
2927			$($rest)*
2928
2929
2930			impl pallet_revive::ReviveApi<Block, AccountId, Balance, Nonce, BlockNumber, __ReviveMacroMoment> for $Runtime
2931			{
2932				fn eth_block() -> $crate::EthBlock {
2933					$crate::Pallet::<Self>::eth_block()
2934				}
2935
2936				fn eth_block_hash(number: $crate::U256) -> Option<$crate::H256> {
2937					$crate::Pallet::<Self>::eth_block_hash_from_number(number)
2938				}
2939
2940				fn eth_receipt_data() -> Vec<$crate::ReceiptGasInfo> {
2941					$crate::Pallet::<Self>::eth_receipt_data()
2942				}
2943
2944				fn balance(address: $crate::H160) -> $crate::U256 {
2945					$crate::Pallet::<Self>::evm_balance(&address)
2946				}
2947
2948				fn block_author() -> $crate::H160 {
2949					$crate::Pallet::<Self>::block_author()
2950				}
2951
2952				fn block_gas_limit() -> $crate::U256 {
2953					$crate::Pallet::<Self>::evm_block_gas_limit()
2954				}
2955
2956				fn max_extrinsic_weight_in_gas() -> $crate::U256 {
2957					$crate::Pallet::<Self>::evm_max_extrinsic_weight_in_gas()
2958				}
2959
2960				fn gas_price() -> $crate::U256 {
2961					$crate::Pallet::<Self>::evm_base_fee()
2962				}
2963
2964				fn nonce(address: $crate::H160) -> Nonce {
2965					use $crate::AddressMapper;
2966					let account = <Self as $crate::Config>::AddressMapper::to_account_id(&address);
2967					$crate::frame_system::Pallet::<Self>::account_nonce(account)
2968				}
2969
2970				fn address(account_id: AccountId) -> $crate::H160 {
2971					use $crate::AddressMapper;
2972					<Self as $crate::Config>::AddressMapper::to_address(&account_id)
2973				}
2974
2975				fn eth_transact(
2976					tx: $crate::evm::GenericTransaction,
2977				) -> Result<$crate::EthTransactInfo<Balance>, $crate::EthTransactError> {
2978					use $crate::{
2979						codec::Encode, evm::runtime::EthExtra, frame_support::traits::Get,
2980						sp_runtime::traits::TransactionExtension,
2981						sp_runtime::traits::Block as BlockT
2982					};
2983					$crate::Pallet::<Self>::dry_run_eth_transact(tx, Default::default())
2984				}
2985
2986				fn eth_transact_with_config(
2987					tx: $crate::evm::GenericTransaction,
2988					config: $crate::DryRunConfig<__ReviveMacroMoment>,
2989				) -> Result<$crate::EthTransactInfo<Balance>, $crate::EthTransactError> {
2990					use $crate::{
2991						codec::Encode, evm::runtime::EthExtra, frame_support::traits::Get,
2992						sp_runtime::traits::TransactionExtension,
2993						sp_runtime::traits::Block as BlockT
2994					};
2995					$crate::Pallet::<Self>::dry_run_eth_transact(tx, config)
2996				}
2997
2998				fn eth_estimate_gas(
2999					tx: $crate::evm::GenericTransaction,
3000					config: $crate::DryRunConfig<__ReviveMacroMoment>,
3001				) -> Result<$crate::U256, $crate::EthTransactError>  {
3002					use $crate::{
3003						codec::Encode, evm::runtime::EthExtra, frame_support::traits::Get,
3004						sp_runtime::traits::TransactionExtension,
3005						sp_runtime::traits::Block as BlockT
3006					};
3007					$crate::Pallet::<Self>::eth_estimate_gas(tx, config)
3008				}
3009
3010				fn call(
3011					origin: AccountId,
3012					dest: $crate::H160,
3013					value: Balance,
3014					weight_limit: Option<$crate::Weight>,
3015					storage_deposit_limit: Option<Balance>,
3016					input_data: Vec<u8>,
3017				) -> $crate::ContractResult<$crate::ExecReturnValue, Balance> {
3018					use $crate::frame_support::traits::Get;
3019					let blockweights: $crate::BlockWeights =
3020						<Self as $crate::frame_system::Config>::BlockWeights::get();
3021
3022					$crate::Pallet::<Self>::prepare_dry_run(&origin);
3023					$crate::Pallet::<Self>::bare_call(
3024						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin),
3025						dest,
3026						$crate::Pallet::<Self>::convert_native_to_evm(value),
3027						$crate::TransactionLimits::WeightAndDeposit {
3028							weight_limit: weight_limit.unwrap_or(blockweights.max_block),
3029							deposit_limit: storage_deposit_limit.unwrap_or(u128::MAX),
3030						},
3031						input_data,
3032						&$crate::ExecConfig::new_substrate_tx().with_dry_run(Default::default()),
3033					)
3034				}
3035
3036				fn instantiate(
3037					origin: AccountId,
3038					value: Balance,
3039					weight_limit: Option<$crate::Weight>,
3040					storage_deposit_limit: Option<Balance>,
3041					code: $crate::Code,
3042					data: Vec<u8>,
3043					salt: Option<[u8; 32]>,
3044				) -> $crate::ContractResult<$crate::InstantiateReturnValue, Balance> {
3045					use $crate::frame_support::traits::Get;
3046					let blockweights: $crate::BlockWeights =
3047						<Self as $crate::frame_system::Config>::BlockWeights::get();
3048
3049					$crate::Pallet::<Self>::prepare_dry_run(&origin);
3050					$crate::Pallet::<Self>::bare_instantiate(
3051						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin),
3052						$crate::Pallet::<Self>::convert_native_to_evm(value),
3053						$crate::TransactionLimits::WeightAndDeposit {
3054							weight_limit: weight_limit.unwrap_or(blockweights.max_block),
3055							deposit_limit: storage_deposit_limit.unwrap_or(u128::MAX),
3056						},
3057						code,
3058						data,
3059						salt,
3060						&$crate::ExecConfig::new_substrate_tx().with_dry_run(Default::default()),
3061					)
3062				}
3063
3064				fn upload_code(
3065					origin: AccountId,
3066					code: Vec<u8>,
3067					storage_deposit_limit: Option<Balance>,
3068				) -> $crate::CodeUploadResult<Balance> {
3069					let origin =
3070						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin);
3071					$crate::Pallet::<Self>::bare_upload_code(
3072						origin,
3073						code,
3074						storage_deposit_limit.unwrap_or(u128::MAX),
3075					)
3076				}
3077
3078				fn get_storage_var_key(
3079					address: $crate::H160,
3080					key: Vec<u8>,
3081				) -> $crate::GetStorageResult {
3082					$crate::Pallet::<Self>::get_storage_var_key(address, key)
3083				}
3084
3085				fn get_storage(address: $crate::H160, key: [u8; 32]) -> $crate::GetStorageResult {
3086					$crate::Pallet::<Self>::get_storage(address, key)
3087				}
3088
3089				fn trace_block(
3090					block: Block,
3091					tracer_type: $crate::evm::TracerType,
3092				) -> Vec<(u32, $crate::evm::Trace)> {
3093					use $crate::{sp_runtime::traits::Block, tracing::trace};
3094
3095					if matches!(tracer_type, $crate::evm::TracerType::ExecutionTracer(_)) &&
3096						!$crate::DebugSettings::is_execution_tracing_enabled::<Runtime>()
3097					{
3098						return Default::default()
3099					}
3100
3101					let mut traces = vec![];
3102					let (header, extrinsics) = block.deconstruct();
3103					<$Executive>::initialize_block(&header);
3104					for (index, ext) in extrinsics.into_iter().enumerate() {
3105						let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type.clone());
3106						let t = tracer.as_tracing();
3107						let _ = trace(t, || <$Executive>::apply_extrinsic(ext));
3108
3109						if let Some(tx_trace) = tracer.collect_trace() {
3110							traces.push((index as u32, tx_trace));
3111						}
3112					}
3113
3114					traces
3115				}
3116
3117				fn trace_tx(
3118					block: Block,
3119					tx_index: u32,
3120					tracer_type: $crate::evm::TracerType,
3121				) -> Option<$crate::evm::Trace> {
3122					use $crate::{sp_runtime::traits::Block, tracing::trace};
3123
3124					if matches!(tracer_type, $crate::evm::TracerType::ExecutionTracer(_)) &&
3125						!$crate::DebugSettings::is_execution_tracing_enabled::<Runtime>()
3126					{
3127						return None
3128					}
3129
3130					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type);
3131					let (header, extrinsics) = block.deconstruct();
3132
3133					<$Executive>::initialize_block(&header);
3134					for (index, ext) in extrinsics.into_iter().enumerate() {
3135						if index as u32 == tx_index {
3136							let t = tracer.as_tracing();
3137							let _ = trace(t, || <$Executive>::apply_extrinsic(ext));
3138							break;
3139						} else {
3140							let _ = <$Executive>::apply_extrinsic(ext);
3141						}
3142					}
3143
3144					tracer.collect_trace()
3145				}
3146
3147				fn trace_call(
3148					tx: $crate::evm::GenericTransaction,
3149					tracer_type: $crate::evm::TracerType,
3150				) -> Result<$crate::evm::Trace, $crate::EthTransactError> {
3151					use $crate::tracing::trace;
3152
3153					if matches!(tracer_type, $crate::evm::TracerType::ExecutionTracer(_)) &&
3154						!$crate::DebugSettings::is_execution_tracing_enabled::<Runtime>()
3155					{
3156						return Err($crate::EthTransactError::Message("Execution Tracing is disabled".into()))
3157					}
3158
3159					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type.clone());
3160					let t = tracer.as_tracing();
3161
3162					t.watch_address(&tx.from.unwrap_or_default());
3163					t.watch_address(&$crate::Pallet::<Self>::block_author());
3164					let result = trace(t, || Self::eth_transact(tx));
3165
3166					if let Some(trace) = tracer.collect_trace() {
3167						Ok(trace)
3168					} else if let Err(err) = result {
3169						Err(err)
3170					} else {
3171						Ok($crate::Pallet::<Self>::evm_tracer(tracer_type).empty_trace())
3172					}
3173				}
3174
3175				fn runtime_pallets_address() -> $crate::H160 {
3176					$crate::RUNTIME_PALLETS_ADDR
3177				}
3178
3179				fn code(address: $crate::H160) -> Vec<u8> {
3180					$crate::Pallet::<Self>::code(&address)
3181				}
3182
3183				fn account_id(address: $crate::H160) -> AccountId {
3184					use $crate::AddressMapper;
3185					<Self as $crate::Config>::AddressMapper::to_account_id(&address)
3186				}
3187
3188				fn new_balance_with_dust(balance: $crate::U256) -> Result<(Balance, u32), $crate::BalanceConversionError> {
3189					$crate::Pallet::<Self>::new_balance_with_dust(balance)
3190				}
3191			}
3192		}
3193	};
3194}