Skip to main content

pallet_revive/
lib.rs

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