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;
24mod address;
25mod benchmarking;
26mod exec;
27mod gas;
28mod limits;
29mod primitives;
30mod storage;
31mod transient_storage;
32mod wasm;
33
34#[cfg(test)]
35mod tests;
36
37pub mod chain_extension;
38pub mod debug;
39pub mod evm;
40pub mod test_utils;
41pub mod weights;
42
43use crate::{
44	evm::{runtime::GAS_PRICE, TransactionLegacyUnsigned},
45	exec::{AccountIdOf, ExecError, Executable, Ext, Key, Origin, Stack as ExecStack},
46	gas::GasMeter,
47	storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager},
48	wasm::{CodeInfo, RuntimeCosts, WasmBlob},
49};
50use alloc::boxed::Box;
51use codec::{Codec, Decode, Encode};
52use environmental::*;
53use frame_support::{
54	dispatch::{
55		DispatchErrorWithPostInfo, DispatchResultWithPostInfo, GetDispatchInfo, Pays,
56		PostDispatchInfo, RawOrigin,
57	},
58	ensure,
59	pallet_prelude::DispatchClass,
60	traits::{
61		fungible::{Inspect, Mutate, MutateHold},
62		ConstU32, ConstU64, Contains, EnsureOrigin, Get, IsType, OriginTrait, Time,
63	},
64	weights::{Weight, WeightMeter},
65	BoundedVec, RuntimeDebugNoBound,
66};
67use frame_system::{
68	ensure_signed,
69	pallet_prelude::{BlockNumberFor, OriginFor},
70	EventRecord, Pallet as System,
71};
72use pallet_transaction_payment::OnChargeTransaction;
73use scale_info::TypeInfo;
74use sp_core::{H160, H256, U256};
75use sp_runtime::{
76	traits::{BadOrigin, Convert, Dispatchable, Saturating},
77	DispatchError,
78};
79
80pub use crate::{
81	address::{create1, create2, AccountId32Mapper, AddressMapper},
82	debug::Tracing,
83	exec::MomentOf,
84	pallet::*,
85};
86pub use primitives::*;
87pub use weights::WeightInfo;
88
89#[cfg(doc)]
90pub use crate::wasm::SyscallDoc;
91
92type TrieId = BoundedVec<u8, ConstU32<128>>;
93type BalanceOf<T> =
94	<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
95type OnChargeTransactionBalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as OnChargeTransaction<T>>::Balance;
96type CodeVec = BoundedVec<u8, ConstU32<{ limits::code::BLOB_BYTES }>>;
97type EventRecordOf<T> =
98	EventRecord<<T as frame_system::Config>::RuntimeEvent, <T as frame_system::Config>::Hash>;
99type DebugBuffer = BoundedVec<u8, ConstU32<{ limits::DEBUG_BUFFER_BYTES }>>;
100type ImmutableData = BoundedVec<u8, ConstU32<{ limits::IMMUTABLE_BYTES }>>;
101
102/// Used as a sentinel value when reading and writing contract memory.
103///
104/// It is usually used to signal `None` to a contract when only a primitive is allowed
105/// and we don't want to go through encoding a full Rust type. Using `u32::Max` is a safe
106/// sentinel because contracts are never allowed to use such a large amount of resources
107/// that this value makes sense for a memory location or length.
108const SENTINEL: u32 = u32::MAX;
109
110/// The target that is used for the log output emitted by this crate.
111///
112/// Hence you can use this target to selectively increase the log level for this crate.
113///
114/// Example: `RUST_LOG=runtime::revive=debug my_code --dev`
115const LOG_TARGET: &str = "runtime::revive";
116
117/// This version determines which syscalls are available to contracts.
118///
119/// Needs to be bumped every time a versioned syscall is added.
120const API_VERSION: u16 = 0;
121
122#[test]
123fn api_version_up_to_date() {
124	assert!(
125		API_VERSION == crate::wasm::HIGHEST_API_VERSION,
126		"A new versioned API has been added. The `API_VERSION` needs to be bumped."
127	);
128}
129
130#[frame_support::pallet]
131pub mod pallet {
132	use super::*;
133	use crate::debug::Debugger;
134	use frame_support::pallet_prelude::*;
135	use frame_system::pallet_prelude::*;
136	use sp_core::U256;
137	use sp_runtime::Perbill;
138
139	/// The in-code storage version.
140	pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
141
142	#[pallet::pallet]
143	#[pallet::storage_version(STORAGE_VERSION)]
144	pub struct Pallet<T>(_);
145
146	#[pallet::config(with_default)]
147	pub trait Config: frame_system::Config {
148		/// The time implementation used to supply timestamps to contracts through `seal_now`.
149		type Time: Time;
150
151		/// The fungible in which fees are paid and contract balances are held.
152		#[pallet::no_default]
153		type Currency: Inspect<Self::AccountId>
154			+ Mutate<Self::AccountId>
155			+ MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>;
156
157		/// The overarching event type.
158		#[pallet::no_default_bounds]
159		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
160
161		/// The overarching call type.
162		#[pallet::no_default_bounds]
163		type RuntimeCall: Parameter
164			+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin, PostInfo = PostDispatchInfo>
165			+ GetDispatchInfo;
166
167		/// Overarching hold reason.
168		#[pallet::no_default_bounds]
169		type RuntimeHoldReason: From<HoldReason>;
170
171		/// Filter that is applied to calls dispatched by contracts.
172		///
173		/// Use this filter to control which dispatchables are callable by contracts.
174		/// This is applied in **addition** to [`frame_system::Config::BaseCallFilter`].
175		/// It is recommended to treat this as a whitelist.
176		///
177		/// # Stability
178		///
179		/// The runtime **must** make sure that all dispatchables that are callable by
180		/// contracts remain stable. In addition [`Self::RuntimeCall`] itself must remain stable.
181		/// This means that no existing variants are allowed to switch their positions.
182		///
183		/// # Note
184		///
185		/// Note that dispatchables that are called via contracts do not spawn their
186		/// own wasm instance for each call (as opposed to when called via a transaction).
187		/// Therefore please make sure to be restrictive about which dispatchables are allowed
188		/// in order to not introduce a new DoS vector like memory allocation patterns that can
189		/// be exploited to drive the runtime into a panic.
190		///
191		/// This filter does not apply to XCM transact calls. To impose restrictions on XCM transact
192		/// calls, you must configure them separately within the XCM pallet itself.
193		#[pallet::no_default_bounds]
194		type CallFilter: Contains<<Self as frame_system::Config>::RuntimeCall>;
195
196		/// Used to answer contracts' queries regarding the current weight price. This is **not**
197		/// used to calculate the actual fee and is only for informational purposes.
198		#[pallet::no_default_bounds]
199		type WeightPrice: Convert<Weight, BalanceOf<Self>>;
200
201		/// Describes the weights of the dispatchables of this module and is also used to
202		/// construct a default cost schedule.
203		type WeightInfo: WeightInfo;
204
205		/// Type that allows the runtime authors to add new host functions for a contract to call.
206		#[pallet::no_default_bounds]
207		type ChainExtension: chain_extension::ChainExtension<Self> + Default;
208
209		/// The amount of balance a caller has to pay for each byte of storage.
210		///
211		/// # Note
212		///
213		/// It is safe to change this value on a live chain as all refunds are pro rata.
214		#[pallet::constant]
215		#[pallet::no_default_bounds]
216		type DepositPerByte: Get<BalanceOf<Self>>;
217
218		/// The amount of balance a caller has to pay for each storage item.
219		///
220		/// # Note
221		///
222		/// It is safe to change this value on a live chain as all refunds are pro rata.
223		#[pallet::constant]
224		#[pallet::no_default_bounds]
225		type DepositPerItem: Get<BalanceOf<Self>>;
226
227		/// The percentage of the storage deposit that should be held for using a code hash.
228		/// Instantiating a contract, or calling [`chain_extension::Ext::lock_delegate_dependency`]
229		/// protects the code from being removed. In order to prevent abuse these actions are
230		/// protected with a percentage of the code deposit.
231		#[pallet::constant]
232		type CodeHashLockupDepositPercent: Get<Perbill>;
233
234		/// Use either valid type is [`address::AccountId32Mapper`] or [`address::H160Mapper`].
235		#[pallet::no_default]
236		type AddressMapper: AddressMapper<Self>;
237
238		/// Make contract callable functions marked as `#[unstable]` available.
239		///
240		/// Contracts that use `#[unstable]` functions won't be able to be uploaded unless
241		/// this is set to `true`. This is only meant for testnets and dev nodes in order to
242		/// experiment with new features.
243		///
244		/// # Warning
245		///
246		/// Do **not** set to `true` on productions chains.
247		#[pallet::constant]
248		type UnsafeUnstableInterface: Get<bool>;
249
250		/// Origin allowed to upload code.
251		///
252		/// By default, it is safe to set this to `EnsureSigned`, allowing anyone to upload contract
253		/// code.
254		#[pallet::no_default_bounds]
255		type UploadOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
256
257		/// Origin allowed to instantiate code.
258		///
259		/// # Note
260		///
261		/// This is not enforced when a contract instantiates another contract. The
262		/// [`Self::UploadOrigin`] should make sure that no code is deployed that does unwanted
263		/// instantiations.
264		///
265		/// By default, it is safe to set this to `EnsureSigned`, allowing anyone to instantiate
266		/// contract code.
267		#[pallet::no_default_bounds]
268		type InstantiateOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
269
270		/// For most production chains, it's recommended to use the `()` implementation of this
271		/// trait. This implementation offers additional logging when the log target
272		/// "runtime::revive" is set to trace.
273		#[pallet::no_default_bounds]
274		type Debug: Debugger<Self>;
275
276		/// A type that exposes XCM APIs, allowing contracts to interact with other parachains, and
277		/// execute XCM programs.
278		#[pallet::no_default_bounds]
279		type Xcm: xcm_builder::Controller<
280			OriginFor<Self>,
281			<Self as frame_system::Config>::RuntimeCall,
282			BlockNumberFor<Self>,
283		>;
284
285		/// The amount of memory in bytes that parachain nodes a lot to the runtime.
286		///
287		/// This is used in [`Pallet::integrity_test`] to make sure that the runtime has enough
288		/// memory to support this pallet if set to the correct value.
289		type RuntimeMemory: Get<u32>;
290
291		/// The amount of memory in bytes that relay chain validators a lot to the PoV.
292		///
293		/// This is used in [`Pallet::integrity_test`] to make sure that the runtime has enough
294		/// memory to support this pallet if set to the correct value.
295		///
296		/// This value is usually higher than [`Self::RuntimeMemory`] to account for the fact
297		/// that validators have to hold all storage items in PvF memory.
298		type PVFMemory: Get<u32>;
299
300		/// The [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID.
301		///
302		/// This is a unique identifier assigned to each blockchain network,
303		/// preventing replay attacks.
304		#[pallet::constant]
305		type ChainId: Get<u64>;
306
307		/// The ratio between the decimal representation of the native token and the ETH token.
308		#[pallet::constant]
309		type NativeToEthRatio: Get<u32>;
310	}
311
312	/// Container for different types that implement [`DefaultConfig`]` of this pallet.
313	pub mod config_preludes {
314		use super::*;
315		use frame_support::{
316			derive_impl,
317			traits::{ConstBool, ConstU32},
318		};
319		use frame_system::EnsureSigned;
320		use sp_core::parameter_types;
321
322		type AccountId = sp_runtime::AccountId32;
323		type Balance = u64;
324		const UNITS: Balance = 10_000_000_000;
325		const CENTS: Balance = UNITS / 100;
326
327		pub const fn deposit(items: u32, bytes: u32) -> Balance {
328			items as Balance * 1 * CENTS + (bytes as Balance) * 1 * CENTS
329		}
330
331		parameter_types! {
332			pub const DepositPerItem: Balance = deposit(1, 0);
333			pub const DepositPerByte: Balance = deposit(0, 1);
334			pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
335		}
336
337		/// A type providing default configurations for this pallet in testing environment.
338		pub struct TestDefaultConfig;
339
340		impl Time for TestDefaultConfig {
341			type Moment = u64;
342			fn now() -> Self::Moment {
343				unimplemented!("No default `now` implementation in `TestDefaultConfig` provide a custom `T::Time` type.")
344			}
345		}
346
347		impl<T: From<u64>> Convert<Weight, T> for TestDefaultConfig {
348			fn convert(w: Weight) -> T {
349				w.ref_time().into()
350			}
351		}
352
353		#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
354		impl frame_system::DefaultConfig for TestDefaultConfig {}
355
356		#[frame_support::register_default_impl(TestDefaultConfig)]
357		impl DefaultConfig for TestDefaultConfig {
358			#[inject_runtime_type]
359			type RuntimeEvent = ();
360
361			#[inject_runtime_type]
362			type RuntimeHoldReason = ();
363
364			#[inject_runtime_type]
365			type RuntimeCall = ();
366			type CallFilter = ();
367			type ChainExtension = ();
368			type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
369			type DepositPerByte = DepositPerByte;
370			type DepositPerItem = DepositPerItem;
371			type Time = Self;
372			type UnsafeUnstableInterface = ConstBool<true>;
373			type UploadOrigin = EnsureSigned<AccountId>;
374			type InstantiateOrigin = EnsureSigned<AccountId>;
375			type WeightInfo = ();
376			type WeightPrice = Self;
377			type Debug = ();
378			type Xcm = ();
379			type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>;
380			type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>;
381			type ChainId = ConstU64<0>;
382			type NativeToEthRatio = ConstU32<1_000_000>;
383		}
384	}
385
386	#[pallet::event]
387	pub enum Event<T: Config> {
388		/// Contract deployed by address at the specified address.
389		Instantiated { deployer: H160, contract: H160 },
390
391		/// Contract has been removed.
392		///
393		/// # Note
394		///
395		/// The only way for a contract to be removed and emitting this event is by calling
396		/// `seal_terminate`.
397		Terminated {
398			/// The contract that was terminated.
399			contract: H160,
400			/// The account that received the contracts remaining balance
401			beneficiary: H160,
402		},
403
404		/// Code with the specified hash has been stored.
405		CodeStored { code_hash: H256, deposit_held: BalanceOf<T>, uploader: H160 },
406
407		/// A custom event emitted by the contract.
408		ContractEmitted {
409			/// The contract that emitted the event.
410			contract: H160,
411			/// Data supplied by the contract. Metadata generated during contract compilation
412			/// is needed to decode it.
413			data: Vec<u8>,
414			/// A list of topics used to index the event.
415			/// Number of topics is capped by [`limits::NUM_EVENT_TOPICS`].
416			topics: Vec<H256>,
417		},
418
419		/// A code with the specified hash was removed.
420		CodeRemoved { code_hash: H256, deposit_released: BalanceOf<T>, remover: H160 },
421
422		/// A contract's code was updated.
423		ContractCodeUpdated {
424			/// The contract that has been updated.
425			contract: H160,
426			/// New code hash that was set for the contract.
427			new_code_hash: H256,
428			/// Previous code hash of the contract.
429			old_code_hash: H256,
430		},
431
432		/// A contract was called either by a plain account or another contract.
433		///
434		/// # Note
435		///
436		/// Please keep in mind that like all events this is only emitted for successful
437		/// calls. This is because on failure all storage changes including events are
438		/// rolled back.
439		Called {
440			/// The caller of the `contract`.
441			caller: Origin<T>,
442			/// The contract that was called.
443			contract: H160,
444		},
445
446		/// A contract delegate called a code hash.
447		///
448		/// # Note
449		///
450		/// Please keep in mind that like all events this is only emitted for successful
451		/// calls. This is because on failure all storage changes including events are
452		/// rolled back.
453		DelegateCalled {
454			/// The contract that performed the delegate call and hence in whose context
455			/// the `code_hash` is executed.
456			contract: H160,
457			/// The code hash that was delegate called.
458			code_hash: H256,
459		},
460
461		/// Some funds have been transferred and held as storage deposit.
462		StorageDepositTransferredAndHeld { from: H160, to: H160, amount: BalanceOf<T> },
463
464		/// Some storage deposit funds have been transferred and released.
465		StorageDepositTransferredAndReleased { from: H160, to: H160, amount: BalanceOf<T> },
466	}
467
468	#[pallet::error]
469	pub enum Error<T> {
470		/// Invalid schedule supplied, e.g. with zero weight of a basic operation.
471		InvalidSchedule,
472		/// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`.
473		InvalidCallFlags,
474		/// The executed contract exhausted its gas limit.
475		OutOfGas,
476		/// Performing the requested transfer failed. Probably because there isn't enough
477		/// free balance in the sender's account.
478		TransferFailed,
479		/// Performing a call was denied because the calling depth reached the limit
480		/// of what is specified in the schedule.
481		MaxCallDepthReached,
482		/// No contract was found at the specified address.
483		ContractNotFound,
484		/// No code could be found at the supplied code hash.
485		CodeNotFound,
486		/// No code info could be found at the supplied code hash.
487		CodeInfoNotFound,
488		/// A buffer outside of sandbox memory was passed to a contract API function.
489		OutOfBounds,
490		/// Input passed to a contract API function failed to decode as expected type.
491		DecodingFailed,
492		/// Contract trapped during execution.
493		ContractTrapped,
494		/// The size defined in `T::MaxValueSize` was exceeded.
495		ValueTooLarge,
496		/// Termination of a contract is not allowed while the contract is already
497		/// on the call stack. Can be triggered by `seal_terminate`.
498		TerminatedWhileReentrant,
499		/// `seal_call` forwarded this contracts input. It therefore is no longer available.
500		InputForwarded,
501		/// The amount of topics passed to `seal_deposit_events` exceeds the limit.
502		TooManyTopics,
503		/// The chain does not provide a chain extension. Calling the chain extension results
504		/// in this error. Note that this usually  shouldn't happen as deploying such contracts
505		/// is rejected.
506		NoChainExtension,
507		/// Failed to decode the XCM program.
508		XCMDecodeFailed,
509		/// A contract with the same AccountId already exists.
510		DuplicateContract,
511		/// A contract self destructed in its constructor.
512		///
513		/// This can be triggered by a call to `seal_terminate`.
514		TerminatedInConstructor,
515		/// A call tried to invoke a contract that is flagged as non-reentrant.
516		ReentranceDenied,
517		/// A contract called into the runtime which then called back into this pallet.
518		ReenteredPallet,
519		/// A contract attempted to invoke a state modifying API while being in read-only mode.
520		StateChangeDenied,
521		/// Origin doesn't have enough balance to pay the required storage deposits.
522		StorageDepositNotEnoughFunds,
523		/// More storage was created than allowed by the storage deposit limit.
524		StorageDepositLimitExhausted,
525		/// Code removal was denied because the code is still in use by at least one contract.
526		CodeInUse,
527		/// The contract ran to completion but decided to revert its storage changes.
528		/// Please note that this error is only returned from extrinsics. When called directly
529		/// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags
530		/// to determine whether a reversion has taken place.
531		ContractReverted,
532		/// The contract failed to compile or is missing the correct entry points.
533		///
534		/// A more detailed error can be found on the node console if debug messages are enabled
535		/// by supplying `-lruntime::revive=debug`.
536		CodeRejected,
537		/// The code blob supplied is larger than [`limits::code::BLOB_BYTES`].
538		BlobTooLarge,
539		/// The static memory consumption of the blob will be larger than
540		/// [`limits::code::STATIC_MEMORY_BYTES`].
541		StaticMemoryTooLarge,
542		/// The program contains a basic block that is larger than allowed.
543		BasicBlockTooLarge,
544		/// The program contains an invalid instruction.
545		InvalidInstruction,
546		/// The contract has reached its maximum number of delegate dependencies.
547		MaxDelegateDependenciesReached,
548		/// The dependency was not found in the contract's delegate dependencies.
549		DelegateDependencyNotFound,
550		/// The contract already depends on the given delegate dependency.
551		DelegateDependencyAlreadyExists,
552		/// Can not add a delegate dependency to the code hash of the contract itself.
553		CannotAddSelfAsDelegateDependency,
554		/// Can not add more data to transient storage.
555		OutOfTransientStorage,
556		/// The contract tried to call a syscall which does not exist (at its current api level).
557		InvalidSyscall,
558		/// Invalid storage flags were passed to one of the storage syscalls.
559		InvalidStorageFlags,
560		/// PolkaVM failed during code execution. Probably due to a malformed program.
561		ExecutionFailed,
562		/// Failed to convert a U256 to a Balance.
563		BalanceConversionFailed,
564		/// Immutable data can only be set during deploys and only be read during calls.
565		/// Additionally, it is only valid to set the data once and it must not be empty.
566		InvalidImmutableAccess,
567		/// An `AccountID32` account tried to interact with the pallet without having a mapping.
568		///
569		/// Call [`Pallet::map_account`] in order to create a mapping for the account.
570		AccountUnmapped,
571		/// Tried to map an account that is already mapped.
572		AccountAlreadyMapped,
573	}
574
575	/// A reason for the pallet contracts placing a hold on funds.
576	#[pallet::composite_enum]
577	pub enum HoldReason {
578		/// The Pallet has reserved it for storing code on-chain.
579		CodeUploadDepositReserve,
580		/// The Pallet has reserved it for storage deposit.
581		StorageDepositReserve,
582		/// Deposit for creating an address mapping in [`AddressSuffix`].
583		AddressMapping,
584	}
585
586	/// A mapping from a contract's code hash to its code.
587	#[pallet::storage]
588	pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, H256, CodeVec>;
589
590	/// A mapping from a contract's code hash to its code info.
591	#[pallet::storage]
592	pub(crate) type CodeInfoOf<T: Config> = StorageMap<_, Identity, H256, CodeInfo<T>>;
593
594	/// The code associated with a given account.
595	#[pallet::storage]
596	pub(crate) type ContractInfoOf<T: Config> = StorageMap<_, Identity, H160, ContractInfo<T>>;
597
598	/// The immutable data associated with a given account.
599	#[pallet::storage]
600	pub(crate) type ImmutableDataOf<T: Config> = StorageMap<_, Identity, H160, ImmutableData>;
601
602	/// Evicted contracts that await child trie deletion.
603	///
604	/// Child trie deletion is a heavy operation depending on the amount of storage items
605	/// stored in said trie. Therefore this operation is performed lazily in `on_idle`.
606	#[pallet::storage]
607	pub(crate) type DeletionQueue<T: Config> = StorageMap<_, Twox64Concat, u32, TrieId>;
608
609	/// A pair of monotonic counters used to track the latest contract marked for deletion
610	/// and the latest deleted contract in queue.
611	#[pallet::storage]
612	pub(crate) type DeletionQueueCounter<T: Config> =
613		StorageValue<_, DeletionQueueManager<T>, ValueQuery>;
614
615	/// Map a Ethereum address to its original `AccountId32`.
616	///
617	/// Stores the last 12 byte for addresses that were originally an `AccountId32` instead
618	/// of an `H160`. Register your `AccountId32` using [`Pallet::map_account`] in order to
619	/// use it with this pallet.
620	#[pallet::storage]
621	pub(crate) type AddressSuffix<T: Config> = StorageMap<_, Identity, H160, [u8; 12]>;
622
623	#[pallet::extra_constants]
624	impl<T: Config> Pallet<T> {
625		#[pallet::constant_name(ApiVersion)]
626		fn api_version() -> u16 {
627			API_VERSION
628		}
629	}
630
631	#[pallet::hooks]
632	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
633		fn on_idle(_block: BlockNumberFor<T>, limit: Weight) -> Weight {
634			let mut meter = WeightMeter::with_limit(limit);
635			ContractInfo::<T>::process_deletion_queue_batch(&mut meter);
636			meter.consumed()
637		}
638
639		fn integrity_test() {
640			use limits::code::STATIC_MEMORY_BYTES;
641
642			// The memory available in the block building runtime
643			let max_runtime_mem: u32 = T::RuntimeMemory::get();
644			// The root frame is not accounted in CALL_STACK_DEPTH
645			let max_call_depth =
646				limits::CALL_STACK_DEPTH.checked_add(1).expect("CallStack size is too big");
647			// Transient storage uses a BTreeMap, which has overhead compared to the raw size of
648			// key-value data. To ensure safety, a margin of 2x the raw key-value size is used.
649			let max_transient_storage_size = limits::TRANSIENT_STORAGE_BYTES
650				.checked_mul(2)
651				.expect("MaxTransientStorageSize is too large");
652
653			// We only allow 50% of the runtime memory to be utilized by the contracts call
654			// stack, keeping the rest for other facilities, such as PoV, etc.
655			const TOTAL_MEMORY_DEVIDER: u32 = 2;
656
657			// The inefficiencies of the freeing-bump allocator
658			// being used in the client for the runtime memory allocations, could lead to possible
659			// memory allocations grow up to `x4` times in some extreme cases.
660			const MEMORY_ALLOCATOR_INEFFICENCY_DEVIDER: u32 = 4;
661
662			// Check that the configured `STATIC_MEMORY_BYTES` fits into runtime memory.
663			//
664			// `STATIC_MEMORY_BYTES` is the amount of memory that a contract can consume
665			// in memory and is enforced at upload time.
666			//
667			// Dynamic allocations are not available, yet. Hence are not taken into consideration
668			// here.
669			let static_memory_limit = max_runtime_mem
670				.saturating_div(TOTAL_MEMORY_DEVIDER)
671				.saturating_sub(max_transient_storage_size)
672				.saturating_div(max_call_depth)
673				.saturating_sub(STATIC_MEMORY_BYTES)
674				.saturating_div(MEMORY_ALLOCATOR_INEFFICENCY_DEVIDER);
675
676			assert!(
677				STATIC_MEMORY_BYTES < static_memory_limit,
678				"Given `CallStack` height {:?}, `STATIC_MEMORY_LIMIT` should be set less than {:?} \
679				 (current value is {:?}), to avoid possible runtime oom issues.",
680				max_call_depth,
681				static_memory_limit,
682				STATIC_MEMORY_BYTES,
683			);
684
685			// Validators are configured to be able to use more memory than block builders. This is
686			// because in addition to `max_runtime_mem` they need to hold additional data in
687			// memory: PoV in multiple copies (1x encoded + 2x decoded) and all storage which
688			// includes emitted events. The assumption is that storage/events size
689			// can be a maximum of half of the validator runtime memory - max_runtime_mem.
690			let max_block_ref_time = T::BlockWeights::get()
691				.get(DispatchClass::Normal)
692				.max_total
693				.unwrap_or_else(|| T::BlockWeights::get().max_block)
694				.ref_time();
695			let max_payload_size = limits::PAYLOAD_BYTES;
696			let max_key_size =
697				Key::try_from_var(alloc::vec![0u8; limits::STORAGE_KEY_BYTES as usize])
698					.expect("Key of maximal size shall be created")
699					.hash()
700					.len() as u32;
701
702			let max_immutable_key_size = T::AccountId::max_encoded_len() as u32;
703			let max_immutable_size: u32 = ((max_block_ref_time /
704				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetImmutableData(
705					limits::IMMUTABLE_BYTES,
706				))
707				.ref_time()))
708			.saturating_mul(limits::IMMUTABLE_BYTES.saturating_add(max_immutable_key_size) as u64))
709			.try_into()
710			.expect("Immutable data size too big");
711
712			// We can use storage to store items using the available block ref_time with the
713			// `set_storage` host function.
714			let max_storage_size: u32 = ((max_block_ref_time /
715				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetStorage {
716					new_bytes: max_payload_size,
717					old_bytes: 0,
718				})
719				.ref_time()))
720			.saturating_mul(max_payload_size.saturating_add(max_key_size) as u64))
721			.saturating_add(max_immutable_size.into())
722			.try_into()
723			.expect("Storage size too big");
724
725			let max_pvf_mem: u32 = T::PVFMemory::get();
726			let storage_size_limit = max_pvf_mem.saturating_sub(max_runtime_mem) / 2;
727
728			assert!(
729				max_storage_size < storage_size_limit,
730				"Maximal storage size {} exceeds the storage limit {}",
731				max_storage_size,
732				storage_size_limit
733			);
734
735			// We can use storage to store events using the available block ref_time with the
736			// `deposit_event` host function. The overhead of stored events, which is around 100B,
737			// is not taken into account to simplify calculations, as it does not change much.
738			let max_events_size: u32 = ((max_block_ref_time /
739				(<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::DepositEvent {
740					num_topic: 0,
741					len: max_payload_size,
742				})
743				.ref_time()))
744			.saturating_mul(max_payload_size as u64))
745			.try_into()
746			.expect("Events size too big");
747
748			assert!(
749				max_events_size < storage_size_limit,
750				"Maximal events size {} exceeds the events limit {}",
751				max_events_size,
752				storage_size_limit
753			);
754		}
755	}
756
757	#[pallet::call]
758	impl<T: Config> Pallet<T>
759	where
760		BalanceOf<T>: Into<U256> + TryFrom<U256>,
761		MomentOf<T>: Into<U256>,
762		T::Hash: frame_support::traits::IsType<H256>,
763	{
764		/// A raw EVM transaction, typically dispatched by an Ethereum JSON-RPC server.
765		///
766		/// # Parameters
767		///
768		/// * `payload`: The RLP-encoded [`crate::evm::TransactionLegacySigned`].
769		/// * `gas_limit`: The gas limit enforced during contract execution.
770		/// * `storage_deposit_limit`: The maximum balance that can be charged to the caller for
771		///   storage usage.
772		///
773		/// # Note
774		///
775		/// This call cannot be dispatched directly; attempting to do so will result in a failed
776		/// transaction. It serves as a wrapper for an Ethereum transaction. When submitted, the
777		/// runtime converts it into a [`sp_runtime::generic::CheckedExtrinsic`] by recovering the
778		/// signer and validating the transaction.
779		#[allow(unused_variables)]
780		#[pallet::call_index(0)]
781		#[pallet::weight(Weight::MAX)]
782		pub fn eth_transact(
783			origin: OriginFor<T>,
784			payload: Vec<u8>,
785			gas_limit: Weight,
786			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
787		) -> DispatchResultWithPostInfo {
788			Err(frame_system::Error::CallFiltered::<T>.into())
789		}
790
791		/// Makes a call to an account, optionally transferring some balance.
792		///
793		/// # Parameters
794		///
795		/// * `dest`: Address of the contract to call.
796		/// * `value`: The balance to transfer from the `origin` to `dest`.
797		/// * `gas_limit`: The gas limit enforced when executing the constructor.
798		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged from the
799		///   caller to pay for the storage consumed.
800		/// * `data`: The input data to pass to the contract.
801		///
802		/// * If the account is a smart-contract account, the associated code will be
803		/// executed and any value will be transferred.
804		/// * If the account is a regular account, any value will be transferred.
805		/// * If no account exists and the call value is not less than `existential_deposit`,
806		/// a regular account will be created and any value will be transferred.
807		#[pallet::call_index(1)]
808		#[pallet::weight(T::WeightInfo::call().saturating_add(*gas_limit))]
809		pub fn call(
810			origin: OriginFor<T>,
811			dest: H160,
812			#[pallet::compact] value: BalanceOf<T>,
813			gas_limit: Weight,
814			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
815			data: Vec<u8>,
816		) -> DispatchResultWithPostInfo {
817			log::info!(target: LOG_TARGET, "Call: {:?} {:?} {:?}", dest, value, data);
818			let mut output = Self::bare_call(
819				origin,
820				dest,
821				value,
822				gas_limit,
823				storage_deposit_limit,
824				data,
825				DebugInfo::Skip,
826				CollectEvents::Skip,
827			);
828			if let Ok(return_value) = &output.result {
829				if return_value.did_revert() {
830					output.result = Err(<Error<T>>::ContractReverted.into());
831				}
832			}
833			dispatch_result(output.result, output.gas_consumed, T::WeightInfo::call())
834		}
835
836		/// Instantiates a contract from a previously deployed wasm binary.
837		///
838		/// This function is identical to [`Self::instantiate_with_code`] but without the
839		/// code deployment step. Instead, the `code_hash` of an on-chain deployed wasm binary
840		/// must be supplied.
841		#[pallet::call_index(2)]
842		#[pallet::weight(
843			T::WeightInfo::instantiate(data.len() as u32).saturating_add(*gas_limit)
844		)]
845		pub fn instantiate(
846			origin: OriginFor<T>,
847			#[pallet::compact] value: BalanceOf<T>,
848			gas_limit: Weight,
849			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
850			code_hash: sp_core::H256,
851			data: Vec<u8>,
852			salt: Option<[u8; 32]>,
853		) -> DispatchResultWithPostInfo {
854			let data_len = data.len() as u32;
855			let mut output = Self::bare_instantiate(
856				origin,
857				value,
858				gas_limit,
859				storage_deposit_limit,
860				Code::Existing(code_hash),
861				data,
862				salt,
863				DebugInfo::Skip,
864				CollectEvents::Skip,
865			);
866			if let Ok(retval) = &output.result {
867				if retval.result.did_revert() {
868					output.result = Err(<Error<T>>::ContractReverted.into());
869				}
870			}
871			dispatch_result(
872				output.result.map(|result| result.result),
873				output.gas_consumed,
874				T::WeightInfo::instantiate(data_len),
875			)
876		}
877
878		/// Instantiates a new contract from the supplied `code` optionally transferring
879		/// some balance.
880		///
881		/// This dispatchable has the same effect as calling [`Self::upload_code`] +
882		/// [`Self::instantiate`]. Bundling them together provides efficiency gains. Please
883		/// also check the documentation of [`Self::upload_code`].
884		///
885		/// # Parameters
886		///
887		/// * `value`: The balance to transfer from the `origin` to the newly created contract.
888		/// * `gas_limit`: The gas limit enforced when executing the constructor.
889		/// * `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved
890		///   from the caller to pay for the storage consumed.
891		/// * `code`: The contract code to deploy in raw bytes.
892		/// * `data`: The input data to pass to the contract constructor.
893		/// * `salt`: Used for the address derivation. If `Some` is supplied then `CREATE2`
894		/// 	semantics are used. If `None` then `CRATE1` is used.
895		///
896		///
897		/// Instantiation is executed as follows:
898		///
899		/// - The supplied `code` is deployed, and a `code_hash` is created for that code.
900		/// - If the `code_hash` already exists on the chain the underlying `code` will be shared.
901		/// - The destination address is computed based on the sender, code_hash and the salt.
902		/// - The smart-contract account is created at the computed address.
903		/// - The `value` is transferred to the new account.
904		/// - The `deploy` function is executed in the context of the newly-created account.
905		#[pallet::call_index(3)]
906		#[pallet::weight(
907			T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32)
908			.saturating_add(*gas_limit)
909		)]
910		pub fn instantiate_with_code(
911			origin: OriginFor<T>,
912			#[pallet::compact] value: BalanceOf<T>,
913			gas_limit: Weight,
914			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
915			code: Vec<u8>,
916			data: Vec<u8>,
917			salt: Option<[u8; 32]>,
918		) -> DispatchResultWithPostInfo {
919			let code_len = code.len() as u32;
920			let data_len = data.len() as u32;
921			let mut output = Self::bare_instantiate(
922				origin,
923				value,
924				gas_limit,
925				storage_deposit_limit,
926				Code::Upload(code),
927				data,
928				salt,
929				DebugInfo::Skip,
930				CollectEvents::Skip,
931			);
932			if let Ok(retval) = &output.result {
933				if retval.result.did_revert() {
934					output.result = Err(<Error<T>>::ContractReverted.into());
935				}
936			}
937			dispatch_result(
938				output.result.map(|result| result.result),
939				output.gas_consumed,
940				T::WeightInfo::instantiate_with_code(code_len, data_len),
941			)
942		}
943
944		/// Upload new `code` without instantiating a contract from it.
945		///
946		/// If the code does not already exist a deposit is reserved from the caller
947		/// and unreserved only when [`Self::remove_code`] is called. The size of the reserve
948		/// depends on the size of the supplied `code`.
949		///
950		/// # Note
951		///
952		/// Anyone can instantiate a contract from any uploaded code and thus prevent its removal.
953		/// To avoid this situation a constructor could employ access control so that it can
954		/// only be instantiated by permissioned entities. The same is true when uploading
955		/// through [`Self::instantiate_with_code`].
956		#[pallet::call_index(4)]
957		#[pallet::weight(T::WeightInfo::upload_code(code.len() as u32))]
958		pub fn upload_code(
959			origin: OriginFor<T>,
960			code: Vec<u8>,
961			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
962		) -> DispatchResult {
963			Self::bare_upload_code(origin, code, storage_deposit_limit).map(|_| ())
964		}
965
966		/// Remove the code stored under `code_hash` and refund the deposit to its owner.
967		///
968		/// A code can only be removed by its original uploader (its owner) and only if it is
969		/// not used by any contract.
970		#[pallet::call_index(5)]
971		#[pallet::weight(T::WeightInfo::remove_code())]
972		pub fn remove_code(
973			origin: OriginFor<T>,
974			code_hash: sp_core::H256,
975		) -> DispatchResultWithPostInfo {
976			let origin = ensure_signed(origin)?;
977			<WasmBlob<T>>::remove(&origin, code_hash)?;
978			// we waive the fee because removing unused code is beneficial
979			Ok(Pays::No.into())
980		}
981
982		/// Privileged function that changes the code of an existing contract.
983		///
984		/// This takes care of updating refcounts and all other necessary operations. Returns
985		/// an error if either the `code_hash` or `dest` do not exist.
986		///
987		/// # Note
988		///
989		/// This does **not** change the address of the contract in question. This means
990		/// that the contract address is no longer derived from its code hash after calling
991		/// this dispatchable.
992		#[pallet::call_index(6)]
993		#[pallet::weight(T::WeightInfo::set_code())]
994		pub fn set_code(
995			origin: OriginFor<T>,
996			dest: H160,
997			code_hash: sp_core::H256,
998		) -> DispatchResult {
999			ensure_root(origin)?;
1000			<ContractInfoOf<T>>::try_mutate(&dest, |contract| {
1001				let contract = if let Some(contract) = contract {
1002					contract
1003				} else {
1004					return Err(<Error<T>>::ContractNotFound.into());
1005				};
1006				<ExecStack<T, WasmBlob<T>>>::increment_refcount(code_hash)?;
1007				<ExecStack<T, WasmBlob<T>>>::decrement_refcount(contract.code_hash);
1008				Self::deposit_event(Event::ContractCodeUpdated {
1009					contract: dest,
1010					new_code_hash: code_hash,
1011					old_code_hash: contract.code_hash,
1012				});
1013				contract.code_hash = code_hash;
1014				Ok(())
1015			})
1016		}
1017
1018		/// Register the callers account id so that it can be used in contract interactions.
1019		///
1020		/// This will error if the origin is already mapped or is a eth native `Address20`. It will
1021		/// take a deposit that can be released by calling [`Self::unmap_account`].
1022		#[pallet::call_index(7)]
1023		#[pallet::weight(T::WeightInfo::map_account())]
1024		pub fn map_account(origin: OriginFor<T>) -> DispatchResult {
1025			let origin = ensure_signed(origin)?;
1026			T::AddressMapper::map(&origin)
1027		}
1028
1029		/// Unregister the callers account id in order to free the deposit.
1030		///
1031		/// There is no reason to ever call this function other than freeing up the deposit.
1032		/// This is only useful when the account should no longer be used.
1033		#[pallet::call_index(8)]
1034		#[pallet::weight(T::WeightInfo::unmap_account())]
1035		pub fn unmap_account(origin: OriginFor<T>) -> DispatchResult {
1036			let origin = ensure_signed(origin)?;
1037			T::AddressMapper::unmap(&origin)
1038		}
1039
1040		/// Dispatch an `call` with the origin set to the callers fallback address.
1041		///
1042		/// Every `AccountId32` can control its corresponding fallback account. The fallback account
1043		/// is the `AccountId20` with the last 12 bytes set to `0xEE`. This is essentially a
1044		/// recovery function in case an `AccountId20` was used without creating a mapping first.
1045		#[pallet::call_index(9)]
1046		#[pallet::weight({
1047			let dispatch_info = call.get_dispatch_info();
1048			(
1049				T::WeightInfo::dispatch_as_fallback_account().saturating_add(dispatch_info.call_weight),
1050				dispatch_info.class
1051			)
1052		})]
1053		pub fn dispatch_as_fallback_account(
1054			origin: OriginFor<T>,
1055			call: Box<<T as Config>::RuntimeCall>,
1056		) -> DispatchResultWithPostInfo {
1057			let origin = ensure_signed(origin)?;
1058			let unmapped_account =
1059				T::AddressMapper::to_fallback_account_id(&T::AddressMapper::to_address(&origin));
1060			call.dispatch(RawOrigin::Signed(unmapped_account).into())
1061		}
1062	}
1063}
1064
1065/// Create a dispatch result reflecting the amount of consumed gas.
1066fn dispatch_result<R>(
1067	result: Result<R, DispatchError>,
1068	gas_consumed: Weight,
1069	base_weight: Weight,
1070) -> DispatchResultWithPostInfo {
1071	let post_info = PostDispatchInfo {
1072		actual_weight: Some(gas_consumed.saturating_add(base_weight)),
1073		pays_fee: Default::default(),
1074	};
1075
1076	result
1077		.map(|_| post_info)
1078		.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e })
1079}
1080
1081impl<T: Config> Pallet<T>
1082where
1083	BalanceOf<T>: Into<U256> + TryFrom<U256>,
1084	MomentOf<T>: Into<U256>,
1085	T::Hash: frame_support::traits::IsType<H256>,
1086{
1087	/// A generalized version of [`Self::call`].
1088	///
1089	/// Identical to [`Self::call`] but tailored towards being called by other code within the
1090	/// runtime as opposed to from an extrinsic. It returns more information and allows the
1091	/// enablement of features that are not suitable for an extrinsic (debugging, event
1092	/// collection).
1093	pub fn bare_call(
1094		origin: OriginFor<T>,
1095		dest: H160,
1096		value: BalanceOf<T>,
1097		gas_limit: Weight,
1098		storage_deposit_limit: BalanceOf<T>,
1099		data: Vec<u8>,
1100		debug: DebugInfo,
1101		collect_events: CollectEvents,
1102	) -> ContractResult<ExecReturnValue, BalanceOf<T>, EventRecordOf<T>> {
1103		let mut gas_meter = GasMeter::new(gas_limit);
1104		let mut storage_deposit = Default::default();
1105		let mut debug_message = if matches!(debug, DebugInfo::UnsafeDebug) {
1106			Some(DebugBuffer::default())
1107		} else {
1108			None
1109		};
1110		let try_call = || {
1111			let origin = Origin::from_runtime_origin(origin)?;
1112			let mut storage_meter = StorageMeter::new(&origin, storage_deposit_limit, value)?;
1113			let result = ExecStack::<T, WasmBlob<T>>::run_call(
1114				origin.clone(),
1115				dest,
1116				&mut gas_meter,
1117				&mut storage_meter,
1118				value,
1119				data,
1120				debug_message.as_mut(),
1121			)?;
1122			storage_deposit = storage_meter.try_into_deposit(&origin)?;
1123			Ok(result)
1124		};
1125		let result = Self::run_guarded(try_call);
1126		let events = if matches!(collect_events, CollectEvents::UnsafeCollect) {
1127			Some(System::<T>::read_events_no_consensus().map(|e| *e).collect())
1128		} else {
1129			None
1130		};
1131		ContractResult {
1132			result: result.map_err(|r| r.error),
1133			gas_consumed: gas_meter.gas_consumed(),
1134			gas_required: gas_meter.gas_required(),
1135			storage_deposit,
1136			debug_message: debug_message.unwrap_or_default().to_vec(),
1137			events,
1138		}
1139	}
1140
1141	/// A generalized version of [`Self::instantiate`] or [`Self::instantiate_with_code`].
1142	///
1143	/// Identical to [`Self::instantiate`] or [`Self::instantiate_with_code`] but tailored towards
1144	/// being called by other code within the runtime as opposed to from an extrinsic. It returns
1145	/// more information and allows the enablement of features that are not suitable for an
1146	/// extrinsic (debugging, event collection).
1147	pub fn bare_instantiate(
1148		origin: OriginFor<T>,
1149		value: BalanceOf<T>,
1150		gas_limit: Weight,
1151		mut storage_deposit_limit: BalanceOf<T>,
1152		code: Code,
1153		data: Vec<u8>,
1154		salt: Option<[u8; 32]>,
1155		debug: DebugInfo,
1156		collect_events: CollectEvents,
1157	) -> ContractResult<InstantiateReturnValue, BalanceOf<T>, EventRecordOf<T>> {
1158		let mut gas_meter = GasMeter::new(gas_limit);
1159		let mut storage_deposit = Default::default();
1160		let mut debug_message =
1161			if debug == DebugInfo::UnsafeDebug { Some(DebugBuffer::default()) } else { None };
1162		let try_instantiate = || {
1163			let instantiate_account = T::InstantiateOrigin::ensure_origin(origin.clone())?;
1164			let (executable, upload_deposit) = match code {
1165				Code::Upload(code) => {
1166					let upload_account = T::UploadOrigin::ensure_origin(origin)?;
1167					let (executable, upload_deposit) =
1168						Self::try_upload_code(upload_account, code, storage_deposit_limit)?;
1169					storage_deposit_limit.saturating_reduce(upload_deposit);
1170					(executable, upload_deposit)
1171				},
1172				Code::Existing(code_hash) =>
1173					(WasmBlob::from_storage(code_hash, &mut gas_meter)?, Default::default()),
1174			};
1175			let instantiate_origin = Origin::from_account_id(instantiate_account.clone());
1176			let mut storage_meter =
1177				StorageMeter::new(&instantiate_origin, storage_deposit_limit, value)?;
1178			let result = ExecStack::<T, WasmBlob<T>>::run_instantiate(
1179				instantiate_account,
1180				executable,
1181				&mut gas_meter,
1182				&mut storage_meter,
1183				value,
1184				data,
1185				salt.as_ref(),
1186				debug_message.as_mut(),
1187			);
1188			storage_deposit = storage_meter
1189				.try_into_deposit(&instantiate_origin)?
1190				.saturating_add(&StorageDeposit::Charge(upload_deposit));
1191			result
1192		};
1193		let output = Self::run_guarded(try_instantiate);
1194		let events = if matches!(collect_events, CollectEvents::UnsafeCollect) {
1195			Some(System::<T>::read_events_no_consensus().map(|e| *e).collect())
1196		} else {
1197			None
1198		};
1199		ContractResult {
1200			result: output
1201				.map(|(addr, result)| InstantiateReturnValue { result, addr })
1202				.map_err(|e| e.error),
1203			gas_consumed: gas_meter.gas_consumed(),
1204			gas_required: gas_meter.gas_required(),
1205			storage_deposit,
1206			debug_message: debug_message.unwrap_or_default().to_vec(),
1207			events,
1208		}
1209	}
1210
1211	/// A version of [`Self::eth_transact`] used to dry-run Ethereum calls.
1212	///
1213	/// # Parameters
1214	///
1215	/// - `origin`: The origin of the call.
1216	/// - `dest`: The destination address of the call.
1217	/// - `value`: The value to transfer.
1218	/// - `input`: The input data.
1219	/// - `gas_limit`: The gas limit enforced during contract execution.
1220	/// - `storage_deposit_limit`: The maximum balance that can be charged to the caller for storage
1221	///   usage.
1222	/// - `utx_encoded_size`: A function that takes a call and returns the encoded size of the
1223	///   unchecked extrinsic.
1224	/// - `debug`: Debugging configuration.
1225	/// - `collect_events`: Event collection configuration.
1226	pub fn bare_eth_transact(
1227		origin: T::AccountId,
1228		dest: Option<H160>,
1229		value: BalanceOf<T>,
1230		input: Vec<u8>,
1231		gas_limit: Weight,
1232		storage_deposit_limit: BalanceOf<T>,
1233		utx_encoded_size: impl Fn(Call<T>) -> u32,
1234		debug: DebugInfo,
1235		collect_events: CollectEvents,
1236	) -> EthContractResult<BalanceOf<T>>
1237	where
1238		T: pallet_transaction_payment::Config,
1239		<T as frame_system::Config>::RuntimeCall:
1240			Dispatchable<Info = frame_support::dispatch::DispatchInfo>,
1241		<T as Config>::RuntimeCall: From<crate::Call<T>>,
1242		<T as Config>::RuntimeCall: Encode,
1243		OnChargeTransactionBalanceOf<T>: Into<BalanceOf<T>>,
1244		T::Nonce: Into<U256>,
1245		T::Hash: frame_support::traits::IsType<H256>,
1246	{
1247		log::debug!(target: LOG_TARGET, "bare_eth_transact: dest: {dest:?} value: {value:?} gas_limit: {gas_limit:?} storage_deposit_limit: {storage_deposit_limit:?}");
1248		// Get the nonce to encode in the tx.
1249		let nonce: T::Nonce = <System<T>>::account_nonce(&origin);
1250
1251		// Use a big enough gas price to ensure that the encoded size is large enough.
1252		let max_gas_fee: BalanceOf<T> =
1253			(pallet_transaction_payment::Pallet::<T>::weight_to_fee(Weight::MAX) /
1254				GAS_PRICE.into())
1255			.into();
1256
1257		// A contract call.
1258		if let Some(dest) = dest {
1259			// Dry run the call.
1260			let result = crate::Pallet::<T>::bare_call(
1261				T::RuntimeOrigin::signed(origin),
1262				dest,
1263				value,
1264				gas_limit,
1265				storage_deposit_limit,
1266				input.clone(),
1267				debug,
1268				collect_events,
1269			);
1270
1271			// Get the encoded size of the transaction.
1272			let tx = TransactionLegacyUnsigned {
1273				value: value.into().saturating_mul(T::NativeToEthRatio::get().into()),
1274				input: input.into(),
1275				nonce: nonce.into(),
1276				chain_id: Some(T::ChainId::get().into()),
1277				gas_price: GAS_PRICE.into(),
1278				gas: max_gas_fee.into(),
1279				to: Some(dest),
1280				..Default::default()
1281			};
1282
1283			let eth_dispatch_call = crate::Call::<T>::eth_transact {
1284				payload: tx.dummy_signed_payload(),
1285				gas_limit: result.gas_required,
1286				storage_deposit_limit: result.storage_deposit.charge_or_zero(),
1287			};
1288			let encoded_len = utx_encoded_size(eth_dispatch_call);
1289
1290			// Get the dispatch info of the call.
1291			let dispatch_call: <T as Config>::RuntimeCall = crate::Call::<T>::call {
1292				dest,
1293				value,
1294				gas_limit: result.gas_required,
1295				storage_deposit_limit: result.storage_deposit.charge_or_zero(),
1296				data: tx.input.0,
1297			}
1298			.into();
1299			let dispatch_info = dispatch_call.get_dispatch_info();
1300
1301			// Compute the fee.
1302			let fee = pallet_transaction_payment::Pallet::<T>::compute_fee(
1303				encoded_len,
1304				&dispatch_info,
1305				0u32.into(),
1306			)
1307			.into();
1308
1309			log::trace!(target: LOG_TARGET, "bare_eth_call: len: {encoded_len:?} fee: {fee:?}");
1310			EthContractResult {
1311				gas_required: result.gas_required,
1312				storage_deposit: result.storage_deposit.charge_or_zero(),
1313				result: result.result.map(|v| v.data),
1314				fee,
1315			}
1316			// A contract deployment
1317		} else {
1318			// Extract code and data from the input.
1319			let (code, data) = match polkavm::ProgramBlob::blob_length(&input) {
1320				Some(blob_len) => blob_len
1321					.try_into()
1322					.ok()
1323					.and_then(|blob_len| (input.split_at_checked(blob_len)))
1324					.unwrap_or_else(|| (&input[..], &[][..])),
1325				_ => {
1326					log::debug!(target: LOG_TARGET, "Failed to extract polkavm blob length");
1327					(&input[..], &[][..])
1328				},
1329			};
1330
1331			// Dry run the call.
1332			let result = crate::Pallet::<T>::bare_instantiate(
1333				T::RuntimeOrigin::signed(origin),
1334				value,
1335				gas_limit,
1336				storage_deposit_limit,
1337				Code::Upload(code.to_vec()),
1338				data.to_vec(),
1339				None,
1340				debug,
1341				collect_events,
1342			);
1343
1344			// Get the encoded size of the transaction.
1345			let tx = TransactionLegacyUnsigned {
1346				gas: max_gas_fee.into(),
1347				nonce: nonce.into(),
1348				value: value.into().saturating_mul(T::NativeToEthRatio::get().into()),
1349				input: input.clone().into(),
1350				gas_price: GAS_PRICE.into(),
1351				chain_id: Some(T::ChainId::get().into()),
1352				..Default::default()
1353			};
1354			let eth_dispatch_call = crate::Call::<T>::eth_transact {
1355				payload: tx.dummy_signed_payload(),
1356				gas_limit: result.gas_required,
1357				storage_deposit_limit: result.storage_deposit.charge_or_zero(),
1358			};
1359			let encoded_len = utx_encoded_size(eth_dispatch_call);
1360
1361			// Get the dispatch info of the call.
1362			let dispatch_call: <T as Config>::RuntimeCall =
1363				crate::Call::<T>::instantiate_with_code {
1364					value,
1365					gas_limit: result.gas_required,
1366					storage_deposit_limit: result.storage_deposit.charge_or_zero(),
1367					code: code.to_vec(),
1368					data: data.to_vec(),
1369					salt: None,
1370				}
1371				.into();
1372			let dispatch_info = dispatch_call.get_dispatch_info();
1373
1374			// Compute the fee.
1375			let fee = pallet_transaction_payment::Pallet::<T>::compute_fee(
1376				encoded_len,
1377				&dispatch_info,
1378				0u32.into(),
1379			)
1380			.into();
1381
1382			log::trace!(target: LOG_TARGET, "bare_eth_call: len: {encoded_len:?} fee: {fee:?}");
1383			EthContractResult {
1384				gas_required: result.gas_required,
1385				storage_deposit: result.storage_deposit.charge_or_zero(),
1386				result: result.result.map(|v| v.result.data),
1387				fee,
1388			}
1389		}
1390	}
1391
1392	/// A generalized version of [`Self::upload_code`].
1393	///
1394	/// It is identical to [`Self::upload_code`] and only differs in the information it returns.
1395	pub fn bare_upload_code(
1396		origin: OriginFor<T>,
1397		code: Vec<u8>,
1398		storage_deposit_limit: BalanceOf<T>,
1399	) -> CodeUploadResult<BalanceOf<T>> {
1400		let origin = T::UploadOrigin::ensure_origin(origin)?;
1401		let (module, deposit) = Self::try_upload_code(origin, code, storage_deposit_limit)?;
1402		Ok(CodeUploadReturnValue { code_hash: *module.code_hash(), deposit })
1403	}
1404
1405	/// Query storage of a specified contract under a specified key.
1406	pub fn get_storage(address: H160, key: [u8; 32]) -> GetStorageResult {
1407		let contract_info =
1408			ContractInfoOf::<T>::get(&address).ok_or(ContractAccessError::DoesntExist)?;
1409
1410		let maybe_value = contract_info.read(&Key::from_fixed(key));
1411		Ok(maybe_value)
1412	}
1413
1414	/// Uploads new code and returns the Wasm blob and deposit amount collected.
1415	fn try_upload_code(
1416		origin: T::AccountId,
1417		code: Vec<u8>,
1418		storage_deposit_limit: BalanceOf<T>,
1419	) -> Result<(WasmBlob<T>, BalanceOf<T>), DispatchError> {
1420		let mut module = WasmBlob::from_code(code, origin)?;
1421		let deposit = module.store_code()?;
1422		ensure!(storage_deposit_limit >= deposit, <Error<T>>::StorageDepositLimitExhausted);
1423		Ok((module, deposit))
1424	}
1425
1426	/// Run the supplied function `f` if no other instance of this pallet is on the stack.
1427	fn run_guarded<R, F: FnOnce() -> Result<R, ExecError>>(f: F) -> Result<R, ExecError> {
1428		executing_contract::using_once(&mut false, || {
1429			executing_contract::with(|f| {
1430				// Fail if already entered contract execution
1431				if *f {
1432					return Err(())
1433				}
1434				// We are entering contract execution
1435				*f = true;
1436				Ok(())
1437			})
1438				.expect("Returns `Ok` if called within `using_once`. It is syntactically obvious that this is the case; qed")
1439				.map_err(|_| <Error<T>>::ReenteredPallet.into())
1440				.map(|_| f())
1441				.and_then(|r| r)
1442		})
1443	}
1444}
1445
1446impl<T: Config> Pallet<T> {
1447	/// Return the existential deposit of [`Config::Currency`].
1448	fn min_balance() -> BalanceOf<T> {
1449		<T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
1450	}
1451
1452	/// Deposit a pallet contracts event.
1453	fn deposit_event(event: Event<T>) {
1454		<frame_system::Pallet<T>>::deposit_event(<T as Config>::RuntimeEvent::from(event))
1455	}
1456}
1457
1458// Set up a global reference to the boolean flag used for the re-entrancy guard.
1459environmental!(executing_contract: bool);
1460
1461sp_api::decl_runtime_apis! {
1462	/// The API used to dry-run contract interactions.
1463	#[api_version(1)]
1464	pub trait ReviveApi<AccountId, Balance, Nonce, BlockNumber, EventRecord> where
1465		AccountId: Codec,
1466		Balance: Codec,
1467		Nonce: Codec,
1468		BlockNumber: Codec,
1469		EventRecord: Codec,
1470	{
1471		/// Returns the free balance of the given `[H160]` address.
1472		fn balance(address: H160) -> Balance;
1473
1474		/// Returns the nonce of the given `[H160]` address.
1475		fn nonce(address: H160) -> Nonce;
1476
1477		/// Perform a call from a specified account to a given contract.
1478		///
1479		/// See [`crate::Pallet::bare_call`].
1480		fn call(
1481			origin: AccountId,
1482			dest: H160,
1483			value: Balance,
1484			gas_limit: Option<Weight>,
1485			storage_deposit_limit: Option<Balance>,
1486			input_data: Vec<u8>,
1487		) -> ContractResult<ExecReturnValue, Balance, EventRecord>;
1488
1489		/// Instantiate a new contract.
1490		///
1491		/// See `[crate::Pallet::bare_instantiate]`.
1492		fn instantiate(
1493			origin: AccountId,
1494			value: Balance,
1495			gas_limit: Option<Weight>,
1496			storage_deposit_limit: Option<Balance>,
1497			code: Code,
1498			data: Vec<u8>,
1499			salt: Option<[u8; 32]>,
1500		) -> ContractResult<InstantiateReturnValue, Balance, EventRecord>;
1501
1502
1503		/// Perform an Ethereum call.
1504		///
1505		/// See [`crate::Pallet::bare_eth_transact`]
1506		fn eth_transact(
1507			origin: H160,
1508			dest: Option<H160>,
1509			value: Balance,
1510			input: Vec<u8>,
1511			gas_limit: Option<Weight>,
1512			storage_deposit_limit: Option<Balance>,
1513		) -> EthContractResult<Balance>;
1514
1515		/// Upload new code without instantiating a contract from it.
1516		///
1517		/// See [`crate::Pallet::bare_upload_code`].
1518		fn upload_code(
1519			origin: AccountId,
1520			code: Vec<u8>,
1521			storage_deposit_limit: Option<Balance>,
1522		) -> CodeUploadResult<Balance>;
1523
1524		/// Query a given storage key in a given contract.
1525		///
1526		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
1527		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
1528		/// doesn't exist, or doesn't have a contract then `Err` is returned.
1529		fn get_storage(
1530			address: H160,
1531			key: [u8; 32],
1532		) -> GetStorageResult;
1533	}
1534}