1use crate::{
19 AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf,
20 CodeRemoved, Config, ContractInfo, Error, Event, ImmutableData, ImmutableDataOf, LOG_TARGET,
21 Pallet as Contracts, RuntimeCosts, TrieId,
22 address::{self, AddressMapper},
23 deposit_payment::Deposit as _,
24 evm::{block_storage, fees::InfoT as _, transfer_with_dust},
25 limits,
26 metering::{ChargedAmount, Diff, FrameMeter, ResourceMeter, State, Token, TransactionMeter},
27 precompiles::{All as AllPrecompiles, Instance as PrecompileInstance, Precompiles},
28 primitives::{ExecConfig, ExecReturnValue, StorageDeposit},
29 runtime_decl_for_revive_api::{Decode, Encode, TypeInfo},
30 storage::{AccountIdOrAddress, WriteOutcome},
31 tracing::if_tracing,
32 transient_storage::TransientStorage,
33};
34use alloc::{
35 collections::{BTreeMap, BTreeSet},
36 vec::Vec,
37};
38use core::{cmp, fmt::Debug, marker::PhantomData, mem, ops::ControlFlow};
39use frame_support::{
40 Blake2_128Concat, BoundedVec, DebugNoBound, StorageHasher,
41 crypto::ecdsa::ECDSAExt,
42 dispatch::DispatchResult,
43 ensure,
44 storage::{TransactionOutcome, with_transaction},
45 traits::{
46 Time,
47 fungible::{Balanced as _, Inspect, Mutate},
48 tokens::Preservation,
49 },
50 weights::Weight,
51};
52use frame_system::{
53 Pallet as System, RawOrigin,
54 pallet_prelude::{BlockNumberFor, OriginFor},
55};
56use sp_core::{
57 ConstU32, Get, H160, H256, U256,
58 ecdsa::Public as ECDSAPublic,
59 sr25519::{Public as SR25519Public, Signature as SR25519Signature},
60};
61use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
62use sp_runtime::{
63 DispatchError, SaturatedConversion,
64 traits::{BadOrigin, Saturating, TrailingZeroInput, Zero},
65};
66
67#[cfg(test)]
68mod tests;
69
70#[cfg(test)]
71pub mod mock_ext;
72
73pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
74pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
75pub type ExecResult = Result<ExecReturnValue, ExecError>;
76
77type VarSizedKey = BoundedVec<u8, ConstU32<{ limits::STORAGE_KEY_BYTES }>>;
79
80const FRAME_ALWAYS_EXISTS_ON_INSTANTIATE: &str = "The return value is only `None` if no contract exists at the specified address. This cannot happen on instantiate or delegate; qed";
81
82pub const EMPTY_CODE_HASH: H256 =
84 H256(sp_core::hex2array!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
85
86#[derive(Debug)]
88pub enum Key {
89 Fix([u8; 32]),
91 Var(VarSizedKey),
93}
94
95impl Key {
96 pub fn unhashed(&self) -> &[u8] {
98 match self {
99 Key::Fix(v) => v.as_ref(),
100 Key::Var(v) => v.as_ref(),
101 }
102 }
103
104 pub fn hash(&self) -> Vec<u8> {
106 match self {
107 Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
108 Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
109 }
110 }
111
112 pub fn from_fixed(v: [u8; 32]) -> Self {
113 Self::Fix(v)
114 }
115
116 pub fn try_from_var(v: Vec<u8>) -> Result<Self, ()> {
117 VarSizedKey::try_from(v).map(Self::Var).map_err(|_| ())
118 }
119}
120
121#[derive(Copy, Clone, PartialEq, Debug)]
127pub enum ReentrancyProtection {
128 AllowReentry,
130 Strict,
133 AllowNext,
141}
142
143#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
149pub enum ErrorOrigin {
150 Caller,
155 Callee,
157}
158
159#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
161pub struct ExecError {
162 pub error: DispatchError,
164 pub origin: ErrorOrigin,
166}
167
168impl<T: Into<DispatchError>> From<T> for ExecError {
169 fn from(error: T) -> Self {
170 Self { error: error.into(), origin: ErrorOrigin::Caller }
171 }
172}
173
174#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, DebugNoBound)]
176pub enum Origin<T: Config> {
177 Root,
178 Signed(T::AccountId),
179}
180
181impl<T: Config> Origin<T> {
182 pub fn from_account_id(account_id: T::AccountId) -> Self {
184 Origin::Signed(account_id)
185 }
186
187 pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
189 match o.into() {
190 Ok(RawOrigin::Root) => Ok(Self::Root),
191 Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
192 _ => Err(BadOrigin.into()),
193 }
194 }
195
196 pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
198 match self {
199 Origin::Signed(id) => Ok(id),
200 Origin::Root => Err(DispatchError::RootNotAllowed),
201 }
202 }
203
204 fn ensure_mapped(&self) -> DispatchResult {
209 match self {
210 Self::Root => Ok(()),
211 Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()),
212 Self::Signed(_) => Err(<Error<T>>::AccountUnmapped.into()),
213 }
214 }
215}
216
217#[derive(DebugNoBound)]
220pub enum CallResources<T: Config> {
221 NoLimits,
223 WeightDeposit { weight: Weight, deposit_limit: BalanceOf<T> },
225 Ethereum { gas: BalanceOf<T>, add_stipend: bool },
227}
228
229impl<T: Config> CallResources<T> {
230 pub fn from_weight_and_deposit(weight: Weight, deposit_limit: U256) -> Self {
232 Self::WeightDeposit {
233 weight,
234 deposit_limit: deposit_limit.saturated_into::<BalanceOf<T>>(),
235 }
236 }
237
238 pub fn from_ethereum_gas(gas: U256, add_stipend: bool) -> Self {
240 Self::Ethereum { gas: gas.saturated_into::<BalanceOf<T>>(), add_stipend }
241 }
242}
243
244impl<T: Config> Default for CallResources<T> {
245 fn default() -> Self {
246 Self::WeightDeposit { weight: Default::default(), deposit_limit: Default::default() }
247 }
248}
249
250struct TerminateArgs<T: Config> {
252 beneficiary: T::AccountId,
254 trie_id: TrieId,
256 code_hash: H256,
258 only_if_same_tx: bool,
260}
261
262pub trait Ext: PrecompileWithInfoExt {
264 fn delegate_call(
268 &mut self,
269 call_resources: &CallResources<Self::T>,
270 address: H160,
271 input_data: Vec<u8>,
272 ) -> Result<(), ExecError>;
273
274 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError>;
281
282 #[allow(dead_code)]
284 fn own_code_hash(&mut self) -> &H256;
285
286 fn immutable_data_len(&mut self) -> u32;
291
292 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError>;
296
297 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError>;
303}
304
305pub trait PrecompileWithInfoExt: PrecompileExt {
307 fn instantiate(
313 &mut self,
314 limits: &CallResources<Self::T>,
315 code: Code,
316 value: U256,
317 input_data: Vec<u8>,
318 salt: Option<&[u8; 32]>,
319 ) -> Result<H160, ExecError>;
320}
321
322pub trait PrecompileExt: sealing::Sealed {
324 type T: Config;
325
326 fn charge(&mut self, weight: Weight) -> Result<ChargedAmount, DispatchError> {
328 self.frame_meter_mut().charge_weight_token(RuntimeCosts::Precompile(weight))
329 }
330
331 fn adjust_gas(&mut self, charged: ChargedAmount, actual_weight: Weight) {
334 self.frame_meter_mut()
335 .adjust_weight(charged, RuntimeCosts::Precompile(actual_weight));
336 }
337
338 #[inline]
341 fn charge_or_halt<Tok: Token<Self::T>>(
342 &mut self,
343 token: Tok,
344 ) -> ControlFlow<crate::vm::evm::Halt, ChargedAmount> {
345 self.frame_meter_mut().charge_or_halt(token)
346 }
347
348 fn call(
350 &mut self,
351 call_resources: &CallResources<Self::T>,
352 to: &H160,
353 value: U256,
354 input_data: Vec<u8>,
355 reentrancy: ReentrancyProtection,
356 read_only: bool,
357 ) -> Result<(), ExecError>;
358
359 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>>;
364
365 fn get_transient_storage_size(&self, key: &Key) -> Option<u32>;
370
371 fn set_transient_storage(
374 &mut self,
375 key: &Key,
376 value: Option<Vec<u8>>,
377 take_old: bool,
378 ) -> Result<WriteOutcome, DispatchError>;
379
380 fn caller(&self) -> Origin<Self::T>;
382
383 fn caller_of_caller(&self) -> Origin<Self::T>;
385
386 fn origin(&self) -> &Origin<Self::T>;
388
389 fn to_account_id(&self, address: &H160) -> AccountIdOf<Self::T>;
391
392 fn code_hash(&self, address: &H160) -> H256;
395
396 fn code_size(&self, address: &H160) -> u64;
398
399 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool;
401
402 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool;
404
405 fn account_id(&self) -> &AccountIdOf<Self::T>;
407
408 fn address(&self) -> H160 {
410 <Self::T as Config>::AddressMapper::to_address(self.account_id())
411 }
412
413 fn balance(&self) -> U256;
417
418 fn balance_of(&self, address: &H160) -> U256;
422
423 fn value_transferred(&self) -> U256;
425
426 fn now(&self) -> U256;
428
429 fn minimum_balance(&self) -> U256;
431
432 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
436
437 fn block_number(&self) -> U256;
439
440 fn block_hash(&self, block_number: U256) -> Option<H256>;
443
444 fn block_author(&self) -> H160;
446
447 fn gas_limit(&self) -> u64;
449
450 fn chain_id(&self) -> u64;
452
453 #[deprecated(note = "Renamed to `frame_meter`; this alias will be removed in future versions")]
455 fn gas_meter(&self) -> &FrameMeter<Self::T>;
456
457 #[deprecated(
459 note = "Renamed to `frame_meter_mut`; this alias will be removed in future versions"
460 )]
461 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
462
463 fn frame_meter(&self) -> &FrameMeter<Self::T>;
465
466 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
468
469 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
471
472 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
474
475 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError>;
477
478 #[cfg(any(test, feature = "runtime-benchmarks"))]
480 fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
481
482 #[cfg(any(feature = "runtime-benchmarks", test))]
486 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
487
488 fn is_read_only(&self) -> bool;
490
491 fn is_delegate_call(&self) -> bool;
493
494 fn last_frame_output(&self) -> &ExecReturnValue;
496
497 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
499
500 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize);
508
509 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError>;
518
519 fn effective_gas_price(&self) -> U256;
521
522 fn gas_left(&self) -> u64;
524
525 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
530
531 fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
536
537 fn set_storage(
540 &mut self,
541 key: &Key,
542 value: Option<Vec<u8>>,
543 take_old: bool,
544 ) -> Result<WriteOutcome, DispatchError>;
545
546 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult;
548}
549
550#[derive(
552 Copy,
553 Clone,
554 PartialEq,
555 Eq,
556 Debug,
557 codec::Decode,
558 codec::Encode,
559 codec::MaxEncodedLen,
560 scale_info::TypeInfo,
561)]
562pub enum ExportedFunction {
563 Constructor,
565 Call,
567}
568
569pub trait Executable<T: Config>: Sized {
574 fn from_storage<S: State>(
579 code_hash: H256,
580 meter: &mut ResourceMeter<T, S>,
581 ) -> Result<Self, DispatchError>;
582
583 fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
585
586 fn execute<E: Ext<T = T>>(
596 self,
597 ext: &mut E,
598 function: ExportedFunction,
599 input_data: Vec<u8>,
600 ) -> ExecResult;
601
602 fn code_info(&self) -> &CodeInfo<T>;
604
605 fn code(&self) -> &[u8];
607
608 fn code_hash(&self) -> &H256;
610}
611
612pub struct Stack<'a, T: Config, E> {
618 origin: Origin<T>,
627 transaction_meter: &'a mut TransactionMeter<T>,
629 timestamp: MomentOf<T>,
631 block_number: BlockNumberFor<T>,
633 frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
636 first_frame: Frame<T>,
638 transient_storage: TransientStorage<T>,
640 exec_config: &'a ExecConfig<T>,
642 _phantom: PhantomData<E>,
644}
645
646struct Frame<T: Config> {
651 account_id: T::AccountId,
653 contract_info: CachedContract<T>,
655 value_transferred: U256,
657 entry_point: ExportedFunction,
659 frame_meter: FrameMeter<T>,
661 allows_reentry: bool,
663 read_only: bool,
665 delegate: Option<DelegateInfo<T>>,
668 last_frame_output: ExecReturnValue,
670 contracts_created: BTreeSet<T::AccountId>,
672 contracts_to_be_destroyed: BTreeMap<T::AccountId, TerminateArgs<T>>,
674}
675
676#[derive(Clone, DebugNoBound)]
679pub struct DelegateInfo<T: Config> {
680 pub caller: Origin<T>,
682 pub callee: H160,
684}
685
686enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
688 Executable(E),
690 Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
692}
693
694impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
695 fn as_executable(&self) -> Option<&E> {
696 if let Self::Executable(executable) = self { Some(executable) } else { None }
697 }
698
699 fn is_pvm(&self) -> bool {
700 match self {
701 Self::Executable(e) => e.code_info().is_pvm(),
702 _ => false,
703 }
704 }
705
706 fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
707 if let Self::Precompile { instance, .. } = self { Some(instance) } else { None }
708 }
709
710 #[cfg(any(feature = "runtime-benchmarks", test))]
711 fn into_executable(self) -> Option<E> {
712 if let Self::Executable(executable) = self { Some(executable) } else { None }
713 }
714}
715
716enum FrameArgs<'a, T: Config, E> {
720 Call {
721 dest: T::AccountId,
723 cached_info: Option<ContractInfo<T>>,
725 delegated_call: Option<DelegateInfo<T>>,
729 },
730 Instantiate {
731 sender: T::AccountId,
733 executable: E,
735 salt: Option<&'a [u8; 32]>,
737 input_data: &'a [u8],
739 },
740}
741
742enum CachedContract<T: Config> {
744 Cached(ContractInfo<T>),
746 Invalidated,
750 None,
752}
753
754impl<T: Config> Frame<T> {
755 fn contract_info(&mut self) -> &mut ContractInfo<T> {
757 self.contract_info.get(&self.account_id)
758 }
759}
760
761macro_rules! get_cached_or_panic_after_load {
765 ($c:expr) => {{
766 if let CachedContract::Cached(contract) = $c {
767 contract
768 } else {
769 panic!(
770 "It is impossible to remove a contract that is on the call stack;\
771 See implementations of terminate;\
772 Therefore fetching a contract will never fail while using an account id
773 that is currently active on the call stack;\
774 qed"
775 );
776 }
777 }};
778}
779
780macro_rules! top_frame {
785 ($stack:expr) => {
786 $stack.frames.last().unwrap_or(&$stack.first_frame)
787 };
788}
789
790macro_rules! top_frame_mut {
795 ($stack:expr) => {
796 $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
797 };
798}
799
800impl<T: Config> CachedContract<T> {
801 fn into_contract(self) -> Option<ContractInfo<T>> {
803 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
804 }
805
806 fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
808 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
809 }
810
811 fn load(&mut self, account_id: &T::AccountId) {
813 if let CachedContract::Invalidated = self &&
814 let Some(contract) =
815 AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
816 {
817 *self = CachedContract::Cached(contract);
818 }
819 }
820
821 fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
823 self.load(account_id);
824 get_cached_or_panic_after_load!(self)
825 }
826
827 fn invalidate(&mut self) {
829 if matches!(self, CachedContract::Cached(_)) {
830 *self = CachedContract::Invalidated;
831 }
832 }
833}
834
835impl<'a, T, E> Stack<'a, T, E>
836where
837 T: Config,
838 E: Executable<T>,
839{
840 pub fn run_call(
846 origin: Origin<T>,
847 dest: H160,
848 transaction_meter: &'a mut TransactionMeter<T>,
849 value: U256,
850 input_data: Vec<u8>,
851 exec_config: &ExecConfig<T>,
852 ) -> ExecResult {
853 let dest = T::AddressMapper::to_account_id(&dest);
854 if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
855 FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
856 origin.clone(),
857 transaction_meter,
858 value,
859 exec_config,
860 &input_data,
861 )? {
862 stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
863 } else {
864 if_tracing(|t| {
865 t.enter_child_span(
866 origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
867 T::AddressMapper::to_address(&dest),
868 None,
869 false,
870 value,
871 &input_data,
872 Default::default(),
873 );
874 });
875
876 let result = if let Some(mock_answer) =
877 exec_config.mock_handler.as_ref().and_then(|handler| {
878 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
879 }) {
880 Ok(mock_answer)
881 } else {
882 Self::transfer_from_origin(
883 &origin,
884 &origin,
885 &dest,
886 value,
887 transaction_meter,
888 exec_config,
889 )
890 };
891
892 if_tracing(|t| {
893 let gas_used =
894 transaction_meter.total_consumed_gas().try_into().unwrap_or(u64::MAX);
895 let weight_consumed = transaction_meter.weight_consumed();
896 match result {
897 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_consumed),
898 Err(e) => {
899 t.exit_child_span_with_error(e.error.into(), gas_used, weight_consumed)
900 },
901 }
902 });
903
904 log::trace!(target: LOG_TARGET, "call finished with: {result:?}");
905
906 result
907 }
908 }
909
910 pub fn run_instantiate(
916 origin: T::AccountId,
917 executable: E,
918 transaction_meter: &'a mut TransactionMeter<T>,
919 value: U256,
920 input_data: Vec<u8>,
921 salt: Option<&[u8; 32]>,
922 exec_config: &ExecConfig<T>,
923 ) -> Result<(H160, ExecReturnValue), ExecError> {
924 let deployer = T::AddressMapper::to_address(&origin);
925 let (mut stack, executable) = Stack::<'_, T, E>::new(
926 FrameArgs::Instantiate {
927 sender: origin.clone(),
928 executable,
929 salt,
930 input_data: input_data.as_ref(),
931 },
932 Origin::from_account_id(origin),
933 transaction_meter,
934 value,
935 exec_config,
936 &input_data,
937 )?
938 .expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
939 let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
940 let result = stack
941 .run(executable, input_data)
942 .map(|_| (address, stack.first_frame.last_frame_output));
943 if let Ok((contract, output)) = &result &&
944 !output.did_revert()
945 {
946 Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract: *contract });
947 }
948 log::trace!(target: LOG_TARGET, "instantiate finished with: {result:?}");
949 result
950 }
951
952 #[cfg(any(feature = "runtime-benchmarks", test))]
953 pub fn bench_new_call(
954 dest: H160,
955 origin: Origin<T>,
956 transaction_meter: &'a mut TransactionMeter<T>,
957 value: BalanceOf<T>,
958 exec_config: &'a ExecConfig<T>,
959 read_only: bool,
960 delegate_call: bool,
961 ) -> (Self, E) {
962 let call = Self::new(
963 FrameArgs::Call {
964 dest: T::AddressMapper::to_account_id(&dest),
965 cached_info: None,
966 delegated_call: None,
967 },
968 origin,
969 transaction_meter,
970 value.into(),
971 exec_config,
972 &Default::default(),
973 )
974 .unwrap()
975 .unwrap();
976 let mut stack = call.0;
977 if read_only {
978 stack.top_frame_mut().read_only = true;
979 }
980 if delegate_call {
981 let frame = stack.top_frame_mut();
982 frame.delegate = Some(DelegateInfo {
983 caller: Origin::from_account_id(frame.account_id.clone()),
984 callee: H160::zero(),
985 });
986 }
987 (stack, call.1.into_executable().unwrap())
988 }
989
990 fn new(
995 args: FrameArgs<T, E>,
996 origin: Origin<T>,
997 transaction_meter: &'a mut TransactionMeter<T>,
998 value: U256,
999 exec_config: &'a ExecConfig<T>,
1000 input_data: &Vec<u8>,
1001 ) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1002 origin.ensure_mapped()?;
1003 let Some((first_frame, executable)) = Self::new_frame(
1004 args,
1005 value,
1006 transaction_meter,
1007 &CallResources::NoLimits,
1008 false,
1009 true,
1010 input_data,
1011 exec_config,
1012 )?
1013 else {
1014 return Ok(None);
1015 };
1016
1017 let mut timestamp = T::Time::now();
1018 let mut block_number = <frame_system::Pallet<T>>::block_number();
1019 if let Some(timestamp_override) =
1021 exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override)
1022 {
1023 block_number = block_number.saturating_add(1u32.into());
1024 let delta = 1000u32.into();
1026 timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override);
1027 }
1028
1029 let stack = Self {
1030 origin,
1031 transaction_meter,
1032 timestamp,
1033 block_number,
1034 first_frame,
1035 frames: Default::default(),
1036 transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
1037 exec_config,
1038 _phantom: Default::default(),
1039 };
1040 Ok(Some((stack, executable)))
1041 }
1042
1043 fn new_frame<S: State>(
1048 frame_args: FrameArgs<T, E>,
1049 value_transferred: U256,
1050 meter: &mut ResourceMeter<T, S>,
1051 call_resources: &CallResources<T>,
1052 read_only: bool,
1053 origin_is_caller: bool,
1054 input_data: &[u8],
1055 exec_config: &ExecConfig<T>,
1056 ) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1057 let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
1058 FrameArgs::Call { dest, cached_info, delegated_call } => {
1059 let address = T::AddressMapper::to_address(&dest);
1060 let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
1061
1062 let mut contract = match (cached_info, &precompile) {
1065 (Some(info), _) => CachedContract::Cached(info),
1066 (None, None) => {
1067 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
1068 CachedContract::Cached(info)
1069 } else {
1070 return Ok(None);
1071 }
1072 },
1073 (None, Some(precompile)) if precompile.has_contract_info() => {
1074 log::trace!(target: LOG_TARGET, "found precompile for address {address:?}");
1075 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
1076 CachedContract::Cached(info)
1077 } else {
1078 let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
1079 CachedContract::Cached(info)
1080 }
1081 },
1082 (None, Some(_)) => CachedContract::None,
1083 };
1084
1085 let delegated_call = delegated_call.or_else(|| {
1086 exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1087 mock_handler.mock_delegated_caller(address, input_data)
1088 })
1089 });
1090 let executable = if let Some(delegated_call) = &delegated_call {
1092 if let Some(precompile) =
1093 <AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
1094 {
1095 ExecutableOrPrecompile::Precompile {
1096 instance: precompile,
1097 _phantom: Default::default(),
1098 }
1099 } else {
1100 let Some(info) = AccountInfo::<T>::load_contract(&delegated_call.callee)
1101 else {
1102 return Ok(None);
1103 };
1104 let executable = E::from_storage(info.code_hash, meter)?;
1105 ExecutableOrPrecompile::Executable(executable)
1106 }
1107 } else {
1108 if let Some(precompile) = precompile {
1109 ExecutableOrPrecompile::Precompile {
1110 instance: precompile,
1111 _phantom: Default::default(),
1112 }
1113 } else {
1114 let executable = E::from_storage(
1115 contract
1116 .as_contract()
1117 .expect("When not a precompile the contract was loaded above; qed")
1118 .code_hash,
1119 meter,
1120 )?;
1121 ExecutableOrPrecompile::Executable(executable)
1122 }
1123 };
1124
1125 (dest, contract, executable, delegated_call, ExportedFunction::Call)
1126 },
1127 FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1128 let deployer = T::AddressMapper::to_address(&sender);
1129 let account_nonce = <System<T>>::account_nonce(&sender);
1130 let address = if let Some(salt) = salt {
1131 address::create2(&deployer, executable.code(), input_data, salt)
1132 } else {
1133 use sp_runtime::Saturating;
1134 address::create1(
1135 &deployer,
1136 if origin_is_caller {
1139 account_nonce.saturating_sub(1u32.into()).saturated_into()
1140 } else {
1141 account_nonce.saturated_into()
1142 },
1143 )
1144 };
1145 let contract = ContractInfo::new(
1146 &address,
1147 <System<T>>::account_nonce(&sender),
1148 *executable.code_hash(),
1149 )?;
1150 (
1151 T::AddressMapper::to_fallback_account_id(&address),
1152 CachedContract::Cached(contract),
1153 ExecutableOrPrecompile::Executable(executable),
1154 None,
1155 ExportedFunction::Constructor,
1156 )
1157 },
1158 };
1159
1160 let frame = Frame {
1161 delegate,
1162 value_transferred,
1163 contract_info,
1164 account_id,
1165 entry_point,
1166 frame_meter: meter.new_nested(call_resources)?,
1167 allows_reentry: true,
1168 read_only,
1169 last_frame_output: Default::default(),
1170 contracts_created: Default::default(),
1171 contracts_to_be_destroyed: Default::default(),
1172 };
1173
1174 Ok(Some((frame, executable)))
1175 }
1176
1177 fn push_frame(
1179 &mut self,
1180 frame_args: FrameArgs<T, E>,
1181 value_transferred: U256,
1182 call_resources: &CallResources<T>,
1183 read_only: bool,
1184 input_data: &[u8],
1185 ) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1186 if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1187 return Err(Error::<T>::MaxCallDepthReached.into());
1188 }
1189
1190 let frame = self.top_frame();
1199 if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1200 (&frame.contract_info, frame.entry_point)
1201 {
1202 let mut contract_with_pending_changes = contract.clone();
1203 frame
1204 .frame_meter
1205 .apply_pending_storage_changes(&mut contract_with_pending_changes);
1206 AccountInfo::<T>::insert_contract(
1207 &T::AddressMapper::to_address(&frame.account_id),
1208 contract_with_pending_changes,
1209 );
1210 }
1211
1212 let frame = top_frame_mut!(self);
1213 let meter = &mut frame.frame_meter;
1214 if let Some((frame, executable)) = Self::new_frame(
1215 frame_args,
1216 value_transferred,
1217 meter,
1218 call_resources,
1219 read_only,
1220 false,
1221 input_data,
1222 self.exec_config,
1223 )? {
1224 self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1225 Ok(Some(executable))
1226 } else {
1227 Ok(None)
1228 }
1229 }
1230
1231 fn run(
1235 &mut self,
1236 executable: ExecutableOrPrecompile<T, E, Self>,
1237 input_data: Vec<u8>,
1238 ) -> Result<(), ExecError> {
1239 let frame = self.top_frame();
1240 let entry_point = frame.entry_point;
1241 let is_pvm = executable.is_pvm();
1242
1243 if_tracing(|tracer| {
1244 let (from, to) = match frame.delegate.as_ref() {
1247 Some(delegate) => {
1248 (T::AddressMapper::to_address(&frame.account_id), delegate.callee)
1249 },
1250 None => (
1251 self.caller()
1252 .account_id()
1253 .map(T::AddressMapper::to_address)
1254 .unwrap_or_default(),
1255 T::AddressMapper::to_address(&frame.account_id),
1256 ),
1257 };
1258 tracer.enter_child_span(
1259 from,
1260 to,
1261 frame.delegate.as_ref().map(|delegate| delegate.callee),
1262 frame.read_only,
1263 frame.value_transferred,
1264 &input_data,
1265 frame
1266 .frame_meter
1267 .eth_gas_left()
1268 .unwrap_or_default()
1269 .try_into()
1270 .unwrap_or_default(),
1271 );
1272 });
1273 let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1274 handler.mock_call(
1275 frame
1276 .delegate
1277 .as_ref()
1278 .map(|delegate| delegate.callee)
1279 .unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1280 &input_data,
1281 frame.value_transferred,
1282 )
1283 });
1284 let frames_len = self.frames.len();
1288 if let Some(caller_frame) = match frames_len {
1289 0 => None,
1290 1 => Some(&mut self.first_frame.last_frame_output),
1291 _ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1292 } {
1293 *caller_frame = Default::default();
1294 }
1295
1296 self.with_transient_storage_mut(|transient_storage| {
1297 transient_storage.start_transaction();
1298 });
1299 let is_first_frame = self.frames.is_empty();
1300
1301 let do_transaction = || -> ExecResult {
1302 let caller = self.caller();
1303 let bump_nonce = self.exec_config.bump_nonce;
1304 let frame = top_frame_mut!(self);
1305 let account_id = &frame.account_id.clone();
1306
1307 if u32::try_from(input_data.len())
1308 .map(|len| len > limits::CALLDATA_BYTES)
1309 .unwrap_or(true)
1310 {
1311 Err(<Error<T>>::CallDataTooLarge)?;
1312 }
1313
1314 if entry_point == ExportedFunction::Constructor {
1317 if !frame_system::Pallet::<T>::account_exists(&account_id) {
1318 T::Deposit::init_contract(account_id)?;
1319 }
1320
1321 <System<T>>::inc_consumers(account_id)?;
1326
1327 <System<T>>::inc_account_nonce(account_id);
1329
1330 if bump_nonce || !is_first_frame {
1331 <System<T>>::inc_account_nonce(caller.account_id()?);
1334 }
1335 if is_pvm {
1337 <CodeInfo<T>>::increment_refcount(
1338 *executable
1339 .as_executable()
1340 .expect("Precompiles cannot be instantiated; qed")
1341 .code_hash(),
1342 )?;
1343 }
1344 }
1345
1346 if frame.delegate.is_none() {
1350 Self::transfer_from_origin(
1351 &self.origin,
1352 &caller,
1353 account_id,
1354 frame.value_transferred,
1355 &mut frame.frame_meter,
1356 self.exec_config,
1357 )?;
1358 }
1359
1360 if let Some(precompile) = executable.as_precompile() &&
1367 precompile.has_contract_info() &&
1368 frame.delegate.is_none() &&
1369 !<System<T>>::account_exists(account_id)
1370 {
1371 T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1374 <System<T>>::inc_consumers(account_id)?;
1376 }
1377
1378 let mut code_deposit = executable
1379 .as_executable()
1380 .map(|exec| exec.code_info().deposit())
1381 .unwrap_or_default();
1382
1383 let mut output = match executable {
1384 ExecutableOrPrecompile::Executable(executable) => {
1385 executable.execute(self, entry_point, input_data)
1386 },
1387 ExecutableOrPrecompile::Precompile { instance, .. } => {
1388 instance.call(input_data, self)
1389 },
1390 }
1391 .and_then(|output| {
1392 if u32::try_from(output.data.len())
1393 .map(|len| len > limits::CALLDATA_BYTES)
1394 .unwrap_or(true)
1395 {
1396 Err(<Error<T>>::ReturnDataTooLarge)?;
1397 }
1398 Ok(output)
1399 })
1400 .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1401
1402 if output.did_revert() {
1404 return Ok(output);
1405 }
1406
1407 let frame = if entry_point == ExportedFunction::Constructor {
1410 let frame = top_frame_mut!(self);
1411 if !is_pvm {
1414 let data = if crate::tracing::if_tracing(|_| {}).is_none() &&
1418 self.exec_config.is_dry_run.is_none()
1419 {
1420 core::mem::replace(&mut output.data, Default::default())
1421 } else {
1422 output.data.clone()
1423 };
1424
1425 let mut module = match &self.origin {
1429 Origin::Signed(o) => {
1430 crate::ContractBlob::<T>::from_evm_runtime_code(data, o.clone())?
1431 },
1432 Origin::Root => {
1433 crate::ContractBlob::<T>::from_evm_runtime_code_with_deposit(
1434 data,
1435 crate::Pallet::<T>::account_id(),
1436 Zero::zero(),
1437 )?
1438 },
1439 };
1440 module.store_code(&self.exec_config, &mut frame.frame_meter)?;
1441 code_deposit = module.code_info().deposit();
1442
1443 let contract_info = frame.contract_info();
1444 contract_info.code_hash = *module.code_hash();
1445 <CodeInfo<T>>::increment_refcount(contract_info.code_hash)?;
1446 }
1447
1448 let deposit = frame.contract_info().update_base_deposit(code_deposit);
1449 frame.frame_meter.charge_contract_deposit_and_transfer(
1450 frame.account_id.clone(),
1451 StorageDeposit::Charge(deposit),
1452 )?;
1453 frame
1454 } else {
1455 self.top_frame_mut()
1456 };
1457
1458 let contract = frame.contract_info.as_contract();
1462 frame
1463 .frame_meter
1464 .finalize(contract)
1465 .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1466
1467 Ok(output)
1468 };
1469
1470 let transaction_outcome =
1477 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1478 let output = if let Some(mock_answer) = mock_answer {
1479 Ok(mock_answer)
1480 } else {
1481 do_transaction()
1482 };
1483 match &output {
1484 Ok(result) if !result.did_revert() => {
1485 TransactionOutcome::Commit(Ok((true, output)))
1486 },
1487 _ => TransactionOutcome::Rollback(Ok((false, output))),
1488 }
1489 });
1490
1491 let (success, output) = match transaction_outcome {
1492 Ok((success, output)) => {
1494 if_tracing(|tracer| {
1495 let frame_meter = &top_frame!(self).frame_meter;
1496
1497 let gas_consumed = if is_first_frame {
1500 frame_meter.total_consumed_gas()
1501 } else {
1502 frame_meter.eth_gas_consumed()
1503 };
1504
1505 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1506 let weight_consumed = frame_meter.weight_consumed();
1507
1508 match &output {
1509 Ok(output) => {
1510 tracer.exit_child_span(&output, gas_consumed, weight_consumed)
1511 },
1512 Err(e) => tracer.exit_child_span_with_error(
1513 e.error.into(),
1514 gas_consumed,
1515 weight_consumed,
1516 ),
1517 }
1518 });
1519
1520 (success, output)
1521 },
1522 Err(error) => {
1525 if_tracing(|tracer| {
1526 let frame_meter = &top_frame!(self).frame_meter;
1527
1528 let gas_consumed = if is_first_frame {
1531 frame_meter.total_consumed_gas()
1532 } else {
1533 frame_meter.eth_gas_consumed()
1534 };
1535
1536 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1537 let weight_consumed = frame_meter.weight_consumed();
1538 tracer.exit_child_span_with_error(error.into(), gas_consumed, weight_consumed);
1539 });
1540
1541 (false, Err(error.into()))
1542 },
1543 };
1544 self.with_transient_storage_mut(|transient_storage| {
1545 if success {
1546 transient_storage.commit_transaction();
1547 } else {
1548 transient_storage.rollback_transaction();
1549 }
1550 });
1551 log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1552
1553 self.pop_frame(success);
1554 output.map(|output| {
1555 self.top_frame_mut().last_frame_output = output;
1556 })
1557 }
1558
1559 fn pop_frame(&mut self, persist: bool) {
1564 let frame = self.frames.pop();
1568
1569 if let Some(mut frame) = frame {
1572 let account_id = &frame.account_id;
1573 let prev = top_frame_mut!(self);
1574
1575 if !persist {
1577 prev.frame_meter.absorb_weight_meter_only(frame.frame_meter);
1578 return;
1579 }
1580
1581 frame.contract_info.load(account_id);
1586 let mut contract = frame.contract_info.into_contract();
1587 prev.frame_meter
1588 .absorb_all_meters(frame.frame_meter, account_id, contract.as_mut());
1589
1590 prev.contracts_created.extend(frame.contracts_created);
1592 prev.contracts_to_be_destroyed.extend(frame.contracts_to_be_destroyed);
1593
1594 if let Some(contract) = contract {
1595 AccountInfo::<T>::insert_contract(
1600 &T::AddressMapper::to_address(account_id),
1601 contract,
1602 );
1603 if let Some(f) = self.frames_mut().find(|f| f.account_id == *account_id) {
1604 f.contract_info.invalidate();
1605 }
1606 }
1607 } else {
1608 if !persist {
1609 self.transaction_meter
1610 .absorb_weight_meter_only(mem::take(&mut self.first_frame.frame_meter));
1611 return;
1612 }
1613
1614 let mut contract = self.first_frame.contract_info.as_contract();
1615 self.transaction_meter.absorb_all_meters(
1616 mem::take(&mut self.first_frame.frame_meter),
1617 &self.first_frame.account_id,
1618 contract.as_deref_mut(),
1619 );
1620
1621 if let Some(contract) = contract {
1622 AccountInfo::<T>::insert_contract(
1623 &T::AddressMapper::to_address(&self.first_frame.account_id),
1624 contract.clone(),
1625 );
1626 }
1627 let contracts_created = mem::take(&mut self.first_frame.contracts_created);
1629 let contracts_to_destroy = mem::take(&mut self.first_frame.contracts_to_be_destroyed);
1630 for (contract_account, args) in contracts_to_destroy {
1631 if args.only_if_same_tx && !contracts_created.contains(&contract_account) {
1632 continue;
1633 }
1634 Self::do_terminate(
1635 &mut self.transaction_meter,
1636 self.exec_config,
1637 &contract_account,
1638 &self.origin,
1639 &args,
1640 )
1641 .ok();
1642 }
1643 }
1644 }
1645
1646 fn transfer<S: State>(
1659 origin: &Origin<T>,
1660 from: &T::AccountId,
1661 to: &T::AccountId,
1662 value: U256,
1663 preservation: Preservation,
1664 meter: &mut ResourceMeter<T, S>,
1665 exec_config: &ExecConfig<T>,
1666 ) -> DispatchResult {
1667 let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1668 .map_err(|_| Error::<T>::BalanceConversionFailed)?;
1669 if value.is_zero() {
1670 return Ok(());
1671 }
1672
1673 if <System<T>>::account_exists(to) {
1674 return transfer_with_dust::<T>(from, to, value, preservation);
1675 }
1676
1677 let origin = origin.account_id()?;
1678 let ed = <T as Config>::Currency::minimum_balance();
1679 let is_eth_tx = exec_config.collect_deposit_from_hold.is_some();
1680 with_transaction(|| -> TransactionOutcome<DispatchResult> {
1681 match meter
1682 .charge_deposit(&StorageDeposit::Charge(ed))
1683 .and_then(|_| {
1684 if is_eth_tx {
1685 let credit = T::FeeInfo::withdraw_txfee(ed)
1686 .ok_or(Error::<T>::StorageDepositNotEnoughFunds)?;
1687 T::Currency::resolve(to, credit)
1688 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
1689 Ok(())
1690 } else {
1691 T::Currency::transfer(origin, to, ed, Preservation::Preserve)
1692 .map(|_| ())
1693 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds.into())
1694 }
1695 })
1696 .and_then(|_| transfer_with_dust::<T>(from, to, value, preservation))
1697 {
1698 Ok(_) => TransactionOutcome::Commit(Ok(())),
1699 Err(err) => TransactionOutcome::Rollback(Err(err)),
1700 }
1701 })
1702 }
1703
1704 fn transfer_from_origin<S: State>(
1706 origin: &Origin<T>,
1707 from: &Origin<T>,
1708 to: &T::AccountId,
1709 value: U256,
1710 meter: &mut ResourceMeter<T, S>,
1711 exec_config: &ExecConfig<T>,
1712 ) -> ExecResult {
1713 let from = match from {
1716 Origin::Signed(caller) => caller,
1717 Origin::Root if value.is_zero() => return Ok(Default::default()),
1718 Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1719 };
1720 Self::transfer(origin, from, to, value, Preservation::Preserve, meter, exec_config)
1721 .map(|_| Default::default())
1722 .map_err(Into::into)
1723 }
1724
1725 fn do_terminate(
1727 transaction_meter: &mut TransactionMeter<T>,
1728 exec_config: &ExecConfig<T>,
1729 contract_account: &T::AccountId,
1730 origin: &Origin<T>,
1731 args: &TerminateArgs<T>,
1732 ) -> Result<(), DispatchError> {
1733 let contract_address = T::AddressMapper::to_address(contract_account);
1734
1735 let origin: Origin<T> = match origin {
1738 Origin::Signed(o) => Origin::Signed(o.clone()),
1739 Origin::Root => Origin::from_account_id(crate::Pallet::<T>::account_id()),
1740 };
1741
1742 let mut delete_contract = |trie_id: &TrieId, code_hash: &H256| {
1743 let refund =
1745 T::Deposit::refund_all(&contract_account, exec_config.funds(origin.account_id()?))?;
1746
1747 System::<T>::dec_consumers(&contract_account);
1749
1750 T::Deposit::destroy_contract(contract_account)?;
1752
1753 let balance = <Contracts<T>>::convert_native_to_evm(<AccountInfo<T>>::total_balance(
1757 contract_address.into(),
1758 ));
1759 Self::transfer(
1760 &origin,
1761 contract_account,
1762 &args.beneficiary,
1763 balance,
1764 Preservation::Expendable,
1765 transaction_meter,
1766 exec_config,
1767 )?;
1768
1769 let _code_removed = <CodeInfo<T>>::decrement_refcount(*code_hash)?;
1771
1772 ContractInfo::<T>::queue_for_deletion(trie_id.clone(), contract_account.clone());
1774 AccountInfoOf::<T>::remove(contract_address);
1775 ImmutableDataOf::<T>::remove(contract_address);
1776
1777 transaction_meter.terminate(contract_account.clone(), refund);
1780
1781 Ok(())
1782 };
1783
1784 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1788 match delete_contract(&args.trie_id, &args.code_hash) {
1789 Ok(()) => {
1790 log::trace!(target: LOG_TARGET, "Terminated {contract_address:?}");
1791 TransactionOutcome::Commit(Ok(()))
1792 },
1793 Err(e) => {
1794 log::debug!(target: LOG_TARGET, "Contract at {contract_address:?} failed to terminate: {e:?}");
1795 TransactionOutcome::Rollback(Err(e))
1796 },
1797 }
1798 })
1799 }
1800
1801 fn top_frame(&self) -> &Frame<T> {
1803 top_frame!(self)
1804 }
1805
1806 fn top_frame_mut(&mut self) -> &mut Frame<T> {
1808 top_frame_mut!(self)
1809 }
1810
1811 fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1815 core::iter::once(&self.first_frame).chain(&self.frames).rev()
1816 }
1817
1818 fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1820 core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1821 }
1822
1823 fn allows_reentry(&self, id: &T::AccountId) -> bool {
1825 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1826 }
1827
1828 fn account_balance(&self, who: &T::AccountId) -> U256 {
1830 let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
1831 crate::Pallet::<T>::convert_native_to_evm(balance)
1832 }
1833
1834 #[cfg(feature = "runtime-benchmarks")]
1837 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
1838 self.top_frame_mut().entry_point = export;
1839 }
1840
1841 #[cfg(feature = "runtime-benchmarks")]
1842 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
1843 self.block_number = block_number;
1844 }
1845
1846 fn block_hash(&self, block_number: U256) -> Option<H256> {
1847 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
1848 return None;
1849 };
1850 if block_number >= self.block_number {
1851 return None;
1852 }
1853 if block_number < self.block_number.saturating_sub(256u32.into()) {
1854 return None;
1855 }
1856
1857 match crate::Pallet::<T>::eth_block_hash_from_number(block_number.into()) {
1861 Some(hash) => Some(hash),
1862 None => {
1863 use codec::Decode;
1864 let block_hash = System::<T>::block_hash(&block_number);
1865 Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
1866 },
1867 }
1868 }
1869
1870 fn has_contract_info(&self) -> bool {
1873 let address = self.address();
1874 let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
1875 if let Some(precompile) = precompile {
1876 return precompile.has_contract_info();
1877 }
1878 true
1879 }
1880
1881 fn with_transient_storage_mut<R, F: FnOnce(&mut TransientStorage<T>) -> R>(
1882 &mut self,
1883 f: F,
1884 ) -> R {
1885 if let Some(transient) = &self.exec_config.test_env_transient_storage {
1886 f(&mut transient.borrow_mut())
1887 } else {
1888 f(&mut self.transient_storage)
1889 }
1890 }
1891 fn with_transient_storage<R, F: FnOnce(&TransientStorage<T>) -> R>(&self, f: F) -> R {
1892 if let Some(transient) = &self.exec_config.test_env_transient_storage {
1893 f(&transient.borrow())
1894 } else {
1895 f(&self.transient_storage)
1896 }
1897 }
1898}
1899
1900impl<'a, T, E> Ext for Stack<'a, T, E>
1901where
1902 T: Config,
1903 E: Executable<T>,
1904{
1905 fn delegate_call(
1906 &mut self,
1907 call_resources: &CallResources<T>,
1908 address: H160,
1909 input_data: Vec<u8>,
1910 ) -> Result<(), ExecError> {
1911 *self.last_frame_output_mut() = Default::default();
1914
1915 let top_frame = self.top_frame_mut();
1916 let mut contract_info = top_frame.contract_info().clone();
1920 top_frame.frame_meter.apply_pending_storage_changes(&mut contract_info);
1921 let account_id = top_frame.account_id.clone();
1922 let value = top_frame.value_transferred;
1923 if let Some(executable) = self.push_frame(
1924 FrameArgs::Call {
1925 dest: account_id,
1926 cached_info: Some(contract_info),
1927 delegated_call: Some(DelegateInfo {
1928 caller: self.caller().clone(),
1929 callee: address,
1930 }),
1931 },
1932 value,
1933 call_resources,
1934 self.is_read_only(),
1935 &input_data,
1936 )? {
1937 self.run(executable, input_data)
1938 } else {
1939 Ok(())
1941 }
1942 }
1943
1944 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
1945 if_tracing(|tracer| {
1946 let addr = T::AddressMapper::to_address(self.account_id());
1947 tracer.terminate(
1948 addr,
1949 *beneficiary,
1950 self.top_frame()
1951 .frame_meter
1952 .eth_gas_left()
1953 .unwrap_or_default()
1954 .try_into()
1955 .unwrap_or_default(),
1956 crate::Pallet::<T>::evm_balance(&addr),
1957 );
1958 });
1959 let frame = top_frame_mut!(self);
1960 let info = frame.contract_info();
1961 let trie_id = info.trie_id.clone();
1962 let code_hash = info.code_hash;
1963 let contract_address = T::AddressMapper::to_address(&frame.account_id);
1964 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
1965
1966 Self::transfer(
1968 &self.origin,
1969 &frame.account_id,
1970 &beneficiary,
1971 <Contracts<T>>::evm_balance(&contract_address),
1972 Preservation::Preserve,
1973 &mut frame.frame_meter,
1974 self.exec_config,
1975 )?;
1976
1977 let account_id = frame.account_id.clone();
1979 self.top_frame_mut().contracts_to_be_destroyed.insert(
1980 account_id,
1981 TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: true },
1982 );
1983 Ok(CodeRemoved::Yes)
1984 }
1985
1986 fn own_code_hash(&mut self) -> &H256 {
1987 &self.top_frame_mut().contract_info().code_hash
1988 }
1989
1990 fn immutable_data_len(&mut self) -> u32 {
1991 self.top_frame_mut().contract_info().immutable_data_len()
1992 }
1993
1994 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
1995 if self.top_frame().entry_point == ExportedFunction::Constructor {
1996 return Err(Error::<T>::InvalidImmutableAccess.into());
1997 }
1998
1999 let address = self
2001 .top_frame()
2002 .delegate
2003 .as_ref()
2004 .map(|d| d.callee)
2005 .unwrap_or(T::AddressMapper::to_address(self.account_id()));
2006 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
2007 }
2008
2009 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
2010 let frame = self.top_frame_mut();
2011 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
2012 return Err(Error::<T>::InvalidImmutableAccess.into());
2013 }
2014 frame.contract_info().set_immutable_data_len(data.len() as u32);
2015 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
2016 Ok(())
2017 }
2018}
2019
2020impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
2021where
2022 T: Config,
2023 E: Executable<T>,
2024{
2025 fn instantiate(
2026 &mut self,
2027 call_resources: &CallResources<T>,
2028 mut code: Code,
2029 value: U256,
2030 input_data: Vec<u8>,
2031 salt: Option<&[u8; 32]>,
2032 ) -> Result<H160, ExecError> {
2033 *self.last_frame_output_mut() = Default::default();
2036
2037 let sender = self.top_frame().account_id.clone();
2038 let executable = {
2039 let executable = match &mut code {
2040 Code::Upload(initcode) => {
2041 if !T::AllowEVMBytecode::get() {
2042 return Err(<Error<T>>::CodeRejected.into());
2043 }
2044 ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
2045 let initcode = crate::tracing::if_tracing(|_| initcode.clone())
2046 .unwrap_or_else(|| mem::take(initcode));
2047 E::from_evm_init_code(initcode, sender.clone())?
2048 },
2049 Code::Existing(hash) => {
2050 let executable = E::from_storage(*hash, self.frame_meter_mut())?;
2051 ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
2052 executable
2053 },
2054 };
2055 self.push_frame(
2056 FrameArgs::Instantiate {
2057 sender,
2058 executable,
2059 salt,
2060 input_data: input_data.as_ref(),
2061 },
2062 value,
2063 call_resources,
2064 self.is_read_only(),
2065 &input_data,
2066 )?
2067 };
2068 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
2069
2070 let account_id = self.top_frame().account_id.clone();
2072 self.top_frame_mut().contracts_created.insert(account_id);
2073
2074 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
2075 if_tracing(|t| t.instantiate_code(&code, salt));
2076 self.run(executable, input_data).map(|_| address)
2077 }
2078}
2079
2080impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
2081where
2082 T: Config,
2083 E: Executable<T>,
2084{
2085 type T = T;
2086
2087 fn call(
2088 &mut self,
2089 call_resources: &CallResources<T>,
2090 dest_addr: &H160,
2091 value: U256,
2092 input_data: Vec<u8>,
2093 allows_reentry: ReentrancyProtection,
2094 read_only: bool,
2095 ) -> Result<(), ExecError> {
2096 if allows_reentry == ReentrancyProtection::Strict {
2101 self.top_frame_mut().allows_reentry = false;
2102 }
2103
2104 *self.last_frame_output_mut() = Default::default();
2107
2108 let try_call = || {
2109 let is_read_only = read_only || self.is_read_only();
2111
2112 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2114 T::AddressMapper::to_fallback_account_id(dest_addr)
2115 } else {
2116 T::AddressMapper::to_account_id(dest_addr)
2117 };
2118
2119 if !self.allows_reentry(&dest) {
2120 return Err(<Error<T>>::ReentranceDenied.into());
2121 }
2122
2123 if allows_reentry == ReentrancyProtection::AllowNext {
2124 self.top_frame_mut().allows_reentry = false;
2125 }
2126
2127 let cached_info = self
2135 .frames()
2136 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2137 .and_then(|f| match &f.contract_info {
2138 CachedContract::Cached(contract) => {
2139 let mut contract_with_pending = contract.clone();
2140 f.frame_meter.apply_pending_storage_changes(&mut contract_with_pending);
2141 Some(contract_with_pending)
2142 },
2143 _ => None,
2144 });
2145
2146 if let Some(executable) = self.push_frame(
2147 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2148 value,
2149 call_resources,
2150 is_read_only,
2151 &input_data,
2152 )? {
2153 self.run(executable, input_data)
2154 } else {
2155 if_tracing(|t| {
2156 t.enter_child_span(
2157 T::AddressMapper::to_address(self.account_id()),
2158 T::AddressMapper::to_address(&dest),
2159 None,
2160 is_read_only,
2161 value,
2162 &input_data,
2163 Default::default(),
2164 );
2165 });
2166
2167 let snapshot = if_tracing(|_| top_frame!(self).frame_meter.snapshot());
2168
2169 let result = if let Some(mock_answer) =
2170 self.exec_config.mock_handler.as_ref().and_then(|handler| {
2171 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2172 }) {
2173 *self.last_frame_output_mut() = mock_answer.clone();
2174 Ok(mock_answer)
2175 } else if is_read_only && value.is_zero() {
2176 Ok(Default::default())
2177 } else if is_read_only {
2178 Err(Error::<T>::StateChangeDenied.into())
2179 } else {
2180 let account_id = self.account_id().clone();
2181 let frame = top_frame_mut!(self);
2182 Self::transfer_from_origin(
2183 &self.origin,
2184 &Origin::from_account_id(account_id),
2185 &dest,
2186 value,
2187 &mut frame.frame_meter,
2188 self.exec_config,
2189 )
2190 };
2191
2192 if_tracing(|t| {
2193 let snapshot = snapshot.as_ref().expect(
2194 "snapshot is taken inside if_tracing above; tracing state cannot \
2195 change mid-call, so it is Some whenever this closure runs; qed",
2196 );
2197 let (gas_used, weight_delta) =
2198 top_frame!(self).frame_meter.delta_since(snapshot);
2199 match result {
2200 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_delta),
2201 Err(e) => {
2202 t.exit_child_span_with_error(e.error.into(), gas_used, weight_delta)
2203 },
2204 }
2205 });
2206
2207 result.map(|_| ())
2208 }
2209 };
2210
2211 let result = try_call();
2213
2214 self.top_frame_mut().allows_reentry = true;
2216
2217 result
2218 }
2219
2220 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2221 self.with_transient_storage(|transient_storage| {
2222 transient_storage.read(self.account_id(), key)
2223 })
2224 }
2225
2226 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2227 self.with_transient_storage(|transient_storage| {
2228 transient_storage.read(self.account_id(), key).map(|value| value.len() as _)
2229 })
2230 }
2231
2232 fn set_transient_storage(
2233 &mut self,
2234 key: &Key,
2235 value: Option<Vec<u8>>,
2236 take_old: bool,
2237 ) -> Result<WriteOutcome, DispatchError> {
2238 let account_id = self.account_id().clone();
2239 self.with_transient_storage_mut(|transient_storage| {
2240 transient_storage.write(&account_id, key, value, take_old)
2241 })
2242 }
2243
2244 fn account_id(&self) -> &T::AccountId {
2245 &self.top_frame().account_id
2246 }
2247
2248 fn caller(&self) -> Origin<T> {
2249 if let Some(Ok(mock_caller)) = self
2250 .exec_config
2251 .mock_handler
2252 .as_ref()
2253 .and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2254 .map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2255 {
2256 return mock_caller;
2257 }
2258
2259 if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
2260 caller.clone()
2261 } else {
2262 self.frames()
2263 .nth(1)
2264 .map(|f| Origin::from_account_id(f.account_id.clone()))
2265 .unwrap_or(self.origin.clone())
2266 }
2267 }
2268
2269 fn caller_of_caller(&self) -> Origin<T> {
2270 let caller_of_caller_frame = match self.frames().nth(2) {
2272 None => return self.origin.clone(),
2273 Some(frame) => frame,
2274 };
2275 if let Some(DelegateInfo { caller, .. }) = &caller_of_caller_frame.delegate {
2276 caller.clone()
2277 } else {
2278 Origin::from_account_id(caller_of_caller_frame.account_id.clone())
2279 }
2280 }
2281
2282 fn origin(&self) -> &Origin<T> {
2283 if let Some(mock_origin) = self
2284 .exec_config
2285 .mock_handler
2286 .as_ref()
2287 .and_then(|mock_handler| mock_handler.mock_origin())
2288 {
2289 return mock_origin;
2290 }
2291
2292 &self.origin
2293 }
2294
2295 fn to_account_id(&self, address: &H160) -> T::AccountId {
2296 T::AddressMapper::to_account_id(address)
2297 }
2298
2299 fn code_hash(&self, address: &H160) -> H256 {
2300 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2301 self.exec_config
2302 .mock_handler
2303 .as_ref()
2304 .and_then(|handler| handler.mocked_code(*address))
2305 }) {
2306 return sp_io::hashing::keccak_256(code).into();
2307 }
2308
2309 <AccountInfo<T>>::load_contract(&address)
2310 .map(|contract| contract.code_hash)
2311 .unwrap_or_else(|| {
2312 if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) {
2313 return EMPTY_CODE_HASH;
2314 }
2315 H256::zero()
2316 })
2317 }
2318
2319 fn code_size(&self, address: &H160) -> u64 {
2320 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2321 self.exec_config
2322 .mock_handler
2323 .as_ref()
2324 .and_then(|handler| handler.mocked_code(*address))
2325 }) {
2326 return code.len() as u64;
2327 }
2328
2329 <AccountInfo<T>>::load_contract(&address)
2330 .and_then(|contract| CodeInfoOf::<T>::get(contract.code_hash))
2331 .map(|info| info.code_len())
2332 .unwrap_or_default()
2333 }
2334
2335 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2336 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2337 self.origin == caller
2338 }
2339
2340 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2341 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2343 }
2344
2345 fn balance(&self) -> U256 {
2346 self.account_balance(&self.top_frame().account_id)
2347 }
2348
2349 fn balance_of(&self, address: &H160) -> U256 {
2350 let balance =
2351 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2352 if_tracing(|tracer| {
2353 tracer.balance_read(address, balance);
2354 });
2355 balance
2356 }
2357
2358 fn value_transferred(&self) -> U256 {
2359 self.top_frame().value_transferred.into()
2360 }
2361
2362 fn now(&self) -> U256 {
2363 (self.timestamp / 1000u32.into()).into()
2364 }
2365
2366 fn minimum_balance(&self) -> U256 {
2367 let min = T::Currency::minimum_balance();
2368 crate::Pallet::<T>::convert_native_to_evm(min)
2369 }
2370
2371 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2372 let contract = T::AddressMapper::to_address(self.account_id());
2373 if_tracing(|tracer| {
2374 tracer.log_event(contract, &topics, &data);
2375 });
2376
2377 block_storage::capture_ethereum_log(&contract, &data, &topics);
2379
2380 Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2381 }
2382
2383 fn block_number(&self) -> U256 {
2384 self.block_number.into()
2385 }
2386
2387 fn block_hash(&self, block_number: U256) -> Option<H256> {
2388 self.block_hash(block_number)
2389 }
2390
2391 fn block_author(&self) -> H160 {
2392 Contracts::<Self::T>::block_author()
2393 }
2394
2395 fn gas_limit(&self) -> u64 {
2396 <Contracts<T>>::evm_block_gas_limit().saturated_into()
2397 }
2398
2399 fn chain_id(&self) -> u64 {
2400 <T as Config>::ChainId::get()
2401 }
2402
2403 fn gas_meter(&self) -> &FrameMeter<Self::T> {
2404 &self.top_frame().frame_meter
2405 }
2406
2407 #[inline]
2408 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2409 &mut self.top_frame_mut().frame_meter
2410 }
2411
2412 fn frame_meter(&self) -> &FrameMeter<Self::T> {
2413 &self.top_frame().frame_meter
2414 }
2415
2416 #[inline]
2417 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2418 &mut self.top_frame_mut().frame_meter
2419 }
2420
2421 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2422 secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2423 }
2424
2425 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2426 sp_io::crypto::sr25519_verify(
2427 &SR25519Signature::from(*signature),
2428 message,
2429 &SR25519Public::from(*pub_key),
2430 )
2431 }
2432
2433 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError> {
2434 Ok(ECDSAPublic::from(*pk)
2435 .to_eth_address()
2436 .or_else(|()| Err(Error::<T>::EcdsaRecoveryFailed))?)
2437 }
2438
2439 #[cfg(any(test, feature = "runtime-benchmarks"))]
2440 fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2441 self.top_frame_mut().contract_info()
2442 }
2443
2444 #[cfg(any(feature = "runtime-benchmarks", test))]
2445 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2446 &mut self.transient_storage
2447 }
2448
2449 fn is_read_only(&self) -> bool {
2450 self.top_frame().read_only
2451 }
2452
2453 fn is_delegate_call(&self) -> bool {
2454 self.top_frame().delegate.is_some()
2455 }
2456
2457 fn last_frame_output(&self) -> &ExecReturnValue {
2458 &self.top_frame().last_frame_output
2459 }
2460
2461 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2462 &mut self.top_frame_mut().last_frame_output
2463 }
2464
2465 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2466 let len = buf.len();
2467 if len == 0 {
2468 return;
2469 }
2470
2471 let code_hash = self.code_hash(address);
2472 let code = crate::PristineCode::<T>::get(&code_hash).unwrap_or_default();
2473
2474 let len = len.min(code.len().saturating_sub(code_offset));
2475 if len > 0 {
2476 buf[..len].copy_from_slice(&code[code_offset..code_offset + len]);
2477 }
2478
2479 buf[len..].fill(0);
2480 }
2481
2482 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2483 ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2484 let parent = self.frames_mut().nth(1).ok_or_else(|| Error::<T>::ContractNotFound)?;
2485 ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2486 ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2487
2488 let info = parent.contract_info();
2489 let trie_id = info.trie_id.clone();
2490 let code_hash = info.code_hash;
2491 let contract_address = T::AddressMapper::to_address(&parent.account_id);
2492 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2493
2494 let parent_account_id = parent.account_id.clone();
2495
2496 Self::transfer(
2498 &self.origin,
2499 &parent_account_id,
2500 &beneficiary,
2501 <Contracts<T>>::evm_balance(&contract_address),
2502 Preservation::Preserve,
2503 &mut top_frame_mut!(self).frame_meter,
2504 &self.exec_config,
2505 )?;
2506
2507 let args = TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: false };
2509 self.top_frame_mut().contracts_to_be_destroyed.insert(parent_account_id, args);
2510
2511 Ok(())
2512 }
2513
2514 fn effective_gas_price(&self) -> U256 {
2515 self.exec_config
2516 .effective_gas_price
2517 .unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2518 }
2519
2520 fn gas_left(&self) -> u64 {
2521 let frame = self.top_frame();
2522
2523 frame.frame_meter.eth_gas_left().unwrap_or_default().saturated_into::<u64>()
2524 }
2525
2526 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2527 assert!(self.has_contract_info());
2528 self.top_frame_mut().contract_info().read(key)
2529 }
2530
2531 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2532 assert!(self.has_contract_info());
2533 self.top_frame_mut().contract_info().size(key.into())
2534 }
2535
2536 fn set_storage(
2537 &mut self,
2538 key: &Key,
2539 value: Option<Vec<u8>>,
2540 take_old: bool,
2541 ) -> Result<WriteOutcome, DispatchError> {
2542 assert!(self.has_contract_info());
2543 let frame = self.top_frame_mut();
2544 frame.contract_info.get(&frame.account_id).write(
2545 key.into(),
2546 value,
2547 Some(&mut frame.frame_meter),
2548 take_old,
2549 )
2550 }
2551
2552 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult {
2553 assert!(self.has_contract_info());
2554 self.top_frame_mut().frame_meter.record_contract_storage_changes(diff)
2555 }
2556}
2557
2558pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2560 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2561}
2562
2563#[cfg(feature = "runtime-benchmarks")]
2564pub fn bench_do_terminate<T: Config>(
2565 transaction_meter: &mut TransactionMeter<T>,
2566 exec_config: &ExecConfig<T>,
2567 contract_account: &T::AccountId,
2568 origin: &Origin<T>,
2569 beneficiary: T::AccountId,
2570 trie_id: TrieId,
2571 code_hash: H256,
2572 only_if_same_tx: bool,
2573) -> Result<(), DispatchError> {
2574 Stack::<T, crate::ContractBlob<T>>::do_terminate(
2575 transaction_meter,
2576 exec_config,
2577 contract_account,
2578 origin,
2579 &TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx },
2580 )
2581}
2582
2583mod sealing {
2584 use super::*;
2585
2586 pub trait Sealed {}
2587 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2588
2589 #[cfg(test)]
2590 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2591}