pallet_revive/
lib.rs

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