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>,
584	{
585		fn build(&self) {
586			use crate::{exec::Key, vm::ContractBlob};
587			use frame_support::traits::fungible::Mutate;
588
589			if !System::<T>::account_exists(&Pallet::<T>::account_id()) {
590				let _ = T::Currency::mint_into(
591					&Pallet::<T>::account_id(),
592					T::Currency::minimum_balance(),
593				);
594			}
595
596			for id in &self.mapped_accounts {
597				if let Err(err) = T::AddressMapper::map_no_deposit(id) {
598					log::error!(target: LOG_TARGET, "Failed to map account {id:?}: {err:?}");
599				}
600			}
601
602			let owner = Pallet::<T>::account_id();
603
604			for genesis::Account { address, balance, nonce, contract_data } in &self.accounts {
605				let Ok(balance_with_dust) =
606					BalanceWithDust::<BalanceOf<T>>::from_value::<T>(*balance).inspect_err(|err| {
607						log::error!(target: LOG_TARGET, "Failed to convert balance for {address:?}: {err:?}");
608					})
609				else {
610					continue;
611				};
612				let account_id = T::AddressMapper::to_account_id(address);
613				let (value, dust) = balance_with_dust.deconstruct();
614
615				let _ = T::Currency::set_balance(&account_id, value);
616				frame_system::Account::<T>::mutate(&account_id, |info| {
617					info.nonce = (*nonce).into();
618				});
619
620				match contract_data {
621					None => {
622						AccountInfoOf::<T>::insert(
623							address,
624							AccountInfo { account_type: AccountType::EOA, dust },
625						);
626					},
627					Some(genesis::ContractData { code, storage }) => {
628						let blob = if code.starts_with(&polkavm_common::program::BLOB_MAGIC) {
629							ContractBlob::<T>::from_pvm_code(   code.clone(), owner.clone()).inspect_err(|err| {
630								log::error!(target: LOG_TARGET, "Failed to create PVM ContractBlob for {address:?}: {err:?}");
631							})
632						} else {
633							ContractBlob::<T>::from_evm_runtime_code(code.clone(), account_id).inspect_err(|err| {
634								log::error!(target: LOG_TARGET, "Failed to create EVM ContractBlob for {address:?}: {err:?}");
635							})
636						};
637
638						let Ok(blob) = blob else {
639							continue;
640						};
641
642						let code_hash = *blob.code_hash();
643						let Ok(info) = <ContractInfo<T>>::new(&address, 0u32.into(), code_hash)
644							.inspect_err(|err| {
645								log::error!(target: LOG_TARGET, "Failed to create ContractInfo for {address:?}: {err:?}");
646							})
647						else {
648							continue;
649						};
650
651						AccountInfoOf::<T>::insert(
652							address,
653							AccountInfo { account_type: info.clone().into(), dust },
654						);
655
656						<PristineCode<T>>::insert(blob.code_hash(), code);
657						<CodeInfoOf<T>>::insert(blob.code_hash(), blob.code_info().clone());
658						for (k, v) in storage {
659							let _ = info.write(&Key::from_fixed(k.0), Some(v.0.to_vec()), None, false).inspect_err(|err| {
660								log::error!(target: LOG_TARGET, "Failed to write genesis storage for {address:?} at key {k:?}: {err:?}");
661							});
662						}
663					},
664				}
665			}
666		}
667	}
668
669	#[pallet::hooks]
670	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
671		fn on_initialize(_block: BlockNumberFor<T>) -> Weight {
672			// Warm up the pallet account.
673			System::<T>::account_exists(&Pallet::<T>::account_id());
674			return T::DbWeight::get().reads(1)
675		}
676		fn on_idle(_block: BlockNumberFor<T>, limit: Weight) -> Weight {
677			let mut meter = WeightMeter::with_limit(limit);
678			ContractInfo::<T>::process_deletion_queue_batch(&mut meter);
679			meter.consumed()
680		}
681
682		fn integrity_test() {
683			assert!(T::ChainId::get() > 0, "ChainId must be greater than 0");
684
685			// The memory available in the block building runtime
686			let max_runtime_mem: u32 = T::RuntimeMemory::get();
687
688			// We only allow 50% of the runtime memory to be utilized by the contracts call
689			// stack, keeping the rest for other facilities, such as PoV, etc.
690			const TOTAL_MEMORY_DEVIDER: u32 = 2;
691
692			// Check that the configured memory limits fit into runtime memory.
693			//
694			// Dynamic allocations are not available, yet. Hence they are not taken into
695			// consideration here.
696			let memory_left = i64::from(max_runtime_mem)
697				.saturating_div(TOTAL_MEMORY_DEVIDER.into())
698				.saturating_sub(limits::MEMORY_REQUIRED.into());
699
700			log::debug!(target: LOG_TARGET, "Integrity check: memory_left={} KB", memory_left / 1024);
701
702			assert!(
703				memory_left >= 0,
704				"Runtime does not have enough memory for current limits. Additional runtime memory required: {} KB",
705				memory_left.saturating_mul(TOTAL_MEMORY_DEVIDER.into()).abs() / 1024
706			);
707
708			// Validators are configured to be able to use more memory than block builders. This is
709			// because in addition to `max_runtime_mem` they need to hold additional data in
710			// memory: PoV in multiple copies (1x encoded + 2x decoded) and all storage which
711			// includes emitted events. The assumption is that storage/events size
712			// can be a maximum of half of the validator runtime memory - max_runtime_mem.
713			let max_block_ref_time = T::BlockWeights::get()
714				.get(DispatchClass::Normal)
715				.max_total
716				.unwrap_or_else(|| T::BlockWeights::get().max_block)
717				.ref_time();
718			let max_payload_size = limits::PAYLOAD_BYTES;
719			let max_key_size =
720				Key::try_from_var(alloc::vec![0u8; limits::STORAGE_KEY_BYTES as usize])
721					.expect("Key of maximal size shall be created")
722					.hash()
723					.len() as u32;
724
725			let max_immutable_key_size = T::AccountId::max_encoded_len() as u32;
726			let max_immutable_size: u32 = ((max_block_ref_time /
727				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetImmutableData(
728					limits::IMMUTABLE_BYTES,
729				))
730				.ref_time()))
731			.saturating_mul(limits::IMMUTABLE_BYTES.saturating_add(max_immutable_key_size) as u64))
732			.try_into()
733			.expect("Immutable data size too big");
734
735			// We can use storage to store items using the available block ref_time with the
736			// `set_storage` host function.
737			let max_storage_size: u32 = ((max_block_ref_time /
738				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetStorage {
739					new_bytes: max_payload_size,
740					old_bytes: 0,
741				})
742				.ref_time()))
743			.saturating_mul(max_payload_size.saturating_add(max_key_size) as u64))
744			.saturating_add(max_immutable_size.into())
745			.try_into()
746			.expect("Storage size too big");
747
748			let max_pvf_mem: u32 = T::PVFMemory::get();
749			let storage_size_limit = max_pvf_mem.saturating_sub(max_runtime_mem) / 2;
750
751			assert!(
752				max_storage_size < storage_size_limit,
753				"Maximal storage size {} exceeds the storage limit {}",
754				max_storage_size,
755				storage_size_limit
756			);
757
758			// We can use storage to store events using the available block ref_time with the
759			// `deposit_event` host function. The overhead of stored events, which is around 100B,
760			// is not taken into account to simplify calculations, as it does not change much.
761			let max_events_size: u32 = ((max_block_ref_time /
762				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::DepositEvent {
763					num_topic: 0,
764					len: max_payload_size,
765				})
766				.saturating_add(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::HostFn))
767				.ref_time()))
768			.saturating_mul(max_payload_size as u64))
769			.try_into()
770			.expect("Events size too big");
771
772			assert!(
773				max_events_size < storage_size_limit,
774				"Maximal events size {} exceeds the events limit {}",
775				max_events_size,
776				storage_size_limit
777			);
778		}
779	}
780
781	#[pallet::call]
782	impl<T: Config> Pallet<T>
783	where
784		BalanceOf<T>: Into<U256> + TryFrom<U256>,
785		MomentOf<T>: Into<U256>,
786		T::Hash: frame_support::traits::IsType<H256>,
787	{
788		/// A raw EVM transaction, typically dispatched by an Ethereum JSON-RPC server.
789		///
790		/// # Parameters
791		///
792		/// * `payload`: The encoded [`crate::evm::TransactionSigned`].
793		/// * `gas_limit`: The gas limit enforced during contract execution.
794		/// * `storage_deposit_limit`: The maximum balance that can be charged to the caller for
795		///   storage usage.
796		///
797		/// # Note
798		///
799		/// This call cannot be dispatched directly; attempting to do so will result in a failed
800		/// transaction. It serves as a wrapper for an Ethereum transaction. When submitted, the
801		/// runtime converts it into a [`sp_runtime::generic::CheckedExtrinsic`] by recovering the
802		/// signer and validating the transaction.
803		#[allow(unused_variables)]
804		#[pallet::call_index(0)]
805		#[pallet::weight(Weight::MAX)]
806		pub fn eth_transact(origin: OriginFor<T>, payload: Vec<u8>) -> DispatchResultWithPostInfo {
807			Err(frame_system::Error::CallFiltered::<T>.into())
808		}
809
810		/// Makes a call to an account, optionally transferring some balance.
811		///
812		/// # Parameters
813		///
814		/// * `dest`: Address of the contract to call.
815		/// * `value`: The balance to transfer from the `origin` to `dest`.
816		/// * `gas_limit`: The gas limit enforced when executing the constructor.
817		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged from the
818		///   caller to pay for the storage consumed.
819		/// * `data`: The input data to pass to the contract.
820		///
821		/// * If the account is a smart-contract account, the associated code will be
822		/// executed and any value will be transferred.
823		/// * If the account is a regular account, any value will be transferred.
824		/// * If no account exists and the call value is not less than `existential_deposit`,
825		/// a regular account will be created and any value will be transferred.
826		#[pallet::call_index(1)]
827		#[pallet::weight(T::WeightInfo::call().saturating_add(*gas_limit))]
828		pub fn call(
829			origin: OriginFor<T>,
830			dest: H160,
831			#[pallet::compact] value: BalanceOf<T>,
832			gas_limit: Weight,
833			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
834			data: Vec<u8>,
835		) -> DispatchResultWithPostInfo {
836			let mut output = Self::bare_call(
837				origin,
838				dest,
839				Pallet::<T>::convert_native_to_evm(value),
840				gas_limit,
841				DepositLimit::Balance(storage_deposit_limit),
842				data,
843			);
844
845			if let Ok(return_value) = &output.result {
846				if return_value.did_revert() {
847					output.result = Err(<Error<T>>::ContractReverted.into());
848				}
849			}
850			dispatch_result(output.result, output.gas_consumed, T::WeightInfo::call())
851		}
852
853		/// Instantiates a contract from a previously deployed vm binary.
854		///
855		/// This function is identical to [`Self::instantiate_with_code`] but without the
856		/// code deployment step. Instead, the `code_hash` of an on-chain deployed vm binary
857		/// must be supplied.
858		#[pallet::call_index(2)]
859		#[pallet::weight(
860			T::WeightInfo::instantiate(data.len() as u32).saturating_add(*gas_limit)
861		)]
862		pub fn instantiate(
863			origin: OriginFor<T>,
864			#[pallet::compact] value: BalanceOf<T>,
865			gas_limit: Weight,
866			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
867			code_hash: sp_core::H256,
868			data: Vec<u8>,
869			salt: Option<[u8; 32]>,
870		) -> DispatchResultWithPostInfo {
871			let data_len = data.len() as u32;
872			let mut output = Self::bare_instantiate(
873				origin,
874				Pallet::<T>::convert_native_to_evm(value),
875				gas_limit,
876				DepositLimit::Balance(storage_deposit_limit),
877				Code::Existing(code_hash),
878				data,
879				salt,
880				BumpNonce::Yes,
881			);
882			if let Ok(retval) = &output.result {
883				if retval.result.did_revert() {
884					output.result = Err(<Error<T>>::ContractReverted.into());
885				}
886			}
887			dispatch_result(
888				output.result.map(|result| result.result),
889				output.gas_consumed,
890				T::WeightInfo::instantiate(data_len),
891			)
892		}
893
894		/// Instantiates a new contract from the supplied `code` optionally transferring
895		/// some balance.
896		///
897		/// This dispatchable has the same effect as calling [`Self::upload_code`] +
898		/// [`Self::instantiate`]. Bundling them together provides efficiency gains. Please
899		/// also check the documentation of [`Self::upload_code`].
900		///
901		/// # Parameters
902		///
903		/// * `value`: The balance to transfer from the `origin` to the newly created contract.
904		/// * `gas_limit`: The gas limit enforced when executing the constructor.
905		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved
906		///   from the caller to pay for the storage consumed.
907		/// * `code`: The contract code to deploy in raw bytes.
908		/// * `data`: The input data to pass to the contract constructor.
909		/// * `salt`: Used for the address derivation. If `Some` is supplied then `CREATE2`
910		/// 	semantics are used. If `None` then `CRATE1` is used.
911		///
912		///
913		/// Instantiation is executed as follows:
914		///
915		/// - The supplied `code` is deployed, and a `code_hash` is created for that code.
916		/// - If the `code_hash` already exists on the chain the underlying `code` will be shared.
917		/// - The destination address is computed based on the sender, code_hash and the salt.
918		/// - The smart-contract account is created at the computed address.
919		/// - The `value` is transferred to the new account.
920		/// - The `deploy` function is executed in the context of the newly-created account.
921		#[pallet::call_index(3)]
922		#[pallet::weight(
923			T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32)
924			.saturating_add(*gas_limit)
925		)]
926		pub fn instantiate_with_code(
927			origin: OriginFor<T>,
928			#[pallet::compact] value: BalanceOf<T>,
929			gas_limit: Weight,
930			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
931			code: Vec<u8>,
932			data: Vec<u8>,
933			salt: Option<[u8; 32]>,
934		) -> DispatchResultWithPostInfo {
935			let code_len = code.len() as u32;
936			let data_len = data.len() as u32;
937			let mut output = Self::bare_instantiate(
938				origin,
939				Pallet::<T>::convert_native_to_evm(value),
940				gas_limit,
941				DepositLimit::Balance(storage_deposit_limit),
942				Code::Upload(code),
943				data,
944				salt,
945				BumpNonce::Yes,
946			);
947			if let Ok(retval) = &output.result {
948				if retval.result.did_revert() {
949					output.result = Err(<Error<T>>::ContractReverted.into());
950				}
951			}
952			dispatch_result(
953				output.result.map(|result| result.result),
954				output.gas_consumed,
955				T::WeightInfo::instantiate_with_code(code_len, data_len),
956			)
957		}
958
959		/// Same as [`Self::instantiate_with_code`], but intended to be dispatched **only**
960		/// by an EVM transaction through the EVM compatibility layer.
961		///
962		/// Calling this dispatchable ensures that the origin's nonce is bumped only once,
963		/// via the `CheckNonce` transaction extension. In contrast, [`Self::instantiate_with_code`]
964		/// also bumps the nonce after contract instantiation, since it may be invoked multiple
965		/// times within a batch call transaction.
966		#[pallet::call_index(10)]
967		#[pallet::weight(
968			T::WeightInfo::eth_instantiate_with_code(code.len() as u32, data.len() as u32, Pallet::<T>::has_dust(*value).into())
969			.saturating_add(*gas_limit)
970		)]
971		pub fn eth_instantiate_with_code(
972			origin: OriginFor<T>,
973			value: U256,
974			gas_limit: Weight,
975			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
976			code: Vec<u8>,
977			data: Vec<u8>,
978		) -> DispatchResultWithPostInfo {
979			let code_len = code.len() as u32;
980			let data_len = data.len() as u32;
981			let mut output = Self::bare_instantiate(
982				origin,
983				value,
984				gas_limit,
985				DepositLimit::Balance(storage_deposit_limit),
986				Code::Upload(code),
987				data,
988				None,
989				BumpNonce::No,
990			);
991
992			if let Ok(retval) = &output.result {
993				if retval.result.did_revert() {
994					output.result = Err(<Error<T>>::ContractReverted.into());
995				}
996			}
997			dispatch_result(
998				output.result.map(|result| result.result),
999				output.gas_consumed,
1000				T::WeightInfo::eth_instantiate_with_code(
1001					code_len,
1002					data_len,
1003					Pallet::<T>::has_dust(value).into(),
1004				),
1005			)
1006		}
1007
1008		/// Same as [`Self::call`], but intended to be dispatched **only**
1009		/// by an EVM transaction through the EVM compatibility layer.
1010		#[pallet::call_index(11)]
1011		#[pallet::weight(T::WeightInfo::eth_call(Pallet::<T>::has_dust(*value).into()).saturating_add(*gas_limit))]
1012		pub fn eth_call(
1013			origin: OriginFor<T>,
1014			dest: H160,
1015			value: U256,
1016			gas_limit: Weight,
1017			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
1018			data: Vec<u8>,
1019		) -> DispatchResultWithPostInfo {
1020			let mut output = Self::bare_call(
1021				origin,
1022				dest,
1023				value,
1024				gas_limit,
1025				DepositLimit::Balance(storage_deposit_limit),
1026				data,
1027			);
1028
1029			if let Ok(return_value) = &output.result {
1030				if return_value.did_revert() {
1031					output.result = Err(<Error<T>>::ContractReverted.into());
1032				}
1033			}
1034			dispatch_result(
1035				output.result,
1036				output.gas_consumed,
1037				T::WeightInfo::eth_call(Pallet::<T>::has_dust(value).into()),
1038			)
1039		}
1040
1041		/// Upload new `code` without instantiating a contract from it.
1042		///
1043		/// If the code does not already exist a deposit is reserved from the caller
1044		/// The size of the reserve depends on the size of the supplied `code`.
1045		///
1046		/// # Note
1047		///
1048		/// Anyone can instantiate a contract from any uploaded code and thus prevent its removal.
1049		/// To avoid this situation a constructor could employ access control so that it can
1050		/// only be instantiated by permissioned entities. The same is true when uploading
1051		/// through [`Self::instantiate_with_code`].
1052		///
1053		/// If the refcount of the code reaches zero after terminating the last contract that
1054		/// references this code, the code will be removed automatically.
1055		#[pallet::call_index(4)]
1056		#[pallet::weight(T::WeightInfo::upload_code(code.len() as u32))]
1057		pub fn upload_code(
1058			origin: OriginFor<T>,
1059			code: Vec<u8>,
1060			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
1061		) -> DispatchResult {
1062			Self::bare_upload_code(origin, code, storage_deposit_limit).map(|_| ())
1063		}
1064
1065		/// Remove the code stored under `code_hash` and refund the deposit to its owner.
1066		///
1067		/// A code can only be removed by its original uploader (its owner) and only if it is
1068		/// not used by any contract.
1069		#[pallet::call_index(5)]
1070		#[pallet::weight(T::WeightInfo::remove_code())]
1071		pub fn remove_code(
1072			origin: OriginFor<T>,
1073			code_hash: sp_core::H256,
1074		) -> DispatchResultWithPostInfo {
1075			let origin = ensure_signed(origin)?;
1076			<ContractBlob<T>>::remove(&origin, code_hash)?;
1077			// we waive the fee because removing unused code is beneficial
1078			Ok(Pays::No.into())
1079		}
1080
1081		/// Privileged function that changes the code of an existing contract.
1082		///
1083		/// This takes care of updating refcounts and all other necessary operations. Returns
1084		/// an error if either the `code_hash` or `dest` do not exist.
1085		///
1086		/// # Note
1087		///
1088		/// This does **not** change the address of the contract in question. This means
1089		/// that the contract address is no longer derived from its code hash after calling
1090		/// this dispatchable.
1091		#[pallet::call_index(6)]
1092		#[pallet::weight(T::WeightInfo::set_code())]
1093		pub fn set_code(
1094			origin: OriginFor<T>,
1095			dest: H160,
1096			code_hash: sp_core::H256,
1097		) -> DispatchResult {
1098			ensure_root(origin)?;
1099			<AccountInfoOf<T>>::try_mutate(&dest, |account| {
1100				let Some(account) = account else {
1101					return Err(<Error<T>>::ContractNotFound.into());
1102				};
1103
1104				let AccountType::Contract(ref mut contract) = account.account_type else {
1105					return Err(<Error<T>>::ContractNotFound.into());
1106				};
1107
1108				<CodeInfo<T>>::increment_refcount(code_hash)?;
1109				let _ = <CodeInfo<T>>::decrement_refcount(contract.code_hash)?;
1110				contract.code_hash = code_hash;
1111
1112				Ok(())
1113			})
1114		}
1115
1116		/// Register the callers account id so that it can be used in contract interactions.
1117		///
1118		/// This will error if the origin is already mapped or is a eth native `Address20`. It will
1119		/// take a deposit that can be released by calling [`Self::unmap_account`].
1120		#[pallet::call_index(7)]
1121		#[pallet::weight(T::WeightInfo::map_account())]
1122		pub fn map_account(origin: OriginFor<T>) -> DispatchResult {
1123			let origin = ensure_signed(origin)?;
1124			T::AddressMapper::map(&origin)
1125		}
1126
1127		/// Unregister the callers account id in order to free the deposit.
1128		///
1129		/// There is no reason to ever call this function other than freeing up the deposit.
1130		/// This is only useful when the account should no longer be used.
1131		#[pallet::call_index(8)]
1132		#[pallet::weight(T::WeightInfo::unmap_account())]
1133		pub fn unmap_account(origin: OriginFor<T>) -> DispatchResult {
1134			let origin = ensure_signed(origin)?;
1135			T::AddressMapper::unmap(&origin)
1136		}
1137
1138		/// Dispatch an `call` with the origin set to the callers fallback address.
1139		///
1140		/// Every `AccountId32` can control its corresponding fallback account. The fallback account
1141		/// is the `AccountId20` with the last 12 bytes set to `0xEE`. This is essentially a
1142		/// recovery function in case an `AccountId20` was used without creating a mapping first.
1143		#[pallet::call_index(9)]
1144		#[pallet::weight({
1145			let dispatch_info = call.get_dispatch_info();
1146			(
1147				T::WeightInfo::dispatch_as_fallback_account().saturating_add(dispatch_info.call_weight),
1148				dispatch_info.class
1149			)
1150		})]
1151		pub fn dispatch_as_fallback_account(
1152			origin: OriginFor<T>,
1153			call: Box<<T as Config>::RuntimeCall>,
1154		) -> DispatchResultWithPostInfo {
1155			let origin = ensure_signed(origin)?;
1156			let unmapped_account =
1157				T::AddressMapper::to_fallback_account_id(&T::AddressMapper::to_address(&origin));
1158			call.dispatch(RawOrigin::Signed(unmapped_account).into())
1159		}
1160	}
1161}
1162
1163/// Create a dispatch result reflecting the amount of consumed gas.
1164fn dispatch_result<R>(
1165	result: Result<R, DispatchError>,
1166	gas_consumed: Weight,
1167	base_weight: Weight,
1168) -> DispatchResultWithPostInfo {
1169	let post_info = PostDispatchInfo {
1170		actual_weight: Some(gas_consumed.saturating_add(base_weight)),
1171		pays_fee: Default::default(),
1172	};
1173
1174	result
1175		.map(|_| post_info)
1176		.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e })
1177}
1178
1179impl<T: Config> Pallet<T>
1180where
1181	BalanceOf<T>: Into<U256> + TryFrom<U256> + Bounded,
1182	MomentOf<T>: Into<U256>,
1183	T::Hash: frame_support::traits::IsType<H256>,
1184{
1185	/// A generalized version of [`Self::call`].
1186	///
1187	/// Identical to [`Self::call`] but tailored towards being called by other code within the
1188	/// runtime as opposed to from an extrinsic. It returns more information and allows the
1189	/// enablement of features that are not suitable for an extrinsic (debugging, event
1190	/// collection).
1191	pub fn bare_call(
1192		origin: OriginFor<T>,
1193		dest: H160,
1194		evm_value: U256,
1195		gas_limit: Weight,
1196		storage_deposit_limit: DepositLimit<BalanceOf<T>>,
1197		data: Vec<u8>,
1198	) -> ContractResult<ExecReturnValue, BalanceOf<T>> {
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		let mut gas_meter = GasMeter::new(gas_limit);
1257		let mut storage_deposit = Default::default();
1258		let unchecked_deposit_limit = storage_deposit_limit.is_unchecked();
1259		let mut storage_deposit_limit = storage_deposit_limit.limit();
1260		let try_instantiate = || {
1261			let instantiate_account = T::InstantiateOrigin::ensure_origin(origin.clone())?;
1262
1263			if_tracing(|t| t.instantiate_code(&code, salt.as_ref()));
1264			let (executable, upload_deposit) = match code {
1265				Code::Upload(code) if code.starts_with(&polkavm_common::program::BLOB_MAGIC) => {
1266					let upload_account = T::UploadOrigin::ensure_origin(origin)?;
1267					let (executable, upload_deposit) = Self::try_upload_pvm_code(
1268						upload_account,
1269						code,
1270						storage_deposit_limit,
1271						unchecked_deposit_limit,
1272					)?;
1273					storage_deposit_limit.saturating_reduce(upload_deposit);
1274					(executable, upload_deposit)
1275				},
1276				Code::Upload(code) =>
1277					if T::AllowEVMBytecode::get() {
1278						let origin = T::UploadOrigin::ensure_origin(origin)?;
1279						let executable = ContractBlob::from_evm_init_code(code, origin)?;
1280						(executable, Default::default())
1281					} else {
1282						return Err(<Error<T>>::CodeRejected.into())
1283					},
1284				Code::Existing(code_hash) =>
1285					(ContractBlob::from_storage(code_hash, &mut gas_meter)?, Default::default()),
1286			};
1287			let instantiate_origin = Origin::from_account_id(instantiate_account.clone());
1288			let mut storage_meter = StorageMeter::new(storage_deposit_limit);
1289			let result = ExecStack::<T, ContractBlob<T>>::run_instantiate(
1290				instantiate_account,
1291				executable,
1292				&mut gas_meter,
1293				&mut storage_meter,
1294				evm_value,
1295				data,
1296				salt.as_ref(),
1297				unchecked_deposit_limit,
1298				bump_nonce,
1299			);
1300			storage_deposit = storage_meter
1301				.try_into_deposit(&instantiate_origin, unchecked_deposit_limit)?
1302				.saturating_add(&StorageDeposit::Charge(upload_deposit));
1303			result
1304		};
1305		let output = Self::run_guarded(try_instantiate);
1306		ContractResult {
1307			result: output
1308				.map(|(addr, result)| InstantiateReturnValue { result, addr })
1309				.map_err(|e| e.error),
1310			gas_consumed: gas_meter.gas_consumed(),
1311			gas_required: gas_meter.gas_required(),
1312			storage_deposit,
1313		}
1314	}
1315
1316	/// Dry-run Ethereum calls.
1317	///
1318	/// # Parameters
1319	///
1320	/// - `tx`: The Ethereum transaction to simulate.
1321	/// - `gas_limit`: The gas limit enforced during contract execution.
1322	/// - `tx_fee`: A function that returns the fee for the computed eth_transact and actual
1323	/// dispatched call
1324	pub fn dry_run_eth_transact(
1325		mut tx: GenericTransaction,
1326		gas_limit: Weight,
1327		tx_fee: impl Fn(<T as Config>::RuntimeCall, <T as Config>::RuntimeCall) -> BalanceOf<T>,
1328	) -> Result<EthTransactInfo<BalanceOf<T>>, EthTransactError>
1329	where
1330		<T as frame_system::Config>::RuntimeCall:
1331			Dispatchable<Info = frame_support::dispatch::DispatchInfo>,
1332		T: pallet_transaction_payment::Config,
1333		OnChargeTransactionBalanceOf<T>: Into<BalanceOf<T>>,
1334		<T as Config>::RuntimeCall: From<crate::Call<T>>,
1335		<T as Config>::RuntimeCall: Encode,
1336		T::Nonce: Into<U256>,
1337		T::Hash: frame_support::traits::IsType<H256>,
1338	{
1339		log::trace!(target: LOG_TARGET, "dry_run_eth_transact: {tx:?} gas_limit: {gas_limit:?}");
1340
1341		let from = tx.from.unwrap_or_default();
1342		let origin = T::AddressMapper::to_account_id(&from);
1343		Self::prepare_dry_run(&origin);
1344
1345		let storage_deposit_limit = if tx.gas.is_some() {
1346			DepositLimit::Balance(BalanceOf::<T>::max_value())
1347		} else {
1348			DepositLimit::UnsafeOnlyForDryRun
1349		};
1350
1351		if tx.nonce.is_none() {
1352			tx.nonce = Some(<System<T>>::account_nonce(&origin).into());
1353		}
1354		if tx.chain_id.is_none() {
1355			tx.chain_id = Some(T::ChainId::get().into());
1356		}
1357		if tx.gas_price.is_none() {
1358			tx.gas_price = Some(GAS_PRICE.into());
1359		}
1360		if tx.max_priority_fee_per_gas.is_none() {
1361			tx.max_priority_fee_per_gas = Some(GAS_PRICE.into());
1362		}
1363		if tx.max_fee_per_gas.is_none() {
1364			tx.max_fee_per_gas = Some(GAS_PRICE.into());
1365		}
1366		if tx.gas.is_none() {
1367			tx.gas = Some(Self::evm_block_gas_limit());
1368		}
1369		if tx.r#type.is_none() {
1370			tx.r#type = Some(TYPE_EIP1559.into());
1371		}
1372
1373		// Convert the value to the native balance type.
1374		let value = tx.value.unwrap_or_default();
1375		let input = tx.input.clone().to_vec();
1376
1377		let extract_error = |err| {
1378			if err == Error::<T>::TransferFailed.into() ||
1379				err == Error::<T>::StorageDepositNotEnoughFunds.into() ||
1380				err == Error::<T>::StorageDepositLimitExhausted.into()
1381			{
1382				let balance = Self::evm_balance(&from);
1383				return Err(EthTransactError::Message(format!(
1384					"insufficient funds for gas * price + value: address {from:?} have {balance} (supplied gas {})",
1385					tx.gas.unwrap_or_default()
1386				)));
1387			}
1388
1389			return Err(EthTransactError::Message(format!(
1390				"Failed to instantiate contract: {err:?}"
1391			)));
1392		};
1393
1394		// Dry run the call
1395		let (mut result, dispatch_call) = match tx.to {
1396			// A contract call.
1397			Some(dest) => {
1398				if dest == RUNTIME_PALLETS_ADDR {
1399					let Ok(dispatch_call) = <T as Config>::RuntimeCall::decode(&mut &input[..])
1400					else {
1401						return Err(EthTransactError::Message(format!(
1402							"Failed to decode pallet-call {input:?}"
1403						)));
1404					};
1405
1406					if let Err(err) =
1407						dispatch_call.clone().dispatch(RawOrigin::Signed(origin).into())
1408					{
1409						return Err(EthTransactError::Message(format!(
1410							"Failed to dispatch call: {err:?}"
1411						)));
1412					};
1413
1414					let result = EthTransactInfo {
1415						gas_required: dispatch_call.get_dispatch_info().total_weight(),
1416						..Default::default()
1417					};
1418
1419					(result, dispatch_call)
1420				} else {
1421					// Dry run the call.
1422					let result = crate::Pallet::<T>::bare_call(
1423						T::RuntimeOrigin::signed(origin),
1424						dest,
1425						value,
1426						gas_limit,
1427						storage_deposit_limit,
1428						input.clone(),
1429					);
1430
1431					let data = match result.result {
1432						Ok(return_value) => {
1433							if return_value.did_revert() {
1434								return Err(EthTransactError::Data(return_value.data));
1435							}
1436							return_value.data
1437						},
1438						Err(err) => {
1439							log::debug!(target: LOG_TARGET, "Failed to execute call: {err:?}");
1440							return extract_error(err);
1441						},
1442					};
1443
1444					let result = EthTransactInfo {
1445						gas_required: result.gas_required,
1446						storage_deposit: result.storage_deposit.charge_or_zero(),
1447						data,
1448						eth_gas: Default::default(),
1449					};
1450
1451					let (gas_limit, storage_deposit_limit) = T::EthGasEncoder::as_encoded_values(
1452						result.gas_required,
1453						result.storage_deposit,
1454					);
1455					let dispatch_call: <T as Config>::RuntimeCall = crate::Call::<T>::eth_call {
1456						dest,
1457						value,
1458						gas_limit,
1459						storage_deposit_limit,
1460						data: input.clone(),
1461					}
1462					.into();
1463					(result, dispatch_call)
1464				}
1465			},
1466			// A contract deployment
1467			None => {
1468				// Extract code and data from the input.
1469				let (code, data) = if input.starts_with(&polkavm_common::program::BLOB_MAGIC) {
1470					extract_code_and_data(&input).unwrap_or_else(|| (input, Default::default()))
1471				} else {
1472					(input, vec![])
1473				};
1474
1475				// Dry run the call.
1476				let result = crate::Pallet::<T>::bare_instantiate(
1477					T::RuntimeOrigin::signed(origin),
1478					value,
1479					gas_limit,
1480					storage_deposit_limit,
1481					Code::Upload(code.clone()),
1482					data.clone(),
1483					None,
1484					BumpNonce::No,
1485				);
1486
1487				let returned_data = match result.result {
1488					Ok(return_value) => {
1489						if return_value.result.did_revert() {
1490							return Err(EthTransactError::Data(return_value.result.data));
1491						}
1492						return_value.result.data
1493					},
1494					Err(err) => {
1495						log::debug!(target: LOG_TARGET, "Failed to instantiate: {err:?}");
1496						return extract_error(err);
1497					},
1498				};
1499
1500				let result = EthTransactInfo {
1501					gas_required: result.gas_required,
1502					storage_deposit: result.storage_deposit.charge_or_zero(),
1503					data: returned_data,
1504					eth_gas: Default::default(),
1505				};
1506
1507				// Get the dispatch info of the call.
1508				let (gas_limit, storage_deposit_limit) = T::EthGasEncoder::as_encoded_values(
1509					result.gas_required,
1510					result.storage_deposit,
1511				);
1512				let dispatch_call: <T as Config>::RuntimeCall =
1513					crate::Call::<T>::eth_instantiate_with_code {
1514						value,
1515						gas_limit,
1516						storage_deposit_limit,
1517						code,
1518						data,
1519					}
1520					.into();
1521				(result, dispatch_call)
1522			},
1523		};
1524
1525		let Ok(unsigned_tx) = tx.clone().try_into_unsigned() else {
1526			return Err(EthTransactError::Message("Invalid transaction".into()));
1527		};
1528
1529		let eth_transact_call =
1530			crate::Call::<T>::eth_transact { payload: unsigned_tx.dummy_signed_payload() };
1531		let fee = tx_fee(eth_transact_call.into(), dispatch_call);
1532		let raw_gas = Self::evm_fee_to_gas(fee);
1533		let eth_gas =
1534			T::EthGasEncoder::encode(raw_gas, result.gas_required, result.storage_deposit);
1535
1536		log::trace!(target: LOG_TARGET, "bare_eth_call: raw_gas: {raw_gas:?} eth_gas: {eth_gas:?}");
1537		result.eth_gas = eth_gas;
1538		Ok(result)
1539	}
1540
1541	/// Get the balance with EVM decimals of the given `address`.
1542	pub fn evm_balance(address: &H160) -> U256 {
1543		let balance = AccountInfo::<T>::balance((*address).into());
1544		Self::convert_native_to_evm(balance)
1545	}
1546
1547	/// Get the nonce for the given `address`.
1548	pub fn evm_nonce(address: &H160) -> u32
1549	where
1550		T::Nonce: Into<u32>,
1551	{
1552		let account = T::AddressMapper::to_account_id(&address);
1553		System::<T>::account_nonce(account).into()
1554	}
1555
1556	/// Convert a substrate fee into a gas value, using the fixed `GAS_PRICE`.
1557	/// The gas is calculated as `fee / GAS_PRICE`, rounded up to the nearest integer.
1558	pub fn evm_fee_to_gas(fee: BalanceOf<T>) -> U256 {
1559		let fee = Self::convert_native_to_evm(fee);
1560		let gas_price = GAS_PRICE.into();
1561		let (quotient, remainder) = fee.div_mod(gas_price);
1562		if remainder.is_zero() {
1563			quotient
1564		} else {
1565			quotient + U256::one()
1566		}
1567	}
1568
1569	/// Convert a gas value into a substrate fee
1570	fn evm_gas_to_fee(gas: U256, gas_price: U256) -> Result<BalanceOf<T>, Error<T>> {
1571		let fee = gas.saturating_mul(gas_price);
1572		let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(fee)?;
1573		Ok(value.into_rounded_balance())
1574	}
1575
1576	/// Convert a weight to a gas value.
1577	pub fn evm_gas_from_weight(weight: Weight) -> U256 {
1578		let fee = T::WeightPrice::convert(weight);
1579		Self::evm_fee_to_gas(fee)
1580	}
1581
1582	/// Get the block gas limit.
1583	pub fn evm_block_gas_limit() -> U256
1584	where
1585		<T as frame_system::Config>::RuntimeCall:
1586			Dispatchable<Info = frame_support::dispatch::DispatchInfo>,
1587		T: pallet_transaction_payment::Config,
1588		OnChargeTransactionBalanceOf<T>: Into<BalanceOf<T>>,
1589	{
1590		let max_block_weight = T::BlockWeights::get()
1591			.get(DispatchClass::Normal)
1592			.max_total
1593			.unwrap_or_else(|| T::BlockWeights::get().max_block);
1594
1595		let length_fee = pallet_transaction_payment::Pallet::<T>::length_to_fee(
1596			5 * 1024 * 1024, // 5 MB
1597		);
1598
1599		Self::evm_gas_from_weight(max_block_weight)
1600			.saturating_add(Self::evm_fee_to_gas(length_fee.into()))
1601	}
1602
1603	/// Get the gas price.
1604	pub fn evm_gas_price() -> U256 {
1605		GAS_PRICE.into()
1606	}
1607
1608	/// Build an EVM tracer from the given tracer type.
1609	pub fn evm_tracer(tracer_type: TracerType) -> Tracer<T>
1610	where
1611		T::Nonce: Into<u32>,
1612	{
1613		match tracer_type {
1614			TracerType::CallTracer(config) => CallTracer::new(
1615				config.unwrap_or_default(),
1616				Self::evm_gas_from_weight as fn(Weight) -> U256,
1617			)
1618			.into(),
1619			TracerType::PrestateTracer(config) =>
1620				PrestateTracer::new(config.unwrap_or_default()).into(),
1621		}
1622	}
1623
1624	/// A generalized version of [`Self::upload_code`].
1625	///
1626	/// It is identical to [`Self::upload_code`] and only differs in the information it returns.
1627	pub fn bare_upload_code(
1628		origin: OriginFor<T>,
1629		code: Vec<u8>,
1630		storage_deposit_limit: BalanceOf<T>,
1631	) -> CodeUploadResult<BalanceOf<T>> {
1632		let origin = T::UploadOrigin::ensure_origin(origin)?;
1633		let (module, deposit) =
1634			Self::try_upload_pvm_code(origin, code, storage_deposit_limit, false)?;
1635		Ok(CodeUploadReturnValue { code_hash: *module.code_hash(), deposit })
1636	}
1637
1638	/// Query storage of a specified contract under a specified key.
1639	pub fn get_storage(address: H160, key: [u8; 32]) -> GetStorageResult {
1640		let contract_info =
1641			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
1642
1643		let maybe_value = contract_info.read(&Key::from_fixed(key));
1644		Ok(maybe_value)
1645	}
1646
1647	/// Query storage of a specified contract under a specified variable-sized key.
1648	pub fn get_storage_var_key(address: H160, key: Vec<u8>) -> GetStorageResult {
1649		let contract_info =
1650			AccountInfo::<T>::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?;
1651
1652		let maybe_value = contract_info.read(
1653			&Key::try_from_var(key)
1654				.map_err(|_| ContractAccessError::KeyDecodingFailed)?
1655				.into(),
1656		);
1657		Ok(maybe_value)
1658	}
1659
1660	/// Uploads new code and returns the Vm binary contract blob and deposit amount collected.
1661	fn try_upload_pvm_code(
1662		origin: T::AccountId,
1663		code: Vec<u8>,
1664		storage_deposit_limit: BalanceOf<T>,
1665		skip_transfer: bool,
1666	) -> Result<(ContractBlob<T>, BalanceOf<T>), DispatchError> {
1667		let mut module = ContractBlob::from_pvm_code(code, origin)?;
1668		let deposit = module.store_code(skip_transfer)?;
1669		ensure!(storage_deposit_limit >= deposit, <Error<T>>::StorageDepositLimitExhausted);
1670		Ok((module, deposit))
1671	}
1672
1673	/// Run the supplied function `f` if no other instance of this pallet is on the stack.
1674	fn run_guarded<R, F: FnOnce() -> Result<R, ExecError>>(f: F) -> Result<R, ExecError> {
1675		executing_contract::using_once(&mut false, || {
1676			executing_contract::with(|f| {
1677				// Fail if already entered contract execution
1678				if *f {
1679					return Err(())
1680				}
1681				// We are entering contract execution
1682				*f = true;
1683				Ok(())
1684			})
1685				.expect("Returns `Ok` if called within `using_once`. It is syntactically obvious that this is the case; qed")
1686				.map_err(|_| <Error<T>>::ReenteredPallet.into())
1687				.map(|_| f())
1688				.and_then(|r| r)
1689		})
1690	}
1691
1692	/// Convert a native balance to EVM balance.
1693	pub fn convert_native_to_evm(value: impl Into<BalanceWithDust<BalanceOf<T>>>) -> U256 {
1694		let (value, dust) = value.into().deconstruct();
1695		value
1696			.into()
1697			.saturating_mul(T::NativeToEthRatio::get().into())
1698			.saturating_add(dust.into())
1699	}
1700}
1701
1702impl<T: Config> Pallet<T> {
1703	/// Pallet account, used to hold funds for contracts upload deposit.
1704	pub fn account_id() -> T::AccountId {
1705		use frame_support::PalletId;
1706		use sp_runtime::traits::AccountIdConversion;
1707		PalletId(*b"py/reviv").into_account_truncating()
1708	}
1709
1710	/// Returns true if the evm value carries dust.
1711	fn has_dust(value: U256) -> bool {
1712		value % U256::from(<T>::NativeToEthRatio::get()) != U256::zero()
1713	}
1714
1715	/// Returns true if the evm value carries balance.
1716	fn has_balance(value: U256) -> bool {
1717		value >= U256::from(<T>::NativeToEthRatio::get())
1718	}
1719
1720	/// Return the existential deposit of [`Config::Currency`].
1721	fn min_balance() -> BalanceOf<T> {
1722		<T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
1723	}
1724
1725	/// Deposit a pallet revive event.
1726	fn deposit_event(event: Event<T>) {
1727		<frame_system::Pallet<T>>::deposit_event(<T as Config>::RuntimeEvent::from(event))
1728	}
1729
1730	/// The address of the validator that produced the current block.
1731	pub fn block_author() -> Option<H160> {
1732		use frame_support::traits::FindAuthor;
1733
1734		let digest = <frame_system::Pallet<T>>::digest();
1735		let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime());
1736
1737		let account_id = T::FindAuthor::find_author(pre_runtime_digests)?;
1738		Some(T::AddressMapper::to_address(&account_id))
1739	}
1740
1741	/// Returns the code at `address`.
1742	///
1743	/// This takes pre-compiles into account.
1744	pub fn code(address: &H160) -> Vec<u8> {
1745		use precompiles::{All, Precompiles};
1746		if let Some(code) = <All<T>>::code(address.as_fixed_bytes()) {
1747			return code.into()
1748		}
1749		AccountInfo::<T>::load_contract(&address)
1750			.and_then(|contract| <PristineCode<T>>::get(contract.code_hash))
1751			.map(|code| code.into())
1752			.unwrap_or_default()
1753	}
1754}
1755
1756/// The address used to call the runtime's pallets dispatchables
1757///
1758/// Note:
1759/// computed with PalletId(*b"py/paddr").into_account_truncating();
1760pub const RUNTIME_PALLETS_ADDR: H160 =
1761	H160(hex_literal::hex!("6d6f646c70792f70616464720000000000000000"));
1762
1763// Set up a global reference to the boolean flag used for the re-entrancy guard.
1764environmental!(executing_contract: bool);
1765
1766sp_api::decl_runtime_apis! {
1767	/// The API used to dry-run contract interactions.
1768	#[api_version(1)]
1769	pub trait ReviveApi<AccountId, Balance, Nonce, BlockNumber> where
1770		AccountId: Codec,
1771		Balance: Codec,
1772		Nonce: Codec,
1773		BlockNumber: Codec,
1774	{
1775		/// Returns the block gas limit.
1776		fn block_gas_limit() -> U256;
1777
1778		/// Returns the free balance of the given `[H160]` address, using EVM decimals.
1779		fn balance(address: H160) -> U256;
1780
1781		/// Returns the gas price.
1782		fn gas_price() -> U256;
1783
1784		/// Returns the nonce of the given `[H160]` address.
1785		fn nonce(address: H160) -> Nonce;
1786
1787		/// Perform a call from a specified account to a given contract.
1788		///
1789		/// See [`crate::Pallet::bare_call`].
1790		fn call(
1791			origin: AccountId,
1792			dest: H160,
1793			value: Balance,
1794			gas_limit: Option<Weight>,
1795			storage_deposit_limit: Option<Balance>,
1796			input_data: Vec<u8>,
1797		) -> ContractResult<ExecReturnValue, Balance>;
1798
1799		/// Instantiate a new contract.
1800		///
1801		/// See `[crate::Pallet::bare_instantiate]`.
1802		fn instantiate(
1803			origin: AccountId,
1804			value: Balance,
1805			gas_limit: Option<Weight>,
1806			storage_deposit_limit: Option<Balance>,
1807			code: Code,
1808			data: Vec<u8>,
1809			salt: Option<[u8; 32]>,
1810		) -> ContractResult<InstantiateReturnValue, Balance>;
1811
1812
1813		/// Perform an Ethereum call.
1814		///
1815		/// See [`crate::Pallet::dry_run_eth_transact`]
1816		fn eth_transact(tx: GenericTransaction) -> Result<EthTransactInfo<Balance>, EthTransactError>;
1817
1818		/// Upload new code without instantiating a contract from it.
1819		///
1820		/// See [`crate::Pallet::bare_upload_code`].
1821		fn upload_code(
1822			origin: AccountId,
1823			code: Vec<u8>,
1824			storage_deposit_limit: Option<Balance>,
1825		) -> CodeUploadResult<Balance>;
1826
1827		/// Query a given storage key in a given contract.
1828		///
1829		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
1830		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
1831		/// doesn't exist, or doesn't have a contract then `Err` is returned.
1832		fn get_storage(
1833			address: H160,
1834			key: [u8; 32],
1835		) -> GetStorageResult;
1836
1837		/// Query a given variable-sized storage key in a given contract.
1838		///
1839		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
1840		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
1841		/// doesn't exist, or doesn't have a contract then `Err` is returned.
1842		fn get_storage_var_key(
1843			address: H160,
1844			key: Vec<u8>,
1845		) -> GetStorageResult;
1846
1847		/// Traces the execution of an entire block and returns call traces.
1848		///
1849		/// This is intended to be called through `state_call` to replay the block from the
1850		/// parent block.
1851		///
1852		/// See eth-rpc `debug_traceBlockByNumber` for usage.
1853		fn trace_block(
1854			block: Block,
1855			config: TracerType
1856		) -> Vec<(u32, Trace)>;
1857
1858		/// Traces the execution of a specific transaction within a block.
1859		///
1860		/// This is intended to be called through `state_call` to replay the block from the
1861		/// parent hash up to the transaction.
1862		///
1863		/// See eth-rpc `debug_traceTransaction` for usage.
1864		fn trace_tx(
1865			block: Block,
1866			tx_index: u32,
1867			config: TracerType
1868		) -> Option<Trace>;
1869
1870		/// Dry run and return the trace of the given call.
1871		///
1872		/// See eth-rpc `debug_traceCall` for usage.
1873		fn trace_call(tx: GenericTransaction, config: TracerType) -> Result<Trace, EthTransactError>;
1874
1875		/// The address of the validator that produced the current block.
1876		fn block_author() -> Option<H160>;
1877
1878		/// Get the H160 address associated to this account id
1879		fn address(account_id: AccountId) -> H160;
1880
1881		/// The address used to call the runtime's pallets dispatchables
1882		fn runtime_pallets_address() -> H160;
1883
1884		/// The code at the specified address taking pre-compiles into account.
1885		fn code(address: H160) -> Vec<u8>;
1886	}
1887}
1888
1889/// This macro wraps substrate's `impl_runtime_apis!` and implements `pallet_revive` runtime APIs.
1890///
1891/// # Parameters
1892/// - `$Runtime`: The runtime type to implement the APIs for.
1893/// - `$Executive`: The Executive type of the runtime.
1894/// - `$EthExtra`: Type for additional Ethereum runtime extension.
1895/// - `$($rest:tt)*`: Remaining input to be forwarded to the underlying `impl_runtime_apis!`.
1896#[macro_export]
1897macro_rules! impl_runtime_apis_plus_revive {
1898	($Runtime: ty, $Executive: ty, $EthExtra: ty, $($rest:tt)*) => {
1899
1900		impl_runtime_apis! {
1901			$($rest)*
1902
1903			impl pallet_revive::ReviveApi<Block, AccountId, Balance, Nonce, BlockNumber> for $Runtime {
1904				fn balance(address: $crate::H160) -> $crate::U256 {
1905					$crate::Pallet::<Self>::evm_balance(&address)
1906				}
1907
1908				fn block_author() -> Option<$crate::H160> {
1909					$crate::Pallet::<Self>::block_author()
1910				}
1911
1912				fn block_gas_limit() -> $crate::U256 {
1913					$crate::Pallet::<Self>::evm_block_gas_limit()
1914				}
1915
1916				fn gas_price() -> $crate::U256 {
1917					$crate::Pallet::<Self>::evm_gas_price()
1918				}
1919
1920				fn nonce(address: $crate::H160) -> Nonce {
1921					use $crate::AddressMapper;
1922					let account = <Self as $crate::Config>::AddressMapper::to_account_id(&address);
1923					$crate::frame_system::Pallet::<Self>::account_nonce(account)
1924				}
1925
1926				fn address(account_id: AccountId) -> $crate::H160 {
1927					use $crate::AddressMapper;
1928					<Self as $crate::Config>::AddressMapper::to_address(&account_id)
1929				}
1930
1931				fn eth_transact(
1932					tx: $crate::evm::GenericTransaction,
1933				) -> Result<$crate::EthTransactInfo<Balance>, $crate::EthTransactError> {
1934					use $crate::{
1935						codec::Encode, evm::runtime::EthExtra, frame_support::traits::Get,
1936						sp_runtime::traits::TransactionExtension,
1937						sp_runtime::traits::Block as BlockT
1938					};
1939
1940					let tx_fee = |call: <Self as $crate::frame_system::Config>::RuntimeCall, dispatch_call: <Self as $crate::frame_system::Config>::RuntimeCall| {
1941						use $crate::frame_support::dispatch::GetDispatchInfo;
1942
1943						// Get the dispatch info of the actual call dispatched
1944						let mut dispatch_info = dispatch_call.get_dispatch_info();
1945						dispatch_info.extension_weight =
1946							<$EthExtra>::get_eth_extension(0, 0u32.into()).weight(&dispatch_call);
1947
1948						// Build the extrinsic
1949						let uxt: <Block as BlockT>::Extrinsic =
1950							$crate::sp_runtime::generic::UncheckedExtrinsic::new_bare(call).into();
1951
1952						// Compute the fee of the extrinsic
1953						$crate::pallet_transaction_payment::Pallet::<Self>::compute_fee(
1954							uxt.encoded_size() as u32,
1955							&dispatch_info,
1956							0u32.into(),
1957						)
1958					};
1959
1960					let blockweights: $crate::BlockWeights =
1961						<Self as $crate::frame_system::Config>::BlockWeights::get();
1962					$crate::Pallet::<Self>::dry_run_eth_transact(tx, blockweights.max_block, tx_fee)
1963				}
1964
1965				fn call(
1966					origin: AccountId,
1967					dest: $crate::H160,
1968					value: Balance,
1969					gas_limit: Option<$crate::Weight>,
1970					storage_deposit_limit: Option<Balance>,
1971					input_data: Vec<u8>,
1972				) -> $crate::ContractResult<$crate::ExecReturnValue, Balance> {
1973					use $crate::frame_support::traits::Get;
1974					let blockweights: $crate::BlockWeights =
1975						<Self as $crate::frame_system::Config>::BlockWeights::get();
1976
1977					$crate::Pallet::<Self>::prepare_dry_run(&origin);
1978					$crate::Pallet::<Self>::bare_call(
1979						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin),
1980						dest,
1981						$crate::Pallet::<Self>::convert_native_to_evm(value),
1982						gas_limit.unwrap_or(blockweights.max_block),
1983						$crate::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)),
1984						input_data,
1985					)
1986				}
1987
1988				fn instantiate(
1989					origin: AccountId,
1990					value: Balance,
1991					gas_limit: Option<$crate::Weight>,
1992					storage_deposit_limit: Option<Balance>,
1993					code: $crate::Code,
1994					data: Vec<u8>,
1995					salt: Option<[u8; 32]>,
1996				) -> $crate::ContractResult<$crate::InstantiateReturnValue, Balance> {
1997					use $crate::frame_support::traits::Get;
1998					let blockweights: $crate::BlockWeights =
1999						<Self as $crate::frame_system::Config>::BlockWeights::get();
2000
2001					$crate::Pallet::<Self>::prepare_dry_run(&origin);
2002					$crate::Pallet::<Self>::bare_instantiate(
2003						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin),
2004						$crate::Pallet::<Self>::convert_native_to_evm(value),
2005						gas_limit.unwrap_or(blockweights.max_block),
2006						$crate::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)),
2007						code,
2008						data,
2009						salt,
2010						$crate::BumpNonce::Yes,
2011					)
2012				}
2013
2014				fn upload_code(
2015					origin: AccountId,
2016					code: Vec<u8>,
2017					storage_deposit_limit: Option<Balance>,
2018				) -> $crate::CodeUploadResult<Balance> {
2019					let origin =
2020						<Self as $crate::frame_system::Config>::RuntimeOrigin::signed(origin);
2021					$crate::Pallet::<Self>::bare_upload_code(
2022						origin,
2023						code,
2024						storage_deposit_limit.unwrap_or(u128::MAX),
2025					)
2026				}
2027
2028				fn get_storage_var_key(
2029					address: $crate::H160,
2030					key: Vec<u8>,
2031				) -> $crate::GetStorageResult {
2032					$crate::Pallet::<Self>::get_storage_var_key(address, key)
2033				}
2034
2035				fn get_storage(address: $crate::H160, key: [u8; 32]) -> $crate::GetStorageResult {
2036					$crate::Pallet::<Self>::get_storage(address, key)
2037				}
2038
2039				fn trace_block(
2040					block: Block,
2041					tracer_type: $crate::evm::TracerType,
2042				) -> Vec<(u32, $crate::evm::Trace)> {
2043					use $crate::{sp_runtime::traits::Block, tracing::trace};
2044					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type);
2045					let mut traces = vec![];
2046					let (header, extrinsics) = block.deconstruct();
2047					<$Executive>::initialize_block(&header);
2048					for (index, ext) in extrinsics.into_iter().enumerate() {
2049						let t = tracer.as_tracing();
2050						let _ = trace(t, || <$Executive>::apply_extrinsic(ext));
2051
2052						if let Some(tx_trace) = tracer.collect_trace() {
2053							traces.push((index as u32, tx_trace));
2054						}
2055					}
2056
2057					traces
2058				}
2059
2060				fn trace_tx(
2061					block: Block,
2062					tx_index: u32,
2063					tracer_type: $crate::evm::TracerType,
2064				) -> Option<$crate::evm::Trace> {
2065					use $crate::{sp_runtime::traits::Block, tracing::trace};
2066
2067					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type);
2068					let (header, extrinsics) = block.deconstruct();
2069
2070					<$Executive>::initialize_block(&header);
2071					for (index, ext) in extrinsics.into_iter().enumerate() {
2072						if index as u32 == tx_index {
2073							let t = tracer.as_tracing();
2074							let _ = trace(t, || <$Executive>::apply_extrinsic(ext));
2075							break;
2076						} else {
2077							let _ = <$Executive>::apply_extrinsic(ext);
2078						}
2079					}
2080
2081					tracer.collect_trace()
2082				}
2083
2084				fn trace_call(
2085					tx: $crate::evm::GenericTransaction,
2086					tracer_type: $crate::evm::TracerType,
2087				) -> Result<$crate::evm::Trace, $crate::EthTransactError> {
2088					use $crate::tracing::trace;
2089					let mut tracer = $crate::Pallet::<Self>::evm_tracer(tracer_type);
2090					let t = tracer.as_tracing();
2091
2092					t.watch_address(&tx.from.unwrap_or_default());
2093					t.watch_address(&$crate::Pallet::<Self>::block_author().unwrap_or_default());
2094					let result = trace(t, || Self::eth_transact(tx));
2095
2096					if let Some(trace) = tracer.collect_trace() {
2097						Ok(trace)
2098					} else if let Err(err) = result {
2099						Err(err)
2100					} else {
2101						Ok(tracer.empty_trace())
2102					}
2103				}
2104
2105				fn runtime_pallets_address() -> $crate::H160 {
2106					$crate::RUNTIME_PALLETS_ADDR
2107				}
2108
2109				fn code(address: $crate::H160) -> Vec<u8> {
2110					$crate::Pallet::<Self>::code(&address)
2111				}
2112			}
2113		}
2114	};
2115}