referrerpolicy=no-referrer-when-downgrade

pallet_revive/
lib.rs

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