referrerpolicy=no-referrer-when-downgrade

pallet_revive/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18#![doc = include_str!("../README.md")]
19#![allow(rustdoc::private_intra_doc_links)]
20#![cfg_attr(not(feature = "std"), no_std)]
21#![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "1024")]
22
23extern crate alloc;
24
25mod address;
26mod benchmarking;
27mod call_builder;
28mod exec;
29mod gas;
30mod impl_fungibles;
31mod limits;
32mod primitives;
33mod storage;
34#[cfg(test)]
35mod tests;
36mod transient_storage;
37mod vm;
38
39pub mod evm;
40pub mod migrations;
41pub mod precompiles;
42pub mod test_utils;
43pub mod tracing;
44pub mod weights;
45
46use crate::{
47	evm::{
48		runtime::GAS_PRICE, CallTracer, GasEncoder, GenericTransaction, PrestateTracer, Trace,
49		Tracer, TracerType, TYPE_EIP1559,
50	},
51	exec::{AccountIdOf, ExecError, Executable, Stack as ExecStack},
52	gas::GasMeter,
53	storage::{meter::Meter as StorageMeter, AccountType, DeletionQueueManager},
54	tracing::if_tracing,
55	vm::{pvm::extract_code_and_data, CodeInfo, ContractBlob, RuntimeCosts},
56};
57use alloc::{boxed::Box, format, vec};
58use codec::{Codec, Decode, Encode};
59use environmental::*;
60use frame_support::{
61	dispatch::{
62		DispatchErrorWithPostInfo, DispatchResultWithPostInfo, GetDispatchInfo, Pays,
63		PostDispatchInfo, RawOrigin,
64	},
65	ensure,
66	pallet_prelude::DispatchClass,
67	traits::{
68		fungible::{Inspect, Mutate, MutateHold},
69		ConstU32, ConstU64, EnsureOrigin, Get, IsType, OriginTrait, Time,
70	},
71	weights::WeightMeter,
72	BoundedVec, RuntimeDebugNoBound,
73};
74use frame_system::{
75	ensure_signed,
76	pallet_prelude::{BlockNumberFor, OriginFor},
77	Pallet as System,
78};
79use pallet_transaction_payment::OnChargeTransaction;
80use scale_info::TypeInfo;
81use sp_runtime::{
82	traits::{Bounded, Convert, Dispatchable, Saturating},
83	AccountId32, DispatchError,
84};
85
86pub use crate::{
87	address::{
88		create1, create2, is_eth_derived, AccountId32Mapper, AddressMapper, TestAccountMapper,
89	},
90	exec::{Key, MomentOf, Origin},
91	pallet::{genesis, *},
92	storage::{AccountInfo, ContractInfo},
93};
94pub use codec;
95pub use frame_support::{self, dispatch::DispatchInfo, weights::Weight};
96pub use frame_system::{self, limits::BlockWeights};
97pub use pallet_transaction_payment;
98pub use primitives::*;
99pub use sp_core::{H160, H256, U256};
100pub use sp_runtime;
101pub use weights::WeightInfo;
102
103#[cfg(doc)]
104pub use crate::vm::pvm::SyscallDoc;
105
106pub type BalanceOf<T> =
107	<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
108type TrieId = BoundedVec<u8, ConstU32<128>>;
109type ImmutableData = BoundedVec<u8, ConstU32<{ limits::IMMUTABLE_BYTES }>>;
110pub(crate) type OnChargeTransactionBalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as OnChargeTransaction<T>>::Balance;
111
112/// Used as a sentinel value when reading and writing contract memory.
113///
114/// It is usually used to signal `None` to a contract when only a primitive is allowed
115/// and we don't want to go through encoding a full Rust type. Using `u32::Max` is a safe
116/// sentinel because contracts are never allowed to use such a large amount of resources
117/// that this value makes sense for a memory location or length.
118const SENTINEL: u32 = u32::MAX;
119
120/// The target that is used for the log output emitted by this crate.
121///
122/// Hence you can use this target to selectively increase the log level for this crate.
123///
124/// Example: `RUST_LOG=runtime::revive=debug my_code --dev`
125const LOG_TARGET: &str = "runtime::revive";
126
127#[frame_support::pallet]
128pub mod pallet {
129	use super::*;
130	use frame_support::{pallet_prelude::*, traits::FindAuthor};
131	use frame_system::pallet_prelude::*;
132	use sp_core::U256;
133	use sp_runtime::Perbill;
134
135	/// The in-code storage version.
136	pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
137
138	#[pallet::pallet]
139	#[pallet::storage_version(STORAGE_VERSION)]
140	pub struct Pallet<T>(_);
141
142	#[pallet::config(with_default)]
143	pub trait Config: frame_system::Config {
144		/// The time implementation used to supply timestamps to contracts through `seal_now`.
145		type Time: Time;
146
147		/// The fungible in which fees are paid and contract balances are held.
148		#[pallet::no_default]
149		type Currency: Inspect<Self::AccountId>
150			+ Mutate<Self::AccountId>
151			+ MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>;
152
153		/// The overarching event type.
154		#[pallet::no_default_bounds]
155		#[allow(deprecated)]
156		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
157
158		/// The overarching call type.
159		#[pallet::no_default_bounds]
160		type RuntimeCall: Parameter
161			+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin, PostInfo = PostDispatchInfo>
162			+ GetDispatchInfo;
163
164		/// Overarching hold reason.
165		#[pallet::no_default_bounds]
166		type RuntimeHoldReason: From<HoldReason>;
167
168		/// Used to answer contracts' queries regarding the current weight price. This is **not**
169		/// used to calculate the actual fee and is only for informational purposes.
170		#[pallet::no_default_bounds]
171		type WeightPrice: Convert<Weight, BalanceOf<Self>>;
172
173		/// Describes the weights of the dispatchables of this module and is also used to
174		/// construct a default cost schedule.
175		type WeightInfo: WeightInfo;
176
177		/// Type that allows the runtime authors to add new host functions for a contract to call.
178		///
179		/// Pass in a tuple of types that implement [`precompiles::Precompile`].
180		#[pallet::no_default_bounds]
181		#[allow(private_bounds)]
182		type Precompiles: precompiles::Precompiles<Self>;
183
184		/// Find the author of the current block.
185		type FindAuthor: FindAuthor<Self::AccountId>;
186
187		/// The amount of balance a caller has to pay for each byte of storage.
188		///
189		/// # Note
190		///
191		/// It is safe to change this value on a live chain as all refunds are pro rata.
192		#[pallet::constant]
193		#[pallet::no_default_bounds]
194		type DepositPerByte: Get<BalanceOf<Self>>;
195
196		/// The amount of balance a caller has to pay for each storage item.
197		///
198		/// # Note
199		///
200		/// It is safe to change this value on a live chain as all refunds are pro rata.
201		#[pallet::constant]
202		#[pallet::no_default_bounds]
203		type DepositPerItem: Get<BalanceOf<Self>>;
204
205		/// The percentage of the storage deposit that should be held for using a code hash.
206		/// Instantiating a contract, protects the code from being removed. In order to prevent
207		/// abuse these actions are protected with a percentage of the code deposit.
208		#[pallet::constant]
209		type CodeHashLockupDepositPercent: Get<Perbill>;
210
211		/// Use either valid type is [`address::AccountId32Mapper`] or [`address::H160Mapper`].
212		#[pallet::no_default]
213		type AddressMapper: AddressMapper<Self>;
214
215		/// Make contract callable functions marked as `#[unstable]` available.
216		///
217		/// Contracts that use `#[unstable]` functions won't be able to be uploaded unless
218		/// this is set to `true`. This is only meant for testnets and dev nodes in order to
219		/// experiment with new features.
220		///
221		/// # Warning
222		///
223		/// Do **not** set to `true` on productions chains.
224		#[pallet::constant]
225		type UnsafeUnstableInterface: Get<bool>;
226
227		/// Allow EVM bytecode to be uploaded and instantiated.
228		#[pallet::constant]
229		type AllowEVMBytecode: Get<bool>;
230
231		/// Origin allowed to upload code.
232		///
233		/// By default, it is safe to set this to `EnsureSigned`, allowing anyone to upload contract
234		/// code.
235		#[pallet::no_default_bounds]
236		type UploadOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
237
238		/// Origin allowed to instantiate code.
239		///
240		/// # Note
241		///
242		/// This is not enforced when a contract instantiates another contract. The
243		/// [`Self::UploadOrigin`] should make sure that no code is deployed that does unwanted
244		/// instantiations.
245		///
246		/// By default, it is safe to set this to `EnsureSigned`, allowing anyone to instantiate
247		/// contract code.
248		#[pallet::no_default_bounds]
249		type InstantiateOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
250
251		/// The amount of memory in bytes that parachain nodes a lot to the runtime.
252		///
253		/// This is used in [`Pallet::integrity_test`] to make sure that the runtime has enough
254		/// memory to support this pallet if set to the correct value.
255		type RuntimeMemory: Get<u32>;
256
257		/// The amount of memory in bytes that relay chain validators a lot to the PoV.
258		///
259		/// This is used in [`Pallet::integrity_test`] to make sure that the runtime has enough
260		/// memory to support this pallet if set to the correct value.
261		///
262		/// This value is usually higher than [`Self::RuntimeMemory`] to account for the fact
263		/// that validators have to hold all storage items in PvF memory.
264		type PVFMemory: Get<u32>;
265
266		/// The [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID.
267		///
268		/// This is a unique identifier assigned to each blockchain network,
269		/// preventing replay attacks.
270		#[pallet::constant]
271		type ChainId: Get<u64>;
272
273		/// The ratio between the decimal representation of the native token and the ETH token.
274		#[pallet::constant]
275		type NativeToEthRatio: Get<u32>;
276
277		/// Encode and decode Ethereum gas values.
278		/// Only valid value is `()`. See [`GasEncoder`].
279		#[pallet::no_default_bounds]
280		type EthGasEncoder: GasEncoder<BalanceOf<Self>>;
281	}
282
283	/// Container for different types that implement [`DefaultConfig`]` of this pallet.
284	pub mod config_preludes {
285		use super::*;
286		use frame_support::{
287			derive_impl,
288			traits::{ConstBool, ConstU32},
289		};
290		use frame_system::EnsureSigned;
291		use sp_core::parameter_types;
292
293		type Balance = u64;
294		const UNITS: Balance = 10_000_000_000;
295		const CENTS: Balance = UNITS / 100;
296
297		pub const fn deposit(items: u32, bytes: u32) -> Balance {
298			items as Balance * 1 * CENTS + (bytes as Balance) * 1 * CENTS
299		}
300
301		parameter_types! {
302			pub const DepositPerItem: Balance = deposit(1, 0);
303			pub const DepositPerByte: Balance = deposit(0, 1);
304			pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
305		}
306
307		/// A type providing default configurations for this pallet in testing environment.
308		pub struct TestDefaultConfig;
309
310		impl Time for TestDefaultConfig {
311			type Moment = u64;
312			fn now() -> Self::Moment {
313				0u64
314			}
315		}
316
317		impl<T: From<u64>> Convert<Weight, T> for TestDefaultConfig {
318			fn convert(w: Weight) -> T {
319				w.ref_time().into()
320			}
321		}
322
323		#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
324		impl frame_system::DefaultConfig for TestDefaultConfig {}
325
326		#[frame_support::register_default_impl(TestDefaultConfig)]
327		impl DefaultConfig for TestDefaultConfig {
328			#[inject_runtime_type]
329			type RuntimeEvent = ();
330
331			#[inject_runtime_type]
332			type RuntimeHoldReason = ();
333
334			#[inject_runtime_type]
335			type RuntimeCall = ();
336			type Precompiles = ();
337			type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
338			type DepositPerByte = DepositPerByte;
339			type DepositPerItem = DepositPerItem;
340			type Time = Self;
341			type UnsafeUnstableInterface = ConstBool<true>;
342			type AllowEVMBytecode = ConstBool<true>;
343			type UploadOrigin = EnsureSigned<Self::AccountId>;
344			type InstantiateOrigin = EnsureSigned<Self::AccountId>;
345			type WeightInfo = ();
346			type WeightPrice = Self;
347			type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>;
348			type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>;
349			type ChainId = ConstU64<42>;
350			type NativeToEthRatio = ConstU32<1_000_000>;
351			type EthGasEncoder = ();
352			type FindAuthor = ();
353		}
354	}
355
356	#[pallet::event]
357	pub enum Event<T: Config> {
358		/// A custom event emitted by the contract.
359		ContractEmitted {
360			/// The contract that emitted the event.
361			contract: H160,
362			/// Data supplied by the contract. Metadata generated during contract compilation
363			/// is needed to decode it.
364			data: Vec<u8>,
365			/// A list of topics used to index the event.
366			/// Number of topics is capped by [`limits::NUM_EVENT_TOPICS`].
367			topics: Vec<H256>,
368		},
369
370		/// Contract deployed by deployer at the specified address.
371		Instantiated { deployer: H160, contract: H160 },
372	}
373
374	#[pallet::error]
375	#[repr(u8)]
376	pub enum Error<T> {
377		/// Invalid schedule supplied, e.g. with zero weight of a basic operation.
378		InvalidSchedule = 0x01,
379		/// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`.
380		InvalidCallFlags = 0x02,
381		/// The executed contract exhausted its gas limit.
382		OutOfGas = 0x03,
383		/// Performing the requested transfer failed. Probably because there isn't enough
384		/// free balance in the sender's account.
385		TransferFailed = 0x04,
386		/// Performing a call was denied because the calling depth reached the limit
387		/// of what is specified in the schedule.
388		MaxCallDepthReached = 0x05,
389		/// No contract was found at the specified address.
390		ContractNotFound = 0x06,
391		/// No code could be found at the supplied code hash.
392		CodeNotFound = 0x07,
393		/// No code info could be found at the supplied code hash.
394		CodeInfoNotFound = 0x08,
395		/// A buffer outside of sandbox memory was passed to a contract API function.
396		OutOfBounds = 0x09,
397		/// Input passed to a contract API function failed to decode as expected type.
398		DecodingFailed = 0x0A,
399		/// Contract trapped during execution.
400		ContractTrapped = 0x0B,
401		/// Event body or storage item exceeds [`limits::PAYLOAD_BYTES`].
402		ValueTooLarge = 0x0C,
403		/// Termination of a contract is not allowed while the contract is already
404		/// on the call stack. Can be triggered by `seal_terminate`.
405		TerminatedWhileReentrant = 0x0D,
406		/// `seal_call` forwarded this contracts input. It therefore is no longer available.
407		InputForwarded = 0x0E,
408		/// The amount of topics passed to `seal_deposit_events` exceeds the limit.
409		TooManyTopics = 0x0F,
410		/// A contract with the same AccountId already exists.
411		DuplicateContract = 0x12,
412		/// A contract self destructed in its constructor.
413		///
414		/// This can be triggered by a call to `seal_terminate`.
415		TerminatedInConstructor = 0x13,
416		/// A call tried to invoke a contract that is flagged as non-reentrant.
417		ReentranceDenied = 0x14,
418		/// A contract called into the runtime which then called back into this pallet.
419		ReenteredPallet = 0x15,
420		/// A contract attempted to invoke a state modifying API while being in read-only mode.
421		StateChangeDenied = 0x16,
422		/// Origin doesn't have enough balance to pay the required storage deposits.
423		StorageDepositNotEnoughFunds = 0x17,
424		/// More storage was created than allowed by the storage deposit limit.
425		StorageDepositLimitExhausted = 0x18,
426		/// Code removal was denied because the code is still in use by at least one contract.
427		CodeInUse = 0x19,
428		/// The contract ran to completion but decided to revert its storage changes.
429		/// Please note that this error is only returned from extrinsics. When called directly
430		/// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags
431		/// to determine whether a reversion has taken place.
432		ContractReverted = 0x1A,
433		/// The contract failed to compile or is missing the correct entry points.
434		///
435		/// A more detailed error can be found on the node console if debug messages are enabled
436		/// by supplying `-lruntime::revive=debug`.
437		CodeRejected = 0x1B,
438		/// The code blob supplied is larger than [`limits::code::BLOB_BYTES`].
439		BlobTooLarge = 0x1C,
440		/// The contract declares too much memory (ro + rw + stack).
441		StaticMemoryTooLarge = 0x1D,
442		/// The program contains a basic block that is larger than allowed.
443		BasicBlockTooLarge = 0x1E,
444		/// The program contains an invalid instruction.
445		InvalidInstruction = 0x1F,
446		/// The contract has reached its maximum number of delegate dependencies.
447		MaxDelegateDependenciesReached = 0x20,
448		/// The dependency was not found in the contract's delegate dependencies.
449		DelegateDependencyNotFound = 0x21,
450		/// The contract already depends on the given delegate dependency.
451		DelegateDependencyAlreadyExists = 0x22,
452		/// Can not add a delegate dependency to the code hash of the contract itself.
453		CannotAddSelfAsDelegateDependency = 0x23,
454		/// Can not add more data to transient storage.
455		OutOfTransientStorage = 0x24,
456		/// The contract tried to call a syscall which does not exist (at its current api level).
457		InvalidSyscall = 0x25,
458		/// Invalid storage flags were passed to one of the storage syscalls.
459		InvalidStorageFlags = 0x26,
460		/// PolkaVM failed during code execution. Probably due to a malformed program.
461		ExecutionFailed = 0x27,
462		/// Failed to convert a U256 to a Balance.
463		BalanceConversionFailed = 0x28,
464		/// Immutable data can only be set during deploys and only be read during calls.
465		/// Additionally, it is only valid to set the data once and it must not be empty.
466		InvalidImmutableAccess = 0x2A,
467		/// An `AccountID32` account tried to interact with the pallet without having a mapping.
468		///
469		/// Call [`Pallet::map_account`] in order to create a mapping for the account.
470		AccountUnmapped = 0x2B,
471		/// Tried to map an account that is already mapped.
472		AccountAlreadyMapped = 0x2C,
473		/// The transaction used to dry-run a contract is invalid.
474		InvalidGenericTransaction = 0x2D,
475		/// The refcount of a code either over or underflowed.
476		RefcountOverOrUnderflow = 0x2E,
477		/// Unsupported precompile address.
478		UnsupportedPrecompileAddress = 0x2F,
479		/// The calldata exceeds [`limits::CALLDATA_BYTES`].
480		CallDataTooLarge = 0x30,
481		/// The return data exceeds [`limits::CALLDATA_BYTES`].
482		ReturnDataTooLarge = 0x31,
483	}
484
485	/// A reason for the pallet revive placing a hold on funds.
486	#[pallet::composite_enum]
487	pub enum HoldReason {
488		/// The Pallet has reserved it for storing code on-chain.
489		CodeUploadDepositReserve,
490		/// The Pallet has reserved it for storage deposit.
491		StorageDepositReserve,
492		/// Deposit for creating an address mapping in [`OriginalAccount`].
493		AddressMapping,
494	}
495
496	/// A mapping from a contract's code hash to its code.
497	/// The code's size is bounded by [`crate::limits::BLOB_BYTES`] for PVM and
498	/// [`revm::primitives::eip170::MAX_CODE_SIZE`] for EVM bytecode.
499	#[pallet::storage]
500	#[pallet::unbounded]
501	pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, H256, Vec<u8>>;
502
503	/// A mapping from a contract's code hash to its code info.
504	#[pallet::storage]
505	pub(crate) type CodeInfoOf<T: Config> = StorageMap<_, Identity, H256, CodeInfo<T>>;
506
507	/// The data associated to a contract or externally owned account.
508	#[pallet::storage]
509	pub(crate) type AccountInfoOf<T: Config> = StorageMap<_, Identity, H160, AccountInfo<T>>;
510
511	/// The immutable data associated with a given account.
512	#[pallet::storage]
513	pub(crate) type ImmutableDataOf<T: Config> = StorageMap<_, Identity, H160, ImmutableData>;
514
515	/// Evicted contracts that await child trie deletion.
516	///
517	/// Child trie deletion is a heavy operation depending on the amount of storage items
518	/// stored in said trie. Therefore this operation is performed lazily in `on_idle`.
519	#[pallet::storage]
520	pub(crate) type DeletionQueue<T: Config> = StorageMap<_, Twox64Concat, u32, TrieId>;
521
522	/// A pair of monotonic counters used to track the latest contract marked for deletion
523	/// and the latest deleted contract in queue.
524	#[pallet::storage]
525	pub(crate) type DeletionQueueCounter<T: Config> =
526		StorageValue<_, DeletionQueueManager<T>, ValueQuery>;
527
528	/// Map a Ethereum address to its original `AccountId32`.
529	///
530	/// When deriving a `H160` from an `AccountId32` we use a hash function. In order to
531	/// reconstruct the original account we need to store the reverse mapping here.
532	/// Register your `AccountId32` using [`Pallet::map_account`] in order to
533	/// use it with this pallet.
534	#[pallet::storage]
535	pub(crate) type OriginalAccount<T: Config> = StorageMap<_, Identity, H160, AccountId32>;
536
537	pub mod genesis {
538		use super::*;
539		use crate::evm::Bytes32;
540
541		/// Genesis configuration for contract-specific data.
542		#[derive(Clone, PartialEq, Debug, Default, serde::Serialize, serde::Deserialize)]
543		pub struct ContractData {
544			/// Contract code.
545			pub code: Vec<u8>,
546			/// Initial storage entries as 32-byte key/value pairs.
547			pub storage: alloc::collections::BTreeMap<Bytes32, Bytes32>,
548		}
549
550		/// Genesis configuration for a contract account.
551		#[derive(PartialEq, Default, Debug, Clone, serde::Serialize, serde::Deserialize)]
552		pub struct Account<T: Config> {
553			/// Contract address.
554			pub address: H160,
555			/// Contract balance.
556			#[serde(default)]
557			pub balance: U256,
558			/// Account nonce
559			#[serde(default)]
560			pub nonce: T::Nonce,
561			/// Contract-specific data (code and storage). None for EOAs.
562			#[serde(flatten, skip_serializing_if = "Option::is_none")]
563			pub contract_data: Option<ContractData>,
564		}
565	}
566
567	#[pallet::genesis_config]
568	#[derive(Debug, PartialEq, frame_support::DefaultNoBound)]
569	pub struct GenesisConfig<T: Config> {
570		/// List of native Substrate accounts (typically `AccountId32`) to be mapped at genesis
571		/// block, enabling them to interact with smart contracts.
572		#[serde(default, skip_serializing_if = "Vec::is_empty")]
573		pub mapped_accounts: Vec<T::AccountId>,
574
575		/// Account entries (both EOAs and contracts)
576		#[serde(default, skip_serializing_if = "Vec::is_empty")]
577		pub accounts: Vec<genesis::Account<T>>,
578	}
579
580	#[pallet::genesis_build]
581	impl<T: Config> BuildGenesisConfig for GenesisConfig<T>
582	where
583		BalanceOf<T>: Into<U256> + TryFrom<U256> + Bounded,
584		MomentOf<T>: Into<U256>,
585		T::Hash: frame_support::traits::IsType<H256>,
586	{
587		fn build(&self) {
588			use crate::{exec::Key, vm::ContractBlob};
589			use frame_support::traits::fungible::Mutate;
590
591			if !System::<T>::account_exists(&Pallet::<T>::account_id()) {
592				let _ = T::Currency::mint_into(
593					&Pallet::<T>::account_id(),
594					T::Currency::minimum_balance(),
595				);
596			}
597
598			for id in &self.mapped_accounts {
599				if let Err(err) = T::AddressMapper::map_no_deposit(id) {
600					log::error!(target: LOG_TARGET, "Failed to map account {id:?}: {err:?}");
601				}
602			}
603
604			let owner = Pallet::<T>::account_id();
605
606			for genesis::Account { address, balance, nonce, contract_data } in &self.accounts {
607				let account_id = T::AddressMapper::to_account_id(address);
608
609				frame_system::Account::<T>::mutate(&account_id, |info| {
610					info.nonce = (*nonce).into();
611				});
612
613				match contract_data {
614					None => {
615						AccountInfoOf::<T>::insert(
616							address,
617							AccountInfo { account_type: AccountType::EOA, dust: 0 },
618						);
619					},
620					Some(genesis::ContractData { code, storage }) => {
621						let blob = if code.starts_with(&polkavm_common::program::BLOB_MAGIC) {
622							ContractBlob::<T>::from_pvm_code(   code.clone(), owner.clone()).inspect_err(|err| {
623								log::error!(target: LOG_TARGET, "Failed to create PVM ContractBlob for {address:?}: {err:?}");
624							})
625						} else {
626							ContractBlob::<T>::from_evm_runtime_code(code.clone(), account_id).inspect_err(|err| {
627								log::error!(target: LOG_TARGET, "Failed to create EVM ContractBlob for {address:?}: {err:?}");
628							})
629						};
630
631						let Ok(blob) = blob else {
632							continue;
633						};
634
635						let code_hash = *blob.code_hash();
636						let Ok(info) = <ContractInfo<T>>::new(&address, 0u32.into(), code_hash)
637							.inspect_err(|err| {
638								log::error!(target: LOG_TARGET, "Failed to create ContractInfo for {address:?}: {err:?}");
639							})
640						else {
641							continue;
642						};
643
644						AccountInfoOf::<T>::insert(
645							address,
646							AccountInfo { account_type: info.clone().into(), dust: 0 },
647						);
648
649						<PristineCode<T>>::insert(blob.code_hash(), code);
650						<CodeInfoOf<T>>::insert(blob.code_hash(), blob.code_info().clone());
651						for (k, v) in storage {
652							let _ = info.write(&Key::from_fixed(k.0), Some(v.0.to_vec()), None, false).inspect_err(|err| {
653								log::error!(target: LOG_TARGET, "Failed to write genesis storage for {address:?} at key {k:?}: {err:?}");
654							});
655						}
656					},
657				}
658
659				let _ = Pallet::<T>::set_evm_balance(address, *balance).inspect_err(|err| {
660					log::error!(target: LOG_TARGET, "Failed to set EVM balance for {address:?}: {err:?}");
661				});
662			}
663		}
664	}
665
666	#[pallet::hooks]
667	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
668		fn on_initialize(_block: BlockNumberFor<T>) -> Weight {
669			// Warm up the pallet account.
670			System::<T>::account_exists(&Pallet::<T>::account_id());
671			return T::DbWeight::get().reads(1)
672		}
673		fn on_idle(_block: BlockNumberFor<T>, limit: Weight) -> Weight {
674			let mut meter = WeightMeter::with_limit(limit);
675			ContractInfo::<T>::process_deletion_queue_batch(&mut meter);
676			meter.consumed()
677		}
678
679		fn integrity_test() {
680			assert!(T::ChainId::get() > 0, "ChainId must be greater than 0");
681
682			// The memory available in the block building runtime
683			let max_runtime_mem: u32 = T::RuntimeMemory::get();
684
685			// We only allow 50% of the runtime memory to be utilized by the contracts call
686			// stack, keeping the rest for other facilities, such as PoV, etc.
687			const TOTAL_MEMORY_DEVIDER: u32 = 2;
688
689			// Check that the configured memory limits fit into runtime memory.
690			//
691			// Dynamic allocations are not available, yet. Hence they are not taken into
692			// consideration here.
693			let memory_left = i64::from(max_runtime_mem)
694				.saturating_div(TOTAL_MEMORY_DEVIDER.into())
695				.saturating_sub(limits::MEMORY_REQUIRED.into());
696
697			log::debug!(target: LOG_TARGET, "Integrity check: memory_left={} KB", memory_left / 1024);
698
699			assert!(
700				memory_left >= 0,
701				"Runtime does not have enough memory for current limits. Additional runtime memory required: {} KB",
702				memory_left.saturating_mul(TOTAL_MEMORY_DEVIDER.into()).abs() / 1024
703			);
704
705			// Validators are configured to be able to use more memory than block builders. This is
706			// because in addition to `max_runtime_mem` they need to hold additional data in
707			// memory: PoV in multiple copies (1x encoded + 2x decoded) and all storage which
708			// includes emitted events. The assumption is that storage/events size
709			// can be a maximum of half of the validator runtime memory - max_runtime_mem.
710			let max_block_ref_time = T::BlockWeights::get()
711				.get(DispatchClass::Normal)
712				.max_total
713				.unwrap_or_else(|| T::BlockWeights::get().max_block)
714				.ref_time();
715			let max_payload_size = limits::PAYLOAD_BYTES;
716			let max_key_size =
717				Key::try_from_var(alloc::vec![0u8; limits::STORAGE_KEY_BYTES as usize])
718					.expect("Key of maximal size shall be created")
719					.hash()
720					.len() as u32;
721
722			let max_immutable_key_size = T::AccountId::max_encoded_len() as u32;
723			let max_immutable_size: u32 = ((max_block_ref_time /
724				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetImmutableData(
725					limits::IMMUTABLE_BYTES,
726				))
727				.ref_time()))
728			.saturating_mul(limits::IMMUTABLE_BYTES.saturating_add(max_immutable_key_size) as u64))
729			.try_into()
730			.expect("Immutable data size too big");
731
732			// We can use storage to store items using the available block ref_time with the
733			// `set_storage` host function.
734			let max_storage_size: u32 = ((max_block_ref_time /
735				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetStorage {
736					new_bytes: max_payload_size,
737					old_bytes: 0,
738				})
739				.ref_time()))
740			.saturating_mul(max_payload_size.saturating_add(max_key_size) as u64))
741			.saturating_add(max_immutable_size.into())
742			.try_into()
743			.expect("Storage size too big");
744
745			let max_pvf_mem: u32 = T::PVFMemory::get();
746			let storage_size_limit = max_pvf_mem.saturating_sub(max_runtime_mem) / 2;
747
748			assert!(
749				max_storage_size < storage_size_limit,
750				"Maximal storage size {} exceeds the storage limit {}",
751				max_storage_size,
752				storage_size_limit
753			);
754
755			// We can use storage to store events using the available block ref_time with the
756			// `deposit_event` host function. The overhead of stored events, which is around 100B,
757			// is not taken into account to simplify calculations, as it does not change much.
758			let max_events_size: u32 = ((max_block_ref_time /
759				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::DepositEvent {
760					num_topic: 0,
761					len: max_payload_size,
762				})
763				.saturating_add(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::HostFn))
764				.ref_time()))
765			.saturating_mul(max_payload_size as u64))
766			.try_into()
767			.expect("Events size too big");
768
769			assert!(
770				max_events_size < storage_size_limit,
771				"Maximal events size {} exceeds the events limit {}",
772				max_events_size,
773				storage_size_limit
774			);
775		}
776	}
777
778	#[pallet::call]
779	impl<T: Config> Pallet<T>
780	where
781		BalanceOf<T>: Into<U256> + TryFrom<U256>,
782		MomentOf<T>: Into<U256>,
783		T::Hash: frame_support::traits::IsType<H256>,
784	{
785		/// A raw EVM transaction, typically dispatched by an Ethereum JSON-RPC server.
786		///
787		/// # Parameters
788		///
789		/// * `payload`: The encoded [`crate::evm::TransactionSigned`].
790		/// * `gas_limit`: The gas limit enforced during contract execution.
791		/// * `storage_deposit_limit`: The maximum balance that can be charged to the caller for
792		///   storage usage.
793		///
794		/// # Note
795		///
796		/// This call cannot be dispatched directly; attempting to do so will result in a failed
797		/// transaction. It serves as a wrapper for an Ethereum transaction. When submitted, the
798		/// runtime converts it into a [`sp_runtime::generic::CheckedExtrinsic`] by recovering the
799		/// signer and validating the transaction.
800		#[allow(unused_variables)]
801		#[pallet::call_index(0)]
802		#[pallet::weight(Weight::MAX)]
803		pub fn eth_transact(origin: OriginFor<T>, payload: Vec<u8>) -> DispatchResultWithPostInfo {
804			Err(frame_system::Error::CallFiltered::<T>.into())
805		}
806
807		/// Makes a call to an account, optionally transferring some balance.
808		///
809		/// # Parameters
810		///
811		/// * `dest`: Address of the contract to call.
812		/// * `value`: The balance to transfer from the `origin` to `dest`.
813		/// * `gas_limit`: The gas limit enforced when executing the constructor.
814		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged from the
815		///   caller to pay for the storage consumed.
816		/// * `data`: The input data to pass to the contract.
817		///
818		/// * If the account is a smart-contract account, the associated code will be
819		/// executed and any value will be transferred.
820		/// * If the account is a regular account, any value will be transferred.
821		/// * If no account exists and the call value is not less than `existential_deposit`,
822		/// a regular account will be created and any value will be transferred.
823		#[pallet::call_index(1)]
824		#[pallet::weight(T::WeightInfo::call().saturating_add(*gas_limit))]
825		pub fn call(
826			origin: OriginFor<T>,
827			dest: H160,
828			#[pallet::compact] value: BalanceOf<T>,
829			gas_limit: Weight,
830			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
831			data: Vec<u8>,
832		) -> DispatchResultWithPostInfo {
833			let mut output = Self::bare_call(
834				origin,
835				dest,
836				Pallet::<T>::convert_native_to_evm(value),
837				gas_limit,
838				DepositLimit::Balance(storage_deposit_limit),
839				data,
840			);
841
842			if let Ok(return_value) = &output.result {
843				if return_value.did_revert() {
844					output.result = Err(<Error<T>>::ContractReverted.into());
845				}
846			}
847			dispatch_result(output.result, output.gas_consumed, T::WeightInfo::call())
848		}
849
850		/// Instantiates a contract from a previously deployed vm binary.
851		///
852		/// This function is identical to [`Self::instantiate_with_code`] but without the
853		/// code deployment step. Instead, the `code_hash` of an on-chain deployed vm binary
854		/// must be supplied.
855		#[pallet::call_index(2)]
856		#[pallet::weight(
857			T::WeightInfo::instantiate(data.len() as u32).saturating_add(*gas_limit)
858		)]
859		pub fn instantiate(
860			origin: OriginFor<T>,
861			#[pallet::compact] value: BalanceOf<T>,
862			gas_limit: Weight,
863			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
864			code_hash: sp_core::H256,
865			data: Vec<u8>,
866			salt: Option<[u8; 32]>,
867		) -> DispatchResultWithPostInfo {
868			let data_len = data.len() as u32;
869			let mut output = Self::bare_instantiate(
870				origin,
871				Pallet::<T>::convert_native_to_evm(value),
872				gas_limit,
873				DepositLimit::Balance(storage_deposit_limit),
874				Code::Existing(code_hash),
875				data,
876				salt,
877				BumpNonce::Yes,
878			);
879			if let Ok(retval) = &output.result {
880				if retval.result.did_revert() {
881					output.result = Err(<Error<T>>::ContractReverted.into());
882				}
883			}
884			dispatch_result(
885				output.result.map(|result| result.result),
886				output.gas_consumed,
887				T::WeightInfo::instantiate(data_len),
888			)
889		}
890
891		/// Instantiates a new contract from the supplied `code` optionally transferring
892		/// some balance.
893		///
894		/// This dispatchable has the same effect as calling [`Self::upload_code`] +
895		/// [`Self::instantiate`]. Bundling them together provides efficiency gains. Please
896		/// also check the documentation of [`Self::upload_code`].
897		///
898		/// # Parameters
899		///
900		/// * `value`: The balance to transfer from the `origin` to the newly created contract.
901		/// * `gas_limit`: The gas limit enforced when executing the constructor.
902		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved
903		///   from the caller to pay for the storage consumed.
904		/// * `code`: The contract code to deploy in raw bytes.
905		/// * `data`: The input data to pass to the contract constructor.
906		/// * `salt`: Used for the address derivation. If `Some` is supplied then `CREATE2`
907		/// 	semantics are used. If `None` then `CRATE1` is used.
908		///
909		///
910		/// Instantiation is executed as follows:
911		///
912		/// - The supplied `code` is deployed, and a `code_hash` is created for that code.
913		/// - If the `code_hash` already exists on the chain the underlying `code` will be shared.
914		/// - The destination address is computed based on the sender, code_hash and the salt.
915		/// - The smart-contract account is created at the computed address.
916		/// - The `value` is transferred to the new account.
917		/// - The `deploy` function is executed in the context of the newly-created account.
918		#[pallet::call_index(3)]
919		#[pallet::weight(
920			T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32)
921			.saturating_add(*gas_limit)
922		)]
923		pub fn instantiate_with_code(
924			origin: OriginFor<T>,
925			#[pallet::compact] value: BalanceOf<T>,
926			gas_limit: Weight,
927			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
928			code: Vec<u8>,
929			data: Vec<u8>,
930			salt: Option<[u8; 32]>,
931		) -> DispatchResultWithPostInfo {
932			let code_len = code.len() as u32;
933			let data_len = data.len() as u32;
934			let mut output = Self::bare_instantiate(
935				origin,
936				Pallet::<T>::convert_native_to_evm(value),
937				gas_limit,
938				DepositLimit::Balance(storage_deposit_limit),
939				Code::Upload(code),
940				data,
941				salt,
942				BumpNonce::Yes,
943			);
944			if let Ok(retval) = &output.result {
945				if retval.result.did_revert() {
946					output.result = Err(<Error<T>>::ContractReverted.into());
947				}
948			}
949			dispatch_result(
950				output.result.map(|result| result.result),
951				output.gas_consumed,
952				T::WeightInfo::instantiate_with_code(code_len, data_len),
953			)
954		}
955
956		/// Same as [`Self::instantiate_with_code`], but intended to be dispatched **only**
957		/// by an EVM transaction through the EVM compatibility layer.
958		///
959		/// Calling this dispatchable ensures that the origin's nonce is bumped only once,
960		/// via the `CheckNonce` transaction extension. In contrast, [`Self::instantiate_with_code`]
961		/// also bumps the nonce after contract instantiation, since it may be invoked multiple
962		/// times within a batch call transaction.
963		#[pallet::call_index(10)]
964		#[pallet::weight(
965			T::WeightInfo::eth_instantiate_with_code(code.len() as u32, data.len() as u32, Pallet::<T>::has_dust(*value).into())
966			.saturating_add(*gas_limit)
967		)]
968		pub fn eth_instantiate_with_code(
969			origin: OriginFor<T>,
970			value: U256,
971			gas_limit: Weight,
972			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
973			code: Vec<u8>,
974			data: Vec<u8>,
975		) -> DispatchResultWithPostInfo {
976			let code_len = code.len() as u32;
977			let data_len = data.len() as u32;
978			let mut output = Self::bare_instantiate(
979				origin,
980				value,
981				gas_limit,
982				DepositLimit::Balance(storage_deposit_limit),
983				Code::Upload(code),
984				data,
985				None,
986				BumpNonce::No,
987			);
988
989			if let Ok(retval) = &output.result {
990				if retval.result.did_revert() {
991					output.result = Err(<Error<T>>::ContractReverted.into());
992				}
993			}
994			dispatch_result(
995				output.result.map(|result| result.result),
996				output.gas_consumed,
997				T::WeightInfo::eth_instantiate_with_code(
998					code_len,
999					data_len,
1000					Pallet::<T>::has_dust(value).into(),
1001				),
1002			)
1003		}
1004
1005		/// Same as [`Self::call`], but intended to be dispatched **only**
1006		/// by an EVM transaction through the EVM compatibility layer.
1007		#[pallet::call_index(11)]
1008		#[pallet::weight(T::WeightInfo::eth_call(Pallet::<T>::has_dust(*value).into()).saturating_add(*gas_limit))]
1009		pub fn eth_call(
1010			origin: OriginFor<T>,
1011			dest: H160,
1012			value: U256,
1013			gas_limit: Weight,
1014			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
1015			data: Vec<u8>,
1016		) -> DispatchResultWithPostInfo {
1017			let mut output = Self::bare_call(
1018				origin,
1019				dest,
1020				value,
1021				gas_limit,
1022				DepositLimit::Balance(storage_deposit_limit),
1023				data,
1024			);
1025
1026			if let Ok(return_value) = &output.result {
1027				if return_value.did_revert() {
1028					output.result = Err(<Error<T>>::ContractReverted.into());
1029				}
1030			}
1031			dispatch_result(
1032				output.result,
1033				output.gas_consumed,
1034				T::WeightInfo::eth_call(Pallet::<T>::has_dust(value).into()),
1035			)
1036		}
1037
1038		/// Upload new `code` without instantiating a contract from it.
1039		///
1040		/// If the code does not already exist a deposit is reserved from the caller
1041		/// The size of the reserve depends on the size of the supplied `code`.
1042		///
1043		/// # Note
1044		///
1045		/// Anyone can instantiate a contract from any uploaded code and thus prevent its removal.
1046		/// To avoid this situation a constructor could employ access control so that it can
1047		/// only be instantiated by permissioned entities. The same is true when uploading
1048		/// through [`Self::instantiate_with_code`].
1049		///
1050		/// If the refcount of the code reaches zero after terminating the last contract that
1051		/// references this code, the code will be removed automatically.
1052		#[pallet::call_index(4)]
1053		#[pallet::weight(T::WeightInfo::upload_code(code.len() as u32))]
1054		pub fn upload_code(
1055			origin: OriginFor<T>,
1056			code: Vec<u8>,
1057			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
1058		) -> DispatchResult {
1059			Self::bare_upload_code(origin, code, storage_deposit_limit).map(|_| ())
1060		}
1061
1062		/// Remove the code stored under `code_hash` and refund the deposit to its owner.
1063		///
1064		/// A code can only be removed by its original uploader (its owner) and only if it is
1065		/// not used by any contract.
1066		#[pallet::call_index(5)]
1067		#[pallet::weight(T::WeightInfo::remove_code())]
1068		pub fn remove_code(
1069			origin: OriginFor<T>,
1070			code_hash: sp_core::H256,
1071		) -> DispatchResultWithPostInfo {
1072			let origin = ensure_signed(origin)?;
1073			<ContractBlob<T>>::remove(&origin, code_hash)?;
1074			// we waive the fee because removing unused code is beneficial
1075			Ok(Pays::No.into())
1076		}
1077
1078		/// Privileged function that changes the code of an existing contract.
1079		///
1080		/// This takes care of updating refcounts and all other necessary operations. Returns
1081		/// an error if either the `code_hash` or `dest` do not exist.
1082		///
1083		/// # Note
1084		///
1085		/// This does **not** change the address of the contract in question. This means
1086		/// that the contract address is no longer derived from its code hash after calling
1087		/// this dispatchable.
1088		#[pallet::call_index(6)]
1089		#[pallet::weight(T::WeightInfo::set_code())]
1090		pub fn set_code(
1091			origin: OriginFor<T>,
1092			dest: H160,
1093			code_hash: sp_core::H256,
1094		) -> DispatchResult {
1095			ensure_root(origin)?;
1096			<AccountInfoOf<T>>::try_mutate(&dest, |account| {
1097				let Some(account) = account else {
1098					return Err(<Error<T>>::ContractNotFound.into());
1099				};
1100
1101				let AccountType::Contract(ref mut contract) = account.account_type else {
1102					return Err(<Error<T>>::ContractNotFound.into());
1103				};
1104
1105				<CodeInfo<T>>::increment_refcount(code_hash)?;
1106				let _ = <CodeInfo<T>>::decrement_refcount(contract.code_hash)?;
1107				contract.code_hash = code_hash;
1108
1109				Ok(())
1110			})
1111		}
1112
1113		/// Register the callers account id so that it can be used in contract interactions.
1114		///
1115		/// This will error if the origin is already mapped or is a eth native `Address20`. It will
1116		/// take a deposit that can be released by calling [`Self::unmap_account`].
1117		#[pallet::call_index(7)]
1118		#[pallet::weight(T::WeightInfo::map_account())]
1119		pub fn map_account(origin: OriginFor<T>) -> DispatchResult {
1120			let origin = ensure_signed(origin)?;
1121			T::AddressMapper::map(&origin)
1122		}
1123
1124		/// Unregister the callers account id in order to free the deposit.
1125		///
1126		/// There is no reason to ever call this function other than freeing up the deposit.
1127		/// This is only useful when the account should no longer be used.
1128		#[pallet::call_index(8)]
1129		#[pallet::weight(T::WeightInfo::unmap_account())]
1130		pub fn unmap_account(origin: OriginFor<T>) -> DispatchResult {
1131			let origin = ensure_signed(origin)?;
1132			T::AddressMapper::unmap(&origin)
1133		}
1134
1135		/// Dispatch an `call` with the origin set to the callers fallback address.
1136		///
1137		/// Every `AccountId32` can control its corresponding fallback account. The fallback account
1138		/// is the `AccountId20` with the last 12 bytes set to `0xEE`. This is essentially a
1139		/// recovery function in case an `AccountId20` was used without creating a mapping first.
1140		#[pallet::call_index(9)]
1141		#[pallet::weight({
1142			let dispatch_info = call.get_dispatch_info();
1143			(
1144				T::WeightInfo::dispatch_as_fallback_account().saturating_add(dispatch_info.call_weight),
1145				dispatch_info.class
1146			)
1147		})]
1148		pub fn dispatch_as_fallback_account(
1149			origin: OriginFor<T>,
1150			call: Box<<T as Config>::RuntimeCall>,
1151		) -> DispatchResultWithPostInfo {
1152			let origin = ensure_signed(origin)?;
1153			let unmapped_account =
1154				T::AddressMapper::to_fallback_account_id(&T::AddressMapper::to_address(&origin));
1155			call.dispatch(RawOrigin::Signed(unmapped_account).into())
1156		}
1157	}
1158}
1159
1160/// Create a dispatch result reflecting the amount of consumed gas.
1161fn dispatch_result<R>(
1162	result: Result<R, DispatchError>,
1163	gas_consumed: Weight,
1164	base_weight: Weight,
1165) -> DispatchResultWithPostInfo {
1166	let post_info = PostDispatchInfo {
1167		actual_weight: Some(gas_consumed.saturating_add(base_weight)),
1168		pays_fee: Default::default(),
1169	};
1170
1171	result
1172		.map(|_| post_info)
1173		.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e })
1174}
1175
1176impl<T: Config> Pallet<T>
1177where
1178	BalanceOf<T>: Into<U256> + TryFrom<U256> + Bounded,
1179	MomentOf<T>: Into<U256>,
1180	T::Hash: frame_support::traits::IsType<H256>,
1181{
1182	/// A generalized version of [`Self::call`].
1183	///
1184	/// Identical to [`Self::call`] but tailored towards being called by other code within the
1185	/// runtime as opposed to from an extrinsic. It returns more information and allows the
1186	/// enablement of features that are not suitable for an extrinsic (debugging, event
1187	/// collection).
1188	pub fn bare_call(
1189		origin: OriginFor<T>,
1190		dest: H160,
1191		evm_value: U256,
1192		gas_limit: Weight,
1193		storage_deposit_limit: DepositLimit<BalanceOf<T>>,
1194		data: Vec<u8>,
1195	) -> ContractResult<ExecReturnValue, BalanceOf<T>> {
1196		if let Err(contract_result) = Self::ensure_non_contract_if_signed(&origin) {
1197			return contract_result;
1198		}
1199		let mut gas_meter = GasMeter::new(gas_limit);
1200		let mut storage_deposit = Default::default();
1201
1202		let try_call = || {
1203			let origin = Origin::from_runtime_origin(origin)?;
1204			let mut storage_meter = StorageMeter::new(storage_deposit_limit.limit());
1205			let result = ExecStack::<T, ContractBlob<T>>::run_call(
1206				origin.clone(),
1207				dest,
1208				&mut gas_meter,
1209				&mut storage_meter,
1210				evm_value,
1211				data,
1212				storage_deposit_limit.is_unchecked(),
1213			)?;
1214			storage_deposit = storage_meter
1215				.try_into_deposit(&origin, storage_deposit_limit.is_unchecked())
1216				.inspect_err(|err| {
1217					log::debug!(target: LOG_TARGET, "Failed to transfer deposit: {err:?}");
1218				})?;
1219			Ok(result)
1220		};
1221		let result = Self::run_guarded(try_call);
1222		ContractResult {
1223			result: result.map_err(|r| r.error),
1224			gas_consumed: gas_meter.gas_consumed(),
1225			gas_required: gas_meter.gas_required(),
1226			storage_deposit,
1227		}
1228	}
1229
1230	/// Prepare a dry run for the given account.
1231	///
1232	///
1233	/// This function is public because it is called by the runtime API implementation
1234	/// (see `impl_runtime_apis_plus_revive`).
1235	pub fn prepare_dry_run(account: &T::AccountId) {
1236		// Bump the  nonce to simulate what would happen
1237		// `pre-dispatch` if the transaction was executed.
1238		frame_system::Pallet::<T>::inc_account_nonce(account);
1239	}
1240
1241	/// A generalized version of [`Self::instantiate`] or [`Self::instantiate_with_code`].
1242	///
1243	/// Identical to [`Self::instantiate`] or [`Self::instantiate_with_code`] but tailored towards
1244	/// being called by other code within the runtime as opposed to from an extrinsic. It returns
1245	/// more information to the caller useful to estimate the cost of the operation.
1246	pub fn bare_instantiate(
1247		origin: OriginFor<T>,
1248		evm_value: U256,
1249		gas_limit: Weight,
1250		storage_deposit_limit: DepositLimit<BalanceOf<T>>,
1251		code: Code,
1252		data: Vec<u8>,
1253		salt: Option<[u8; 32]>,
1254		bump_nonce: BumpNonce,
1255	) -> ContractResult<InstantiateReturnValue, BalanceOf<T>> {
1256		// Enforce EIP-3607 for top-level signed origins: deny signed contract addresses.
1257		if let Err(contract_result) = Self::ensure_non_contract_if_signed(&origin) {
1258			return contract_result;
1259		}
1260		let mut gas_meter = GasMeter::new(gas_limit);
1261		let mut storage_deposit = Default::default();
1262		let unchecked_deposit_limit = storage_deposit_limit.is_unchecked();
1263		let mut storage_deposit_limit = storage_deposit_limit.limit();
1264		let try_instantiate = || {
1265			let instantiate_account = T::InstantiateOrigin::ensure_origin(origin.clone())?;
1266
1267			if_tracing(|t| t.instantiate_code(&code, salt.as_ref()));
1268			let (executable, upload_deposit) = match code {
1269				Code::Upload(code) if code.starts_with(&polkavm_common::program::BLOB_MAGIC) => {
1270					let upload_account = T::UploadOrigin::ensure_origin(origin)?;
1271					let (executable, upload_deposit) = Self::try_upload_pvm_code(
1272						upload_account,
1273						code,
1274						storage_deposit_limit,
1275						unchecked_deposit_limit,
1276					)?;
1277					storage_deposit_limit.saturating_reduce(upload_deposit);
1278					(executable, upload_deposit)
1279				},
1280				Code::Upload(code) =>
1281					if T::AllowEVMBytecode::get() {
1282						let origin = T::UploadOrigin::ensure_origin(origin)?;
1283						let executable = ContractBlob::from_evm_init_code(code, origin)?;
1284						(executable, Default::default())
1285					} else {
1286						return Err(<Error<T>>::CodeRejected.into())
1287					},
1288				Code::Existing(code_hash) =>
1289					(ContractBlob::from_storage(code_hash, &mut gas_meter)?, Default::default()),
1290			};
1291			let instantiate_origin = Origin::from_account_id(instantiate_account.clone());
1292			let mut storage_meter = StorageMeter::new(storage_deposit_limit);
1293			let result = ExecStack::<T, ContractBlob<T>>::run_instantiate(
1294				instantiate_account,
1295				executable,
1296				&mut gas_meter,
1297				&mut storage_meter,
1298				evm_value,
1299				data,
1300				salt.as_ref(),
1301				unchecked_deposit_limit,
1302				bump_nonce,
1303			);
1304			storage_deposit = storage_meter
1305				.try_into_deposit(&instantiate_origin, unchecked_deposit_limit)?
1306				.saturating_add(&StorageDeposit::Charge(upload_deposit));
1307			result
1308		};
1309		let output = Self::run_guarded(try_instantiate);
1310		ContractResult {
1311			result: output
1312				.map(|(addr, result)| InstantiateReturnValue { result, addr })
1313				.map_err(|e| e.error),
1314			gas_consumed: gas_meter.gas_consumed(),
1315			gas_required: gas_meter.gas_required(),
1316			storage_deposit,
1317		}
1318	}
1319
1320	/// Dry-run Ethereum calls.
1321	///
1322	/// # Parameters
1323	///
1324	/// - `tx`: The Ethereum transaction to simulate.
1325	/// - `gas_limit`: The gas limit enforced during contract execution.
1326	/// - `tx_fee`: A function that returns the fee for the computed eth_transact and actual
1327	/// dispatched call
1328	pub fn dry_run_eth_transact(
1329		mut tx: GenericTransaction,
1330		gas_limit: Weight,
1331		tx_fee: impl Fn(<T as Config>::RuntimeCall, <T as Config>::RuntimeCall) -> BalanceOf<T>,
1332	) -> Result<EthTransactInfo<BalanceOf<T>>, EthTransactError>
1333	where
1334		<T as frame_system::Config>::RuntimeCall:
1335			Dispatchable<Info = frame_support::dispatch::DispatchInfo>,
1336		T: pallet_transaction_payment::Config,
1337		OnChargeTransactionBalanceOf<T>: Into<BalanceOf<T>>,
1338		<T as Config>::RuntimeCall: From<crate::Call<T>>,
1339		<T as Config>::RuntimeCall: Encode,
1340		T::Nonce: Into<U256>,
1341		T::Hash: frame_support::traits::IsType<H256>,
1342	{
1343		log::trace!(target: LOG_TARGET, "dry_run_eth_transact: {tx:?} gas_limit: {gas_limit:?}");
1344
1345		let from = tx.from.unwrap_or_default();
1346		let origin = T::AddressMapper::to_account_id(&from);
1347		Self::prepare_dry_run(&origin);
1348
1349		let storage_deposit_limit = if tx.gas.is_some() {
1350			DepositLimit::Balance(BalanceOf::<T>::max_value())
1351		} else {
1352			DepositLimit::UnsafeOnlyForDryRun
1353		};
1354
1355		if tx.nonce.is_none() {
1356			tx.nonce = Some(<System<T>>::account_nonce(&origin).into());
1357		}
1358		if tx.chain_id.is_none() {
1359			tx.chain_id = Some(T::ChainId::get().into());
1360		}
1361		if tx.gas_price.is_none() {
1362			tx.gas_price = Some(GAS_PRICE.into());
1363		}
1364		if tx.max_priority_fee_per_gas.is_none() {
1365			tx.max_priority_fee_per_gas = Some(GAS_PRICE.into());
1366		}
1367		if tx.max_fee_per_gas.is_none() {
1368			tx.max_fee_per_gas = Some(GAS_PRICE.into());
1369		}
1370		if tx.gas.is_none() {
1371			tx.gas = Some(Self::evm_block_gas_limit());
1372		}
1373		if tx.r#type.is_none() {
1374			tx.r#type = Some(TYPE_EIP1559.into());
1375		}
1376
1377		// Convert the value to the native balance type.
1378		let value = tx.value.unwrap_or_default();
1379		let input = tx.input.clone().to_vec();
1380
1381		let extract_error = |err| {
1382			if err == Error::<T>::TransferFailed.into() ||
1383				err == Error::<T>::StorageDepositNotEnoughFunds.into() ||
1384				err == Error::<T>::StorageDepositLimitExhausted.into()
1385			{
1386				let balance = Self::evm_balance(&from);
1387				return Err(EthTransactError::Message(format!(
1388					"insufficient funds for gas * price + value: address {from:?} have {balance} (supplied gas {})",
1389					tx.gas.unwrap_or_default()
1390				)));
1391			}
1392
1393			return Err(EthTransactError::Message(format!(
1394				"Failed to instantiate contract: {err:?}"
1395			)));
1396		};
1397
1398		// Dry run the call
1399		let (mut result, dispatch_call) = match tx.to {
1400			// A contract call.
1401			Some(dest) => {
1402				if dest == RUNTIME_PALLETS_ADDR {
1403					let Ok(dispatch_call) = <T as Config>::RuntimeCall::decode(&mut &input[..])
1404					else {
1405						return Err(EthTransactError::Message(format!(
1406							"Failed to decode pallet-call {input:?}"
1407						)));
1408					};
1409
1410					if let Err(err) =
1411						dispatch_call.clone().dispatch(RawOrigin::Signed(origin).into())
1412					{
1413						return Err(EthTransactError::Message(format!(
1414							"Failed to dispatch call: {err:?}"
1415						)));
1416					};
1417
1418					let result = EthTransactInfo {
1419						gas_required: dispatch_call.get_dispatch_info().total_weight(),
1420						..Default::default()
1421					};
1422
1423					(result, dispatch_call)
1424				} else {
1425					// Dry run the call.
1426					let result = crate::Pallet::<T>::bare_call(
1427						T::RuntimeOrigin::signed(origin),
1428						dest,
1429						value,
1430						gas_limit,
1431						storage_deposit_limit,
1432						input.clone(),
1433					);
1434
1435					let data = match result.result {
1436						Ok(return_value) => {
1437							if return_value.did_revert() {
1438								return Err(EthTransactError::Data(return_value.data));
1439							}
1440							return_value.data
1441						},
1442						Err(err) => {
1443							log::debug!(target: LOG_TARGET, "Failed to execute call: {err:?}");
1444							return extract_error(err);
1445						},
1446					};
1447
1448					let result = EthTransactInfo {
1449						gas_required: result.gas_required,
1450						storage_deposit: result.storage_deposit.charge_or_zero(),
1451						data,
1452						eth_gas: Default::default(),
1453					};
1454
1455					let (gas_limit, storage_deposit_limit) = T::EthGasEncoder::as_encoded_values(
1456						result.gas_required,
1457						result.storage_deposit,
1458					);
1459					let dispatch_call: <T as Config>::RuntimeCall = crate::Call::<T>::eth_call {
1460						dest,
1461						value,
1462						gas_limit,
1463						storage_deposit_limit,
1464						data: input.clone(),
1465					}
1466					.into();
1467					(result, dispatch_call)
1468				}
1469			},
1470			// A contract deployment
1471			None => {
1472				// Extract code and data from the input.
1473				let (code, data) = if input.starts_with(&polkavm_common::program::BLOB_MAGIC) {
1474					extract_code_and_data(&input).unwrap_or_else(|| (input, Default::default()))
1475				} else {
1476					(input, vec![])
1477				};
1478
1479				// Dry run the call.
1480				let result = crate::Pallet::<T>::bare_instantiate(
1481					T::RuntimeOrigin::signed(origin),
1482					value,
1483					gas_limit,
1484					storage_deposit_limit,
1485					Code::Upload(code.clone()),
1486					data.clone(),
1487					None,
1488					BumpNonce::No,
1489				);
1490
1491				let returned_data = match result.result {
1492					Ok(return_value) => {
1493						if return_value.result.did_revert() {
1494							return Err(EthTransactError::Data(return_value.result.data));
1495						}
1496						return_value.result.data
1497					},
1498					Err(err) => {
1499						log::debug!(target: LOG_TARGET, "Failed to instantiate: {err:?}");
1500						return extract_error(err);
1501					},
1502				};
1503
1504				let result = EthTransactInfo {
1505					gas_required: result.gas_required,
1506					storage_deposit: result.storage_deposit.charge_or_zero(),
1507					data: returned_data,
1508					eth_gas: Default::default(),
1509				};
1510
1511				// Get the dispatch info of the call.
1512				let (gas_limit, storage_deposit_limit) = T::EthGasEncoder::as_encoded_values(
1513					result.gas_required,
1514					result.storage_deposit,
1515				);
1516				let dispatch_call: <T as Config>::RuntimeCall =
1517					crate::Call::<T>::eth_instantiate_with_code {
1518						value,
1519						gas_limit,
1520						storage_deposit_limit,
1521						code,
1522						data,
1523					}
1524					.into();
1525				(result, dispatch_call)
1526			},
1527		};
1528
1529		let Ok(unsigned_tx) = tx.clone().try_into_unsigned() else {
1530			return Err(EthTransactError::Message("Invalid transaction".into()));
1531		};
1532
1533		let eth_transact_call =
1534			crate::Call::<T>::eth_transact { payload: unsigned_tx.dummy_signed_payload() };
1535		let fee = tx_fee(eth_transact_call.into(), dispatch_call);
1536		let raw_gas = Self::evm_fee_to_gas(fee);
1537		let eth_gas =
1538			T::EthGasEncoder::encode(raw_gas, result.gas_required, result.storage_deposit);
1539
1540		log::trace!(target: LOG_TARGET, "bare_eth_call: raw_gas: {raw_gas:?} eth_gas: {eth_gas:?}");
1541		result.eth_gas = eth_gas;
1542		Ok(result)
1543	}
1544
1545	/// Get the balance with EVM decimals of the given `address`.
1546	///
1547	/// Returns the spendable balance excluding the existential deposit.
1548	pub fn evm_balance(address: &H160) -> U256 {
1549		let balance = AccountInfo::<T>::balance((*address).into());
1550		Self::convert_native_to_evm(balance)
1551	}
1552
1553	/// Set the EVM balance of an account.
1554	///
1555	/// The account's total balance becomes the EVM value plus the existential deposit,
1556	/// consistent with `evm_balance` which returns the spendable balance excluding the existential
1557	/// deposit.
1558	pub fn set_evm_balance(address: &H160, evm_value: U256) -> Result<(), Error<T>> {
1559		let (balance, dust) = Self::new_balance_with_dust(evm_value)
1560			.map_err(|_| <Error<T>>::BalanceConversionFailed)?;
1561		let account_id = T::AddressMapper::to_account_id(&address);
1562		T::Currency::set_balance(&account_id, balance);
1563		AccountInfoOf::<T>::mutate(address, |account| {
1564			account.as_mut().map(|a| a.dust = dust);
1565		});
1566
1567		Ok(())
1568	}
1569
1570	/// Construct native balance from EVM balance.
1571	///
1572	/// Adds the existential deposit and returns the native balance plus the dust.
1573	pub fn new_balance_with_dust(
1574		evm_value: U256,
1575	) -> Result<(BalanceOf<T>, u32), BalanceConversionError> {
1576		let ed = T::Currency::minimum_balance();
1577		let balance_with_dust = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(evm_value)?;
1578		let (value, dust) = balance_with_dust.deconstruct();
1579
1580		Ok((ed.saturating_add(value), dust))
1581	}
1582
1583	/// Get the nonce for the given `address`.
1584	pub fn evm_nonce(address: &H160) -> u32
1585	where
1586		T::Nonce: Into<u32>,
1587	{
1588		let account = T::AddressMapper::to_account_id(&address);
1589		System::<T>::account_nonce(account).into()
1590	}
1591
1592	/// Convert a substrate fee into a gas value, using the fixed `GAS_PRICE`.
1593	/// The gas is calculated as `fee / GAS_PRICE`, rounded up to the nearest integer.
1594	pub fn evm_fee_to_gas(fee: BalanceOf<T>) -> U256 {
1595		let fee = Self::convert_native_to_evm(fee);
1596		let gas_price = GAS_PRICE.into();
1597		let (quotient, remainder) = fee.div_mod(gas_price);
1598		if remainder.is_zero() {
1599			quotient
1600		} else {
1601			quotient + U256::one()
1602		}
1603	}
1604
1605	/// Convert a gas value into a substrate fee
1606	fn evm_gas_to_fee(gas: U256, gas_price: U256) -> Result<BalanceOf<T>, Error<T>> {
1607		let fee = gas.saturating_mul(gas_price);
1608		let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(fee)
1609			.map_err(|_| <Error<T>>::BalanceConversionFailed)?;
1610		Ok(value.into_rounded_balance())
1611	}
1612
1613	/// Convert a weight to a gas value.
1614	pub fn evm_gas_from_weight(weight: Weight) -> U256 {
1615		let fee = T::WeightPrice::convert(weight);
1616		Self::evm_fee_to_gas(fee)
1617	}
1618
1619	/// Get the block gas limit.
1620	pub fn evm_block_gas_limit() -> U256
1621	where
1622		<T as frame_system::Config>::RuntimeCall:
1623			Dispatchable<Info = frame_support::dispatch::DispatchInfo>,
1624		T: pallet_transaction_payment::Config,
1625		OnChargeTransactionBalanceOf<T>: Into<BalanceOf<T>>,
1626	{
1627		let max_block_weight = T::BlockWeights::get()
1628			.get(DispatchClass::Normal)
1629			.max_total
1630			.unwrap_or_else(|| T::BlockWeights::get().max_block);
1631
1632		let length_fee = pallet_transaction_payment::Pallet::<T>::length_to_fee(
1633			5 * 1024 * 1024, // 5 MB
1634		);
1635
1636		Self::evm_gas_from_weight(max_block_weight)
1637			.saturating_add(Self::evm_fee_to_gas(length_fee.into()))
1638	}
1639
1640	/// Get the gas price.
1641	pub fn evm_gas_price() -> U256 {
1642		GAS_PRICE.into()
1643	}
1644
1645	/// Build an EVM tracer from the given tracer type.
1646	pub fn evm_tracer(tracer_type: TracerType) -> Tracer<T>
1647	where
1648		T::Nonce: Into<u32>,
1649	{
1650		match tracer_type {
1651			TracerType::CallTracer(config) => CallTracer::new(
1652				config.unwrap_or_default(),
1653				Self::evm_gas_from_weight as fn(Weight) -> U256,
1654			)
1655			.into(),
1656			TracerType::PrestateTracer(config) =>
1657				PrestateTracer::new(config.unwrap_or_default()).into(),
1658		}
1659	}
1660
1661	/// A generalized version of [`Self::upload_code`].
1662	///
1663	/// It is identical to [`Self::upload_code`] and only differs in the information it returns.
1664	pub fn bare_upload_code(
1665		origin: OriginFor<T>,
1666		code: Vec<u8>,
1667		storage_deposit_limit: BalanceOf<T>,
1668	) -> CodeUploadResult<BalanceOf<T>> {
1669		let origin = T::UploadOrigin::ensure_origin(origin)?;
1670		let (module, deposit) =
1671			Self::try_upload_pvm_code(origin, code, storage_deposit_limit, false)?;
1672		Ok(CodeUploadReturnValue { code_hash: *module.code_hash(), deposit })
1673	}
1674
1675	/// Query storage of a specified contract under a specified key.
1676	pub fn get_storage(address: H160, key: [u8; 32]) -> GetStorageResult {
1677		let contract_info =
1678			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
1679
1680		let maybe_value = contract_info.read(&Key::from_fixed(key));
1681		Ok(maybe_value)
1682	}
1683
1684	/// Query storage of a specified contract under a specified variable-sized key.
1685	pub fn get_storage_var_key(address: H160, key: Vec<u8>) -> GetStorageResult {
1686		let contract_info =
1687			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
1688
1689		let maybe_value = contract_info.read(
1690			&Key::try_from_var(key)
1691				.map_err(|_| ContractAccessError::KeyDecodingFailed)?
1692				.into(),
1693		);
1694		Ok(maybe_value)
1695	}
1696
1697	/// Uploads new code and returns the Vm binary contract blob and deposit amount collected.
1698	fn try_upload_pvm_code(
1699		origin: T::AccountId,
1700		code: Vec<u8>,
1701		storage_deposit_limit: BalanceOf<T>,
1702		skip_transfer: bool,
1703	) -> Result<(ContractBlob<T>, BalanceOf<T>), DispatchError> {
1704		let mut module = ContractBlob::from_pvm_code(code, origin)?;
1705		let deposit = module.store_code(skip_transfer)?;
1706		ensure!(storage_deposit_limit >= deposit, <Error<T>>::StorageDepositLimitExhausted);
1707		Ok((module, deposit))
1708	}
1709
1710	/// Run the supplied function `f` if no other instance of this pallet is on the stack.
1711	fn run_guarded<R, F: FnOnce() -> Result<R, ExecError>>(f: F) -> Result<R, ExecError> {
1712		executing_contract::using_once(&mut false, || {
1713			executing_contract::with(|f| {
1714				// Fail if already entered contract execution
1715				if *f {
1716					return Err(())
1717				}
1718				// We are entering contract execution
1719				*f = true;
1720				Ok(())
1721			})
1722				.expect("Returns `Ok` if called within `using_once`. It is syntactically obvious that this is the case; qed")
1723				.map_err(|_| <Error<T>>::ReenteredPallet.into())
1724				.map(|_| f())
1725				.and_then(|r| r)
1726		})
1727	}
1728
1729	/// Convert a native balance to EVM balance.
1730	pub fn convert_native_to_evm(value: impl Into<BalanceWithDust<BalanceOf<T>>>) -> U256 {
1731		let (value, dust) = value.into().deconstruct();
1732		value
1733			.into()
1734			.saturating_mul(T::NativeToEthRatio::get().into())
1735			.saturating_add(dust.into())
1736	}
1737
1738	/// Ensure the origin has no code deplyoyed if it is a signed origin.
1739	fn ensure_non_contract_if_signed<ReturnValue>(
1740		origin: &OriginFor<T>,
1741	) -> Result<(), ContractResult<ReturnValue, BalanceOf<T>>> {
1742		use crate::exec::is_precompile;
1743		let Ok(who) = ensure_signed(origin.clone()) else { return Ok(()) };
1744		let address = <T::AddressMapper as AddressMapper<T>>::to_address(&who);
1745
1746		// EIP_1052: precompile can never be used as EOA.
1747		if is_precompile::<T, ContractBlob<T>>(&address) {
1748			log::debug!(
1749				target: crate::LOG_TARGET,
1750				"EIP-3607: reject externally-signed tx from precompile account {:?}",
1751				address
1752			);
1753			return Err(ContractResult {
1754				result: Err(DispatchError::BadOrigin),
1755				gas_consumed: Weight::default(),
1756				gas_required: Weight::default(),
1757				storage_deposit: Default::default(),
1758			});
1759		}
1760
1761		// Deployed code exists when hash is neither zero (no account) nor EMPTY_CODE_HASH
1762		// (account exists but no code).
1763		if <AccountInfo<T>>::is_contract(&address) {
1764			log::debug!(
1765				target: crate::LOG_TARGET,
1766				"EIP-3607: reject externally-signed tx from contract account {:?}",
1767				address
1768			);
1769			return Err(ContractResult {
1770				result: Err(DispatchError::BadOrigin),
1771				gas_consumed: Weight::default(),
1772				gas_required: Weight::default(),
1773				storage_deposit: Default::default(),
1774			});
1775		}
1776		Ok(())
1777	}
1778}
1779
1780impl<T: Config> Pallet<T> {
1781	/// Pallet account, used to hold funds for contracts upload deposit.
1782	pub fn account_id() -> T::AccountId {
1783		use frame_support::PalletId;
1784		use sp_runtime::traits::AccountIdConversion;
1785		PalletId(*b"py/reviv").into_account_truncating()
1786	}
1787
1788	/// Returns true if the evm value carries dust.
1789	fn has_dust(value: U256) -> bool {
1790		value % U256::from(<T>::NativeToEthRatio::get()) != U256::zero()
1791	}
1792
1793	/// Returns true if the evm value carries balance.
1794	fn has_balance(value: U256) -> bool {
1795		value >= U256::from(<T>::NativeToEthRatio::get())
1796	}
1797
1798	/// Return the existential deposit of [`Config::Currency`].
1799	fn min_balance() -> BalanceOf<T> {
1800		<T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
1801	}
1802
1803	/// Deposit a pallet revive event.
1804	fn deposit_event(event: Event<T>) {
1805		<frame_system::Pallet<T>>::deposit_event(<T as Config>::RuntimeEvent::from(event))
1806	}
1807
1808	/// The address of the validator that produced the current block.
1809	pub fn block_author() -> Option<H160> {
1810		use frame_support::traits::FindAuthor;
1811
1812		let digest = <frame_system::Pallet<T>>::digest();
1813		let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime());
1814
1815		let account_id = T::FindAuthor::find_author(pre_runtime_digests)?;
1816		Some(T::AddressMapper::to_address(&account_id))
1817	}
1818
1819	/// Returns the code at `address`.
1820	///
1821	/// This takes pre-compiles into account.
1822	pub fn code(address: &H160) -> Vec<u8> {
1823		use precompiles::{All, Precompiles};
1824		if let Some(code) = <All<T>>::code(address.as_fixed_bytes()) {
1825			return code.into()
1826		}
1827		AccountInfo::<T>::load_contract(&address)
1828			.and_then(|contract| <PristineCode<T>>::get(contract.code_hash))
1829			.map(|code| code.into())
1830			.unwrap_or_default()
1831	}
1832}
1833
1834/// The address used to call the runtime's pallets dispatchables
1835///
1836/// Note:
1837/// computed with PalletId(*b"py/paddr").into_account_truncating();
1838pub const RUNTIME_PALLETS_ADDR: H160 =
1839	H160(hex_literal::hex!("6d6f646c70792f70616464720000000000000000"));
1840
1841// Set up a global reference to the boolean flag used for the re-entrancy guard.
1842environmental!(executing_contract: bool);
1843
1844sp_api::decl_runtime_apis! {
1845	/// The API used to dry-run contract interactions.
1846	#[api_version(1)]
1847	pub trait ReviveApi<AccountId, Balance, Nonce, BlockNumber> where
1848		AccountId: Codec,
1849		Balance: Codec,
1850		Nonce: Codec,
1851		BlockNumber: Codec,
1852	{
1853		/// Returns the block gas limit.
1854		fn block_gas_limit() -> U256;
1855
1856		/// Returns the free balance of the given `[H160]` address, using EVM decimals.
1857		fn balance(address: H160) -> U256;
1858
1859		/// Returns the gas price.
1860		fn gas_price() -> U256;
1861
1862		/// Returns the nonce of the given `[H160]` address.
1863		fn nonce(address: H160) -> Nonce;
1864
1865		/// Perform a call from a specified account to a given contract.
1866		///
1867		/// See [`crate::Pallet::bare_call`].
1868		fn call(
1869			origin: AccountId,
1870			dest: H160,
1871			value: Balance,
1872			gas_limit: Option<Weight>,
1873			storage_deposit_limit: Option<Balance>,
1874			input_data: Vec<u8>,
1875		) -> ContractResult<ExecReturnValue, Balance>;
1876
1877		/// Instantiate a new contract.
1878		///
1879		/// See `[crate::Pallet::bare_instantiate]`.
1880		fn instantiate(
1881			origin: AccountId,
1882			value: Balance,
1883			gas_limit: Option<Weight>,
1884			storage_deposit_limit: Option<Balance>,
1885			code: Code,
1886			data: Vec<u8>,
1887			salt: Option<[u8; 32]>,
1888		) -> ContractResult<InstantiateReturnValue, Balance>;
1889
1890
1891		/// Perform an Ethereum call.
1892		///
1893		/// See [`crate::Pallet::dry_run_eth_transact`]
1894		fn eth_transact(tx: GenericTransaction) -> Result<EthTransactInfo<Balance>, EthTransactError>;
1895
1896		/// Upload new code without instantiating a contract from it.
1897		///
1898		/// See [`crate::Pallet::bare_upload_code`].
1899		fn upload_code(
1900			origin: AccountId,
1901			code: Vec<u8>,
1902			storage_deposit_limit: Option<Balance>,
1903		) -> CodeUploadResult<Balance>;
1904
1905		/// Query a given storage key in a given contract.
1906		///
1907		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
1908		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
1909		/// doesn't exist, or doesn't have a contract then `Err` is returned.
1910		fn get_storage(
1911			address: H160,
1912			key: [u8; 32],
1913		) -> GetStorageResult;
1914
1915		/// Query a given variable-sized storage key in a given contract.
1916		///
1917		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
1918		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
1919		/// doesn't exist, or doesn't have a contract then `Err` is returned.
1920		fn get_storage_var_key(
1921			address: H160,
1922			key: Vec<u8>,
1923		) -> GetStorageResult;
1924
1925		/// Traces the execution of an entire block and returns call traces.
1926		///
1927		/// This is intended to be called through `state_call` to replay the block from the
1928		/// parent block.
1929		///
1930		/// See eth-rpc `debug_traceBlockByNumber` for usage.
1931		fn trace_block(
1932			block: Block,
1933			config: TracerType
1934		) -> Vec<(u32, Trace)>;
1935
1936		/// Traces the execution of a specific transaction within a block.
1937		///
1938		/// This is intended to be called through `state_call` to replay the block from the
1939		/// parent hash up to the transaction.
1940		///
1941		/// See eth-rpc `debug_traceTransaction` for usage.
1942		fn trace_tx(
1943			block: Block,
1944			tx_index: u32,
1945			config: TracerType
1946		) -> Option<Trace>;
1947
1948		/// Dry run and return the trace of the given call.
1949		///
1950		/// See eth-rpc `debug_traceCall` for usage.
1951		fn trace_call(tx: GenericTransaction, config: TracerType) -> Result<Trace, EthTransactError>;
1952
1953		/// The address of the validator that produced the current block.
1954		fn block_author() -> Option<H160>;
1955
1956		/// Get the H160 address associated to this account id
1957		fn address(account_id: AccountId) -> H160;
1958
1959		/// Get the account id associated to this H160 address.
1960		fn account_id(address: H160) -> AccountId;
1961
1962		/// The address used to call the runtime's pallets dispatchables
1963		fn runtime_pallets_address() -> H160;
1964
1965		/// The code at the specified address taking pre-compiles into account.
1966		fn code(address: H160) -> Vec<u8>;
1967
1968		/// Construct the new balance and dust components of this EVM balance.
1969		fn new_balance_with_dust(balance: U256) -> Result<(Balance, u32), BalanceConversionError>;
1970	}
1971}
1972
1973/// This macro wraps substrate's `impl_runtime_apis!` and implements `pallet_revive` runtime APIs.
1974///
1975/// # Parameters
1976/// - `$Runtime`: The runtime type to implement the APIs for.
1977/// - `$Executive`: The Executive type of the runtime.
1978/// - `$EthExtra`: Type for additional Ethereum runtime extension.
1979/// - `$($rest:tt)*`: Remaining input to be forwarded to the underlying `impl_runtime_apis!`.
1980#[macro_export]
1981macro_rules! impl_runtime_apis_plus_revive {
1982	($Runtime: ty, $Executive: ty, $EthExtra: ty, $($rest:tt)*) => {
1983
1984		impl_runtime_apis! {
1985			$($rest)*
1986
1987			impl pallet_revive::ReviveApi<Block, AccountId, Balance, Nonce, BlockNumber> for $Runtime {
1988				fn balance(address: $crate::H160) -> $crate::U256 {
1989					$crate::Pallet::<Self>::evm_balance(&address)
1990				}
1991
1992				fn block_author() -> Option<$crate::H160> {
1993					$crate::Pallet::<Self>::block_author()
1994				}
1995
1996				fn block_gas_limit() -> $crate::U256 {
1997					$crate::Pallet::<Self>::evm_block_gas_limit()
1998				}
1999
2000				fn gas_price() -> $crate::U256 {
2001					$crate::Pallet::<Self>::evm_gas_price()
2002				}
2003
2004				fn nonce(address: $crate::H160) -> Nonce {
2005					use $crate::AddressMapper;
2006					let account = <Self as $crate::Config>::AddressMapper::to_account_id(&address);
2007					$crate::frame_system::Pallet::<Self>::account_nonce(account)
2008				}
2009
2010				fn address(account_id: AccountId) -> $crate::H160 {
2011					use $crate::AddressMapper;
2012					<Self as $crate::Config>::AddressMapper::to_address(&account_id)
2013				}
2014
2015				fn eth_transact(
2016					tx: $crate::evm::GenericTransaction,
2017				) -> Result<$crate::EthTransactInfo<Balance>, $crate::EthTransactError> {
2018					use $crate::{
2019						codec::Encode, evm::runtime::EthExtra, frame_support::traits::Get,
2020						sp_runtime::traits::TransactionExtension,
2021						sp_runtime::traits::Block as BlockT
2022					};
2023
2024					let tx_fee = |call: <Self as $crate::frame_system::Config>::RuntimeCall, dispatch_call: <Self as $crate::frame_system::Config>::RuntimeCall| {
2025						use $crate::frame_support::dispatch::GetDispatchInfo;
2026
2027						// Get the dispatch info of the actual call dispatched
2028						let mut dispatch_info = dispatch_call.get_dispatch_info();
2029						dispatch_info.extension_weight =
2030							<$EthExtra>::get_eth_extension(0, 0u32.into()).weight(&dispatch_call);
2031
2032						// Build the extrinsic
2033						let uxt: <Block as BlockT>::Extrinsic =
2034							$crate::sp_runtime::generic::UncheckedExtrinsic::new_bare(call).into();
2035
2036						// Compute the fee of the extrinsic
2037						$crate::pallet_transaction_payment::Pallet::<Self>::compute_fee(
2038							uxt.encoded_size() as u32,
2039							&dispatch_info,
2040							0u32.into(),
2041						)
2042					};
2043
2044					let blockweights: $crate::BlockWeights =
2045						<Self as $crate::frame_system::Config>::BlockWeights::get();
2046					$crate::Pallet::<Self>::dry_run_eth_transact(tx, blockweights.max_block, tx_fee)
2047				}
2048
2049				fn call(
2050					origin: AccountId,
2051					dest: $crate::H160,
2052					value: Balance,
2053					gas_limit: Option<$crate::Weight>,
2054					storage_deposit_limit: Option<Balance>,
2055					input_data: Vec<u8>,
2056				) -> $crate::ContractResult<$crate::ExecReturnValue, Balance> {
2057					use $crate::frame_support::traits::Get;
2058					let blockweights: $crate::BlockWeights =
2059						<Self as $crate::frame_system::Config>::BlockWeights::get();
2060
2061					$crate::Pallet::<Self>::prepare_dry_run(&origin);
2062					$crate::Pallet::<Self>::bare_call(
2063						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin),
2064						dest,
2065						$crate::Pallet::<Self>::convert_native_to_evm(value),
2066						gas_limit.unwrap_or(blockweights.max_block),
2067						$crate::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)),
2068						input_data,
2069					)
2070				}
2071
2072				fn instantiate(
2073					origin: AccountId,
2074					value: Balance,
2075					gas_limit: Option<$crate::Weight>,
2076					storage_deposit_limit: Option<Balance>,
2077					code: $crate::Code,
2078					data: Vec<u8>,
2079					salt: Option<[u8; 32]>,
2080				) -> $crate::ContractResult<$crate::InstantiateReturnValue, Balance> {
2081					use $crate::frame_support::traits::Get;
2082					let blockweights: $crate::BlockWeights =
2083						<Self as $crate::frame_system::Config>::BlockWeights::get();
2084
2085					$crate::Pallet::<Self>::prepare_dry_run(&origin);
2086					$crate::Pallet::<Self>::bare_instantiate(
2087						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin),
2088						$crate::Pallet::<Self>::convert_native_to_evm(value),
2089						gas_limit.unwrap_or(blockweights.max_block),
2090						$crate::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)),
2091						code,
2092						data,
2093						salt,
2094						$crate::BumpNonce::Yes,
2095					)
2096				}
2097
2098				fn upload_code(
2099					origin: AccountId,
2100					code: Vec<u8>,
2101					storage_deposit_limit: Option<Balance>,
2102				) -> $crate::CodeUploadResult<Balance> {
2103					let origin =
2104						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin);
2105					$crate::Pallet::<Self>::bare_upload_code(
2106						origin,
2107						code,
2108						storage_deposit_limit.unwrap_or(u128::MAX),
2109					)
2110				}
2111
2112				fn get_storage_var_key(
2113					address: $crate::H160,
2114					key: Vec<u8>,
2115				) -> $crate::GetStorageResult {
2116					$crate::Pallet::<Self>::get_storage_var_key(address, key)
2117				}
2118
2119				fn get_storage(address: $crate::H160, key: [u8; 32]) -> $crate::GetStorageResult {
2120					$crate::Pallet::<Self>::get_storage(address, key)
2121				}
2122
2123				fn trace_block(
2124					block: Block,
2125					tracer_type: $crate::evm::TracerType,
2126				) -> Vec<(u32, $crate::evm::Trace)> {
2127					use $crate::{sp_runtime::traits::Block, tracing::trace};
2128					let mut traces = vec![];
2129					let (header, extrinsics) = block.deconstruct();
2130					<$Executive>::initialize_block(&header);
2131					for (index, ext) in extrinsics.into_iter().enumerate() {
2132						let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type.clone());
2133						let t = tracer.as_tracing();
2134						let _ = trace(t, || <$Executive>::apply_extrinsic(ext));
2135
2136						if let Some(tx_trace) = tracer.collect_trace() {
2137							traces.push((index as u32, tx_trace));
2138						}
2139					}
2140
2141					traces
2142				}
2143
2144				fn trace_tx(
2145					block: Block,
2146					tx_index: u32,
2147					tracer_type: $crate::evm::TracerType,
2148				) -> Option<$crate::evm::Trace> {
2149					use $crate::{sp_runtime::traits::Block, tracing::trace};
2150
2151					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type);
2152					let (header, extrinsics) = block.deconstruct();
2153
2154					<$Executive>::initialize_block(&header);
2155					for (index, ext) in extrinsics.into_iter().enumerate() {
2156						if index as u32 == tx_index {
2157							let t = tracer.as_tracing();
2158							let _ = trace(t, || <$Executive>::apply_extrinsic(ext));
2159							break;
2160						} else {
2161							let _ = <$Executive>::apply_extrinsic(ext);
2162						}
2163					}
2164
2165					tracer.collect_trace()
2166				}
2167
2168				fn trace_call(
2169					tx: $crate::evm::GenericTransaction,
2170					tracer_type: $crate::evm::TracerType,
2171				) -> Result<$crate::evm::Trace, $crate::EthTransactError> {
2172					use $crate::tracing::trace;
2173					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type.clone());
2174					let t = tracer.as_tracing();
2175
2176					t.watch_address(&tx.from.unwrap_or_default());
2177					t.watch_address(&$crate::Pallet::<Self>::block_author().unwrap_or_default());
2178					let result = trace(t, || Self::eth_transact(tx));
2179
2180					if let Some(trace) = tracer.collect_trace() {
2181						Ok(trace)
2182					} else if let Err(err) = result {
2183						Err(err)
2184					} else {
2185						Ok($crate::Pallet::<Self>::evm_tracer(tracer_type).empty_trace())
2186					}
2187				}
2188
2189				fn runtime_pallets_address() -> $crate::H160 {
2190					$crate::RUNTIME_PALLETS_ADDR
2191				}
2192
2193				fn code(address: $crate::H160) -> Vec<u8> {
2194					$crate::Pallet::<Self>::code(&address)
2195				}
2196
2197				fn account_id(address: $crate::H160) -> AccountId {
2198					use $crate::AddressMapper;
2199					<Self as $crate::Config>::AddressMapper::to_account_id(&address)
2200				}
2201
2202				fn new_balance_with_dust(balance: $crate::U256) -> Result<(Balance, u32), $crate::BalanceConversionError> {
2203					$crate::Pallet::<Self>::new_balance_with_dust(balance)
2204				}
2205			}
2206		}
2207	};
2208}