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