Skip to main content

pallet_revive/
lib.rs

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