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 access_list::{AccessEntry, AccessList, StorageAccessKind, StorageOp},
23 address::{self, AddressMapper},
24 deposit_payment::Deposit as _,
25 evm::{block_storage, fees::InfoT as _, transfer_with_dust},
26 limits,
27 metering::{ChargedAmount, Diff, FrameMeter, ResourceMeter, State, Token, TransactionMeter},
28 precompiles::{All as AllPrecompiles, Instance as PrecompileInstance, Precompiles},
29 primitives::{ExecConfig, ExecReturnValue, StorageDeposit},
30 runtime_decl_for_revive_api::{Decode, Encode, TypeInfo},
31 storage::{AccountIdOrAddress, WriteOutcome},
32 tracing::if_tracing,
33 transient_storage::TransientStorage,
34};
35use alloc::{
36 collections::{BTreeMap, BTreeSet},
37 vec::Vec,
38};
39use core::{cmp, fmt::Debug, marker::PhantomData, mem, ops::ControlFlow};
40use frame_support::{
41 Blake2_128Concat, BoundedVec, DebugNoBound, StorageHasher,
42 crypto::ecdsa::ECDSAExt,
43 dispatch::DispatchResult,
44 ensure,
45 storage::{TransactionOutcome, with_transaction},
46 traits::{
47 Time,
48 fungible::{Balanced as _, Inspect, Mutate},
49 tokens::Preservation,
50 },
51 weights::Weight,
52};
53use frame_system::{
54 Pallet as System, RawOrigin,
55 pallet_prelude::{BlockNumberFor, OriginFor},
56};
57use sp_core::{
58 ConstU32, Get, H160, H256, U256,
59 ecdsa::Public as ECDSAPublic,
60 sr25519::{Public as SR25519Public, Signature as SR25519Signature},
61};
62use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
63use sp_runtime::{
64 DispatchError, SaturatedConversion,
65 traits::{BadOrigin, Saturating, TrailingZeroInput, Zero},
66};
67
68#[cfg(test)]
69mod tests;
70
71#[cfg(test)]
72pub mod mock_ext;
73
74pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
75pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
76pub type ExecResult = Result<ExecReturnValue, ExecError>;
77
78type VarSizedKey = BoundedVec<u8, ConstU32<{ limits::STORAGE_KEY_BYTES }>>;
80
81const 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";
82
83pub const EMPTY_CODE_HASH: H256 =
85 H256(sp_core::hex2array!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
86
87#[derive(Debug)]
89pub enum Key {
90 Fix([u8; 32]),
92 Var(VarSizedKey),
94}
95
96impl Key {
97 pub fn unhashed(&self) -> &[u8] {
99 match self {
100 Key::Fix(v) => v.as_ref(),
101 Key::Var(v) => v.as_ref(),
102 }
103 }
104
105 pub fn hash(&self) -> Vec<u8> {
107 match self {
108 Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
109 Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
110 }
111 }
112
113 pub fn from_fixed(v: [u8; 32]) -> Self {
114 Self::Fix(v)
115 }
116
117 pub fn try_from_var(v: Vec<u8>) -> Result<Self, ()> {
118 VarSizedKey::try_from(v).map(Self::Var).map_err(|_| ())
119 }
120}
121
122#[derive(Copy, Clone, PartialEq, Debug)]
128pub enum ReentrancyProtection {
129 AllowReentry,
131 Strict,
134 AllowNext,
142}
143
144#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
150pub enum ErrorOrigin {
151 Caller,
156 Callee,
158}
159
160#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
162pub struct ExecError {
163 pub error: DispatchError,
165 pub origin: ErrorOrigin,
167}
168
169impl<T: Into<DispatchError>> From<T> for ExecError {
170 fn from(error: T) -> Self {
171 Self { error: error.into(), origin: ErrorOrigin::Caller }
172 }
173}
174
175#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, DebugNoBound)]
177pub enum Origin<T: Config> {
178 Root,
179 Signed(T::AccountId),
180}
181
182impl<T: Config> Origin<T> {
183 pub fn from_account_id(account_id: T::AccountId) -> Self {
185 Origin::Signed(account_id)
186 }
187
188 pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
190 match o.into() {
191 Ok(RawOrigin::Root) => Ok(Self::Root),
192 Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
193 _ => Err(BadOrigin.into()),
194 }
195 }
196
197 pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
199 match self {
200 Origin::Signed(id) => Ok(id),
201 Origin::Root => Err(DispatchError::RootNotAllowed),
202 }
203 }
204
205 fn ensure_mapped(&self) -> DispatchResult {
210 match self {
211 Self::Root => Ok(()),
212 Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()),
213 Self::Signed(_) => Err(<Error<T>>::AccountUnmapped.into()),
214 }
215 }
216}
217
218#[derive(DebugNoBound)]
221pub enum CallResources<T: Config> {
222 NoLimits,
224 WeightDeposit { weight: Weight, deposit_limit: BalanceOf<T> },
226 Ethereum { gas: BalanceOf<T>, add_stipend: bool },
228}
229
230impl<T: Config> CallResources<T> {
231 pub fn from_weight_and_deposit(weight: Weight, deposit_limit: U256) -> Self {
233 Self::WeightDeposit {
234 weight,
235 deposit_limit: deposit_limit.saturated_into::<BalanceOf<T>>(),
236 }
237 }
238
239 pub fn from_ethereum_gas(gas: U256, add_stipend: bool) -> Self {
241 Self::Ethereum { gas: gas.saturated_into::<BalanceOf<T>>(), add_stipend }
242 }
243}
244
245impl<T: Config> Default for CallResources<T> {
246 fn default() -> Self {
247 Self::WeightDeposit { weight: Default::default(), deposit_limit: Default::default() }
248 }
249}
250
251struct TerminateArgs<T: Config> {
253 beneficiary: T::AccountId,
255 trie_id: TrieId,
257 code_hash: H256,
259 only_if_same_tx: bool,
261}
262
263pub trait Ext: PrecompileWithInfoExt {
265 fn delegate_call(
269 &mut self,
270 call_resources: &CallResources<Self::T>,
271 address: H160,
272 input_data: Vec<u8>,
273 ) -> Result<(), ExecError>;
274
275 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError>;
282
283 #[allow(dead_code)]
285 fn own_code_hash(&mut self) -> &H256;
286
287 fn immutable_data_len(&mut self) -> u32;
292
293 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError>;
297
298 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError>;
304}
305
306pub trait PrecompileWithInfoExt: PrecompileExt {
308 fn instantiate(
314 &mut self,
315 limits: &CallResources<Self::T>,
316 code: Code,
317 value: U256,
318 input_data: Vec<u8>,
319 salt: Option<&[u8; 32]>,
320 ) -> Result<H160, ExecError>;
321}
322
323pub trait PrecompileExt: sealing::Sealed {
325 type T: Config;
326
327 fn charge(&mut self, weight: Weight) -> Result<ChargedAmount, DispatchError> {
329 self.frame_meter_mut().charge_weight_token(RuntimeCosts::Precompile(weight))
330 }
331
332 fn adjust_gas(&mut self, charged: ChargedAmount, actual_weight: Weight) {
335 self.frame_meter_mut()
336 .adjust_weight(charged, RuntimeCosts::Precompile(actual_weight));
337 }
338
339 #[inline]
342 fn charge_or_halt<Tok: Token<Self::T>>(
343 &mut self,
344 token: Tok,
345 ) -> ControlFlow<crate::vm::evm::Halt, ChargedAmount> {
346 self.frame_meter_mut().charge_or_halt(token)
347 }
348
349 fn call(
351 &mut self,
352 call_resources: &CallResources<Self::T>,
353 to: &H160,
354 value: U256,
355 input_data: Vec<u8>,
356 reentrancy: ReentrancyProtection,
357 read_only: bool,
358 ) -> Result<(), ExecError>;
359
360 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>>;
365
366 fn get_transient_storage_size(&self, key: &Key) -> Option<u32>;
371
372 fn set_transient_storage(
375 &mut self,
376 key: &Key,
377 value: Option<Vec<u8>>,
378 take_old: bool,
379 ) -> Result<WriteOutcome, DispatchError>;
380
381 fn caller(&self) -> Origin<Self::T>;
383
384 fn caller_of_caller(&self) -> Origin<Self::T>;
386
387 fn origin(&self) -> &Origin<Self::T>;
389
390 fn to_account_id(&self, address: &H160) -> AccountIdOf<Self::T>;
392
393 fn code_hash(&self, address: &H160) -> H256;
396
397 fn code_size(&self, address: &H160) -> u64;
399
400 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool;
402
403 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool;
405
406 fn origin_is_root(&self) -> bool;
411
412 fn account_id(&self) -> &AccountIdOf<Self::T>;
414
415 fn address(&self) -> H160 {
417 <Self::T as Config>::AddressMapper::to_address(self.account_id())
418 }
419
420 fn balance(&self) -> U256;
424
425 fn balance_of(&self, address: &H160) -> U256;
429
430 fn value_transferred(&self) -> U256;
432
433 fn now(&self) -> U256;
435
436 fn minimum_balance(&self) -> U256;
438
439 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
443
444 fn block_number(&self) -> U256;
446
447 fn block_hash(&self, block_number: U256) -> Option<H256>;
450
451 fn block_author(&self) -> H160;
453
454 fn gas_limit(&self) -> u64;
456
457 fn chain_id(&self) -> u64;
459
460 #[deprecated(note = "Renamed to `frame_meter`; this alias will be removed in future versions")]
462 fn gas_meter(&self) -> &FrameMeter<Self::T>;
463
464 #[deprecated(
466 note = "Renamed to `frame_meter_mut`; this alias will be removed in future versions"
467 )]
468 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
469
470 fn frame_meter(&self) -> &FrameMeter<Self::T>;
472
473 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
475
476 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
478
479 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
481
482 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError>;
484
485 #[cfg(any(test, feature = "runtime-benchmarks"))]
487 fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
488
489 #[cfg(any(feature = "runtime-benchmarks", test))]
493 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
494
495 fn is_read_only(&self) -> bool;
497
498 fn is_delegate_call(&self) -> bool;
500
501 fn last_frame_output(&self) -> &ExecReturnValue;
503
504 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
506
507 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize);
515
516 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError>;
525
526 fn effective_gas_price(&self) -> U256;
528
529 fn gas_left(&self) -> u64;
531
532 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
537
538 fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
543
544 fn set_storage(
547 &mut self,
548 key: &Key,
549 value: Option<Vec<u8>>,
550 take_old: bool,
551 ) -> Result<WriteOutcome, DispatchError>;
552
553 fn touch_storage_access(
560 &mut self,
561 transient: bool,
562 key: &Key,
563 op: StorageOp,
564 ) -> StorageAccessKind;
565
566 fn peek_storage_access(&self, transient: bool, key: &Key) -> StorageAccessKind;
569
570 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult;
572}
573
574#[derive(
576 Copy,
577 Clone,
578 PartialEq,
579 Eq,
580 Debug,
581 codec::Decode,
582 codec::Encode,
583 codec::MaxEncodedLen,
584 scale_info::TypeInfo,
585)]
586pub enum ExportedFunction {
587 Constructor,
589 Call,
591}
592
593pub trait Executable<T: Config>: Sized {
598 fn from_storage<S: State>(
603 code_hash: H256,
604 meter: &mut ResourceMeter<T, S>,
605 ) -> Result<Self, DispatchError>;
606
607 fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
609
610 fn execute<E: Ext<T = T>>(
620 self,
621 ext: &mut E,
622 function: ExportedFunction,
623 input_data: Vec<u8>,
624 ) -> ExecResult;
625
626 fn code_info(&self) -> &CodeInfo<T>;
628
629 fn code(&self) -> &[u8];
631
632 fn code_hash(&self) -> &H256;
634}
635
636pub struct Stack<'a, T: Config, E> {
642 origin: Origin<T>,
651 transaction_meter: &'a mut TransactionMeter<T>,
653 timestamp: MomentOf<T>,
655 block_number: BlockNumberFor<T>,
657 frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
660 first_frame: Frame<T>,
662 transient_storage: TransientStorage<T>,
664 access_list: AccessList,
666 exec_config: &'a ExecConfig<T>,
668 _phantom: PhantomData<E>,
670}
671
672struct Frame<T: Config> {
677 account_id: T::AccountId,
679 contract_info: CachedContract<T>,
681 value_transferred: U256,
683 entry_point: ExportedFunction,
685 frame_meter: FrameMeter<T>,
687 allows_reentry: bool,
689 read_only: bool,
691 delegate: Option<DelegateInfo<T>>,
694 last_frame_output: ExecReturnValue,
696 contracts_created: BTreeSet<T::AccountId>,
698 contracts_to_be_destroyed: BTreeMap<T::AccountId, TerminateArgs<T>>,
700}
701
702#[derive(Clone, DebugNoBound)]
705pub struct DelegateInfo<T: Config> {
706 pub caller: Origin<T>,
708 pub callee: H160,
710}
711
712enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
714 Executable(E),
716 Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
718}
719
720impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
721 fn as_executable(&self) -> Option<&E> {
722 if let Self::Executable(executable) = self { Some(executable) } else { None }
723 }
724
725 fn is_pvm(&self) -> bool {
726 match self {
727 Self::Executable(e) => e.code_info().is_pvm(),
728 _ => false,
729 }
730 }
731
732 fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
733 if let Self::Precompile { instance, .. } = self { Some(instance) } else { None }
734 }
735
736 #[cfg(any(feature = "runtime-benchmarks", test))]
737 fn into_executable(self) -> Option<E> {
738 if let Self::Executable(executable) = self { Some(executable) } else { None }
739 }
740}
741
742enum FrameArgs<'a, T: Config, E> {
746 Call {
747 dest: T::AccountId,
749 cached_info: Option<ContractInfo<T>>,
751 delegated_call: Option<DelegateInfo<T>>,
755 },
756 Instantiate {
757 sender: T::AccountId,
759 executable: E,
761 salt: Option<&'a [u8; 32]>,
763 input_data: &'a [u8],
765 },
766}
767
768enum CachedContract<T: Config> {
770 Cached(ContractInfo<T>),
772 Invalidated,
776 None,
778}
779
780impl<T: Config> Frame<T> {
781 fn contract_info(&mut self) -> &mut ContractInfo<T> {
783 self.contract_info.get(&self.account_id)
784 }
785}
786
787macro_rules! get_cached_or_panic_after_load {
791 ($c:expr) => {{
792 if let CachedContract::Cached(contract) = $c {
793 contract
794 } else {
795 panic!(
796 "It is impossible to remove a contract that is on the call stack;\
797 See implementations of terminate;\
798 Therefore fetching a contract will never fail while using an account id
799 that is currently active on the call stack;\
800 qed"
801 );
802 }
803 }};
804}
805
806macro_rules! top_frame {
811 ($stack:expr) => {
812 $stack.frames.last().unwrap_or(&$stack.first_frame)
813 };
814}
815
816macro_rules! top_frame_mut {
821 ($stack:expr) => {
822 $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
823 };
824}
825
826impl<T: Config> CachedContract<T> {
827 fn into_contract(self) -> Option<ContractInfo<T>> {
829 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
830 }
831
832 fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
834 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
835 }
836
837 fn load(&mut self, account_id: &T::AccountId) {
839 if let CachedContract::Invalidated = self &&
840 let Some(contract) =
841 AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
842 {
843 *self = CachedContract::Cached(contract);
844 }
845 }
846
847 fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
849 self.load(account_id);
850 get_cached_or_panic_after_load!(self)
851 }
852
853 fn invalidate(&mut self) {
855 if matches!(self, CachedContract::Cached(_)) {
856 *self = CachedContract::Invalidated;
857 }
858 }
859}
860
861impl<'a, T, E> Stack<'a, T, E>
862where
863 T: Config,
864 E: Executable<T>,
865{
866 pub fn run_call(
872 origin: Origin<T>,
873 dest: H160,
874 transaction_meter: &'a mut TransactionMeter<T>,
875 value: U256,
876 input_data: Vec<u8>,
877 exec_config: &ExecConfig<T>,
878 ) -> ExecResult {
879 let dest = T::AddressMapper::to_account_id(&dest);
880 if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
881 FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
882 origin.clone(),
883 transaction_meter,
884 value,
885 exec_config,
886 &input_data,
887 )? {
888 stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
889 } else {
890 if_tracing(|t| {
891 t.enter_child_span(
892 origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
893 T::AddressMapper::to_address(&dest),
894 None,
895 false,
896 value,
897 &input_data,
898 Default::default(),
899 );
900 });
901
902 let result = if let Some(mock_answer) =
903 exec_config.mock_handler.as_ref().and_then(|handler| {
904 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
905 }) {
906 Ok(mock_answer)
907 } else {
908 Self::transfer_from_origin(
909 &origin,
910 &origin,
911 &dest,
912 value,
913 transaction_meter,
914 exec_config,
915 )
916 };
917
918 if_tracing(|t| {
919 let gas_used =
920 transaction_meter.total_consumed_gas().try_into().unwrap_or(u64::MAX);
921 let weight_consumed = transaction_meter.weight_consumed();
922 match result {
923 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_consumed),
924 Err(e) => {
925 t.exit_child_span_with_error(e.error.into(), gas_used, weight_consumed)
926 },
927 }
928 });
929
930 log::trace!(target: LOG_TARGET, "call finished with: {result:?}");
931
932 result
933 }
934 }
935
936 pub fn run_instantiate(
942 origin: T::AccountId,
943 executable: E,
944 transaction_meter: &'a mut TransactionMeter<T>,
945 value: U256,
946 input_data: Vec<u8>,
947 salt: Option<&[u8; 32]>,
948 exec_config: &ExecConfig<T>,
949 ) -> Result<(H160, ExecReturnValue), ExecError> {
950 let deployer = T::AddressMapper::to_address(&origin);
951 let (mut stack, executable) = Stack::<'_, T, E>::new(
952 FrameArgs::Instantiate {
953 sender: origin.clone(),
954 executable,
955 salt,
956 input_data: input_data.as_ref(),
957 },
958 Origin::from_account_id(origin),
959 transaction_meter,
960 value,
961 exec_config,
962 &input_data,
963 )?
964 .expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
965 let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
966 let result = stack
967 .run(executable, input_data)
968 .map(|_| (address, stack.first_frame.last_frame_output));
969 if let Ok((contract, output)) = &result &&
970 !output.did_revert()
971 {
972 Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract: *contract });
973 }
974 log::trace!(target: LOG_TARGET, "instantiate finished with: {result:?}");
975 result
976 }
977
978 #[cfg(any(feature = "runtime-benchmarks", test))]
979 pub fn bench_new_call(
980 dest: H160,
981 origin: Origin<T>,
982 transaction_meter: &'a mut TransactionMeter<T>,
983 value: BalanceOf<T>,
984 exec_config: &'a ExecConfig<T>,
985 read_only: bool,
986 delegate_call: bool,
987 ) -> (Self, E) {
988 let call = Self::new(
989 FrameArgs::Call {
990 dest: T::AddressMapper::to_account_id(&dest),
991 cached_info: None,
992 delegated_call: None,
993 },
994 origin,
995 transaction_meter,
996 value.into(),
997 exec_config,
998 &Default::default(),
999 )
1000 .unwrap()
1001 .unwrap();
1002 let mut stack = call.0;
1003 if read_only {
1004 stack.top_frame_mut().read_only = true;
1005 }
1006 if delegate_call {
1007 let frame = stack.top_frame_mut();
1008 frame.delegate = Some(DelegateInfo {
1009 caller: Origin::from_account_id(frame.account_id.clone()),
1010 callee: H160::zero(),
1011 });
1012 }
1013 (stack, call.1.into_executable().unwrap())
1014 }
1015
1016 fn new(
1021 args: FrameArgs<T, E>,
1022 origin: Origin<T>,
1023 transaction_meter: &'a mut TransactionMeter<T>,
1024 value: U256,
1025 exec_config: &'a ExecConfig<T>,
1026 input_data: &Vec<u8>,
1027 ) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1028 origin.ensure_mapped()?;
1029 let Some((first_frame, executable)) = Self::new_frame(
1030 args,
1031 value,
1032 transaction_meter,
1033 &CallResources::NoLimits,
1034 false,
1035 true,
1036 input_data,
1037 exec_config,
1038 )?
1039 else {
1040 return Ok(None);
1041 };
1042
1043 let mut timestamp = T::Time::now();
1044 let mut block_number = <frame_system::Pallet<T>>::block_number();
1045 if let Some(timestamp_override) =
1047 exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override)
1048 {
1049 block_number = block_number.saturating_add(1u32.into());
1050 let delta = 1000u32.into();
1052 timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override);
1053 }
1054
1055 let stack = Self {
1056 origin,
1057 transaction_meter,
1058 timestamp,
1059 block_number,
1060 first_frame,
1061 frames: Default::default(),
1062 transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
1063 access_list: AccessList::new(),
1064 exec_config,
1065 _phantom: Default::default(),
1066 };
1067 Ok(Some((stack, executable)))
1068 }
1069
1070 fn new_frame<S: State>(
1075 frame_args: FrameArgs<T, E>,
1076 value_transferred: U256,
1077 meter: &mut ResourceMeter<T, S>,
1078 call_resources: &CallResources<T>,
1079 read_only: bool,
1080 origin_is_caller: bool,
1081 input_data: &[u8],
1082 exec_config: &ExecConfig<T>,
1083 ) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1084 let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
1085 FrameArgs::Call { dest, cached_info, delegated_call } => {
1086 let address = T::AddressMapper::to_address(&dest);
1087 let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
1088
1089 let mut contract = match (cached_info, &precompile) {
1092 (Some(info), _) => CachedContract::Cached(info),
1093 (None, None) => {
1094 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
1095 CachedContract::Cached(info)
1096 } else {
1097 return Ok(None);
1098 }
1099 },
1100 (None, Some(precompile)) if precompile.has_contract_info() => {
1101 log::trace!(target: LOG_TARGET, "found precompile for address {address:?}");
1102 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
1103 CachedContract::Cached(info)
1104 } else {
1105 let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
1106 CachedContract::Cached(info)
1107 }
1108 },
1109 (None, Some(_)) => CachedContract::None,
1110 };
1111
1112 let delegated_call = delegated_call.or_else(|| {
1113 exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1114 mock_handler.mock_delegated_caller(address, input_data)
1115 })
1116 });
1117 let executable = if let Some(delegated_call) = &delegated_call {
1119 if let Some(precompile) =
1120 <AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
1121 {
1122 ExecutableOrPrecompile::Precompile {
1123 instance: precompile,
1124 _phantom: Default::default(),
1125 }
1126 } else {
1127 let Some(info) = AccountInfo::<T>::load_contract(&delegated_call.callee)
1128 else {
1129 return Ok(None);
1130 };
1131 let executable = E::from_storage(info.code_hash, meter)?;
1132 ExecutableOrPrecompile::Executable(executable)
1133 }
1134 } else {
1135 if let Some(precompile) = precompile {
1136 ExecutableOrPrecompile::Precompile {
1137 instance: precompile,
1138 _phantom: Default::default(),
1139 }
1140 } else {
1141 let executable = E::from_storage(
1142 contract
1143 .as_contract()
1144 .expect("When not a precompile the contract was loaded above; qed")
1145 .code_hash,
1146 meter,
1147 )?;
1148 ExecutableOrPrecompile::Executable(executable)
1149 }
1150 };
1151
1152 (dest, contract, executable, delegated_call, ExportedFunction::Call)
1153 },
1154 FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1155 let deployer = T::AddressMapper::to_address(&sender);
1156 let account_nonce = <System<T>>::account_nonce(&sender);
1157 let address = if let Some(salt) = salt {
1158 address::create2(&deployer, executable.code(), input_data, salt)
1159 } else {
1160 use sp_runtime::Saturating;
1161 address::create1(
1162 &deployer,
1163 if origin_is_caller {
1166 account_nonce.saturating_sub(1u32.into()).saturated_into()
1167 } else {
1168 account_nonce.saturated_into()
1169 },
1170 )
1171 };
1172 let contract = ContractInfo::new(
1173 &address,
1174 <System<T>>::account_nonce(&sender),
1175 *executable.code_hash(),
1176 )?;
1177 (
1178 T::AddressMapper::to_fallback_account_id(&address),
1179 CachedContract::Cached(contract),
1180 ExecutableOrPrecompile::Executable(executable),
1181 None,
1182 ExportedFunction::Constructor,
1183 )
1184 },
1185 };
1186
1187 let frame = Frame {
1188 delegate,
1189 value_transferred,
1190 contract_info,
1191 account_id,
1192 entry_point,
1193 frame_meter: meter.new_nested(call_resources)?,
1194 allows_reentry: true,
1195 read_only,
1196 last_frame_output: Default::default(),
1197 contracts_created: Default::default(),
1198 contracts_to_be_destroyed: Default::default(),
1199 };
1200
1201 Ok(Some((frame, executable)))
1202 }
1203
1204 fn push_frame(
1206 &mut self,
1207 frame_args: FrameArgs<T, E>,
1208 value_transferred: U256,
1209 call_resources: &CallResources<T>,
1210 read_only: bool,
1211 input_data: &[u8],
1212 ) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1213 if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1214 return Err(Error::<T>::MaxCallDepthReached.into());
1215 }
1216
1217 let frame = self.top_frame();
1226 if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1227 (&frame.contract_info, frame.entry_point)
1228 {
1229 let mut contract_with_pending_changes = contract.clone();
1230 frame
1231 .frame_meter
1232 .apply_pending_storage_changes(&mut contract_with_pending_changes);
1233 AccountInfo::<T>::insert_contract(
1234 &T::AddressMapper::to_address(&frame.account_id),
1235 contract_with_pending_changes,
1236 );
1237 }
1238
1239 let frame = top_frame_mut!(self);
1240 let meter = &mut frame.frame_meter;
1241 if let Some((frame, executable)) = Self::new_frame(
1242 frame_args,
1243 value_transferred,
1244 meter,
1245 call_resources,
1246 read_only,
1247 false,
1248 input_data,
1249 self.exec_config,
1250 )? {
1251 if frame.entry_point == ExportedFunction::Constructor &&
1254 self.frames().any(|f| {
1255 f.entry_point == ExportedFunction::Constructor &&
1256 f.account_id == frame.account_id
1257 }) {
1258 return Err(Error::<T>::DuplicateContract.into());
1259 }
1260 self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1261 Ok(Some(executable))
1262 } else {
1263 Ok(None)
1264 }
1265 }
1266
1267 fn run(
1271 &mut self,
1272 executable: ExecutableOrPrecompile<T, E, Self>,
1273 input_data: Vec<u8>,
1274 ) -> Result<(), ExecError> {
1275 let frame = self.top_frame();
1276 let entry_point = frame.entry_point;
1277 let is_pvm = executable.is_pvm();
1278
1279 if_tracing(|tracer| {
1280 let (from, to) = match frame.delegate.as_ref() {
1283 Some(delegate) => {
1284 (T::AddressMapper::to_address(&frame.account_id), delegate.callee)
1285 },
1286 None => (
1287 self.caller()
1288 .account_id()
1289 .map(T::AddressMapper::to_address)
1290 .unwrap_or_default(),
1291 T::AddressMapper::to_address(&frame.account_id),
1292 ),
1293 };
1294 tracer.enter_child_span(
1295 from,
1296 to,
1297 frame.delegate.as_ref().map(|delegate| delegate.callee),
1298 frame.read_only,
1299 frame.value_transferred,
1300 &input_data,
1301 frame
1302 .frame_meter
1303 .eth_gas_left()
1304 .unwrap_or_default()
1305 .try_into()
1306 .unwrap_or_default(),
1307 );
1308 });
1309 let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1310 handler.mock_call(
1311 frame
1312 .delegate
1313 .as_ref()
1314 .map(|delegate| delegate.callee)
1315 .unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1316 &input_data,
1317 frame.value_transferred,
1318 )
1319 });
1320 let frames_len = self.frames.len();
1324 if let Some(caller_frame) = match frames_len {
1325 0 => None,
1326 1 => Some(&mut self.first_frame.last_frame_output),
1327 _ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1328 } {
1329 *caller_frame = Default::default();
1330 }
1331
1332 self.with_transient_storage_mut(|transient_storage| {
1333 transient_storage.start_transaction();
1334 });
1335 let is_first_frame = self.frames.is_empty();
1336 let access_list_checkpoints_len = self.access_list.frame_depth();
1337 if !is_first_frame {
1341 self.access_list.enter_frame();
1342 }
1343
1344 let do_transaction = || -> ExecResult {
1345 let caller = self.caller();
1346 let bump_nonce = self.exec_config.bump_nonce;
1347 let frame = top_frame_mut!(self);
1348 let account_id = &frame.account_id.clone();
1349
1350 if u32::try_from(input_data.len())
1351 .map(|len| len > limits::CALLDATA_BYTES)
1352 .unwrap_or(true)
1353 {
1354 Err(<Error<T>>::CallDataTooLarge)?;
1355 }
1356
1357 if entry_point == ExportedFunction::Constructor {
1360 if !frame_system::Pallet::<T>::account_exists(&account_id) {
1361 T::Deposit::init_contract(account_id)?;
1362 }
1363
1364 <System<T>>::inc_consumers(account_id)?;
1369
1370 <System<T>>::inc_account_nonce(account_id);
1372
1373 if bump_nonce || !is_first_frame {
1374 <System<T>>::inc_account_nonce(caller.account_id()?);
1377 }
1378 if is_pvm {
1380 <CodeInfo<T>>::increment_refcount(
1381 *executable
1382 .as_executable()
1383 .expect("Precompiles cannot be instantiated; qed")
1384 .code_hash(),
1385 )?;
1386 }
1387 }
1388
1389 if frame.delegate.is_none() {
1393 Self::transfer_from_origin(
1394 &self.origin,
1395 &caller,
1396 account_id,
1397 frame.value_transferred,
1398 &mut frame.frame_meter,
1399 self.exec_config,
1400 )?;
1401 }
1402
1403 if let Some(precompile) = executable.as_precompile() &&
1410 precompile.has_contract_info() &&
1411 frame.delegate.is_none() &&
1412 !<System<T>>::account_exists(account_id)
1413 {
1414 T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1417 <System<T>>::inc_consumers(account_id)?;
1419 }
1420
1421 let mut code_deposit = executable
1422 .as_executable()
1423 .map(|exec| exec.code_info().deposit())
1424 .unwrap_or_default();
1425
1426 let mut output = match executable {
1427 ExecutableOrPrecompile::Executable(executable) => {
1428 executable.execute(self, entry_point, input_data)
1429 },
1430 ExecutableOrPrecompile::Precompile { instance, .. } => {
1431 instance.call(input_data, self)
1432 },
1433 }
1434 .and_then(|output| {
1435 if u32::try_from(output.data.len())
1436 .map(|len| len > limits::CALLDATA_BYTES)
1437 .unwrap_or(true)
1438 {
1439 Err(<Error<T>>::ReturnDataTooLarge)?;
1440 }
1441 Ok(output)
1442 })
1443 .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1444
1445 if output.did_revert() {
1447 return Ok(output);
1448 }
1449
1450 let frame = if entry_point == ExportedFunction::Constructor {
1453 let frame = top_frame_mut!(self);
1454 if !is_pvm {
1457 let data = if crate::tracing::if_tracing(|_| {}).is_none() &&
1461 self.exec_config.is_dry_run.is_none()
1462 {
1463 core::mem::replace(&mut output.data, Default::default())
1464 } else {
1465 output.data.clone()
1466 };
1467
1468 let mut module = match &self.origin {
1472 Origin::Signed(o) => {
1473 crate::ContractBlob::<T>::from_evm_runtime_code(data, o.clone())?
1474 },
1475 Origin::Root => {
1476 crate::ContractBlob::<T>::from_evm_runtime_code_with_deposit(
1477 data,
1478 crate::Pallet::<T>::account_id(),
1479 Zero::zero(),
1480 )?
1481 },
1482 };
1483 module.store_code(&self.exec_config, &mut frame.frame_meter)?;
1484 code_deposit = module.code_info().deposit();
1485
1486 let contract_info = frame.contract_info();
1487 contract_info.code_hash = *module.code_hash();
1488 <CodeInfo<T>>::increment_refcount(contract_info.code_hash)?;
1489 }
1490
1491 let deposit = frame.contract_info().update_base_deposit(code_deposit);
1492 frame.frame_meter.charge_contract_deposit_and_transfer(
1493 frame.account_id.clone(),
1494 StorageDeposit::Charge(deposit),
1495 )?;
1496 frame
1497 } else {
1498 self.top_frame_mut()
1499 };
1500
1501 let contract = frame.contract_info.as_contract();
1505 frame
1506 .frame_meter
1507 .finalize(contract)
1508 .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1509
1510 Ok(output)
1511 };
1512
1513 let transaction_outcome =
1520 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1521 let output = if let Some(mock_answer) = mock_answer {
1522 Ok(mock_answer)
1523 } else {
1524 do_transaction()
1525 };
1526 match &output {
1527 Ok(result) if !result.did_revert() => {
1528 TransactionOutcome::Commit(Ok((true, output)))
1529 },
1530 _ => TransactionOutcome::Rollback(Ok((false, output))),
1531 }
1532 });
1533
1534 let (success, output) = match transaction_outcome {
1535 Ok((success, output)) => {
1537 if_tracing(|tracer| {
1538 let frame_meter = &top_frame!(self).frame_meter;
1539
1540 let gas_consumed = if is_first_frame {
1543 frame_meter.total_consumed_gas()
1544 } else {
1545 frame_meter.eth_gas_consumed()
1546 };
1547
1548 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1549 let weight_consumed = frame_meter.weight_consumed();
1550
1551 match &output {
1552 Ok(output) => {
1553 tracer.exit_child_span(&output, gas_consumed, weight_consumed)
1554 },
1555 Err(e) => tracer.exit_child_span_with_error(
1556 e.error.into(),
1557 gas_consumed,
1558 weight_consumed,
1559 ),
1560 }
1561 });
1562
1563 (success, output)
1564 },
1565 Err(error) => {
1568 if_tracing(|tracer| {
1569 let frame_meter = &top_frame!(self).frame_meter;
1570
1571 let gas_consumed = if is_first_frame {
1574 frame_meter.total_consumed_gas()
1575 } else {
1576 frame_meter.eth_gas_consumed()
1577 };
1578
1579 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1580 let weight_consumed = frame_meter.weight_consumed();
1581 tracer.exit_child_span_with_error(error.into(), gas_consumed, weight_consumed);
1582 });
1583
1584 (false, Err(error.into()))
1585 },
1586 };
1587 self.with_transient_storage_mut(|transient_storage| {
1588 if success {
1589 transient_storage.commit_transaction();
1590 } else {
1591 transient_storage.rollback_transaction();
1592 }
1593 });
1594 if is_first_frame {
1597 let m = self.access_list.metrics();
1598 log::trace!(
1599 target: LOG_TARGET,
1600 "access list metrics: size={size} cold={cold} hot={hot}",
1601 size = m.size, cold = m.cold, hot = m.hot,
1602 );
1603 } else if success {
1604 self.access_list.commit_frame();
1605 } else {
1606 self.access_list.rollback_frame();
1607 }
1608 debug_assert_eq!(
1609 self.access_list.frame_depth(),
1610 access_list_checkpoints_len,
1611 "this frame closed exactly the checkpoint it opened",
1612 );
1613 log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1614
1615 self.pop_frame(success);
1616 output.map(|output| {
1617 self.top_frame_mut().last_frame_output = output;
1618 })
1619 }
1620
1621 fn pop_frame(&mut self, persist: bool) {
1626 fn bank_pending_changes_and_invalidate<T: Config>(f: &mut Frame<T>) {
1633 let contract = f.account_id.clone();
1634 f.contract_info.load(&f.account_id);
1635 if let Some(info) = f.contract_info.as_contract() {
1636 f.frame_meter.bank_pending_storage_changes(contract, info);
1637 }
1638 f.contract_info.invalidate();
1645 }
1646
1647 let frame = self.frames.pop();
1651
1652 if let Some(mut frame) = frame {
1655 let account_id = &frame.account_id;
1656 let prev = top_frame_mut!(self);
1657
1658 if !persist {
1660 prev.frame_meter.absorb_weight_meter_only(frame.frame_meter);
1661 return;
1662 }
1663
1664 frame.contract_info.load(account_id);
1669 let mut contract = frame.contract_info.into_contract();
1670 prev.frame_meter
1671 .absorb_all_meters(frame.frame_meter, account_id, contract.as_mut());
1672
1673 prev.contracts_created.extend(frame.contracts_created);
1675 prev.contracts_to_be_destroyed.extend(frame.contracts_to_be_destroyed);
1676
1677 if let Some(contract) = contract {
1678 AccountInfo::<T>::insert_contract(
1683 &T::AddressMapper::to_address(account_id),
1684 contract,
1685 );
1686 if let Some(f) = self.frames_mut().find(|f| f.account_id == *account_id) {
1687 bank_pending_changes_and_invalidate(f);
1689 }
1690 }
1691 } else {
1692 if !persist {
1693 self.transaction_meter
1694 .absorb_weight_meter_only(mem::take(&mut self.first_frame.frame_meter));
1695 return;
1696 }
1697
1698 let mut contract = self.first_frame.contract_info.as_contract();
1699 self.transaction_meter.absorb_all_meters(
1700 mem::take(&mut self.first_frame.frame_meter),
1701 &self.first_frame.account_id,
1702 contract.as_deref_mut(),
1703 );
1704
1705 if let Some(contract) = contract {
1706 AccountInfo::<T>::insert_contract(
1707 &T::AddressMapper::to_address(&self.first_frame.account_id),
1708 contract.clone(),
1709 );
1710 }
1711 let contracts_created = mem::take(&mut self.first_frame.contracts_created);
1713 let contracts_to_destroy = mem::take(&mut self.first_frame.contracts_to_be_destroyed);
1714 for (contract_account, args) in contracts_to_destroy {
1715 if args.only_if_same_tx && !contracts_created.contains(&contract_account) {
1716 continue;
1717 }
1718 Self::do_terminate(
1719 &mut self.transaction_meter,
1720 self.exec_config,
1721 &contract_account,
1722 &self.origin,
1723 &args,
1724 )
1725 .ok();
1726 }
1727 }
1728 }
1729
1730 fn transfer<S: State>(
1743 origin: &Origin<T>,
1744 from: &T::AccountId,
1745 to: &T::AccountId,
1746 value: U256,
1747 preservation: Preservation,
1748 meter: &mut ResourceMeter<T, S>,
1749 exec_config: &ExecConfig<T>,
1750 ) -> DispatchResult {
1751 let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1752 .map_err(|_| Error::<T>::BalanceConversionFailed)?;
1753 if value.is_zero() {
1754 return Ok(());
1755 }
1756
1757 if <System<T>>::account_exists(to) {
1758 return transfer_with_dust::<T>(from, to, value, preservation);
1759 }
1760
1761 let origin = origin.account_id()?;
1762 let ed = <T as Config>::Currency::minimum_balance();
1763 let is_eth_tx = exec_config.collect_deposit_from_hold.is_some();
1764 with_transaction(|| -> TransactionOutcome<DispatchResult> {
1765 match Ok::<(), DispatchError>(())
1768 .and_then(|_| {
1769 if is_eth_tx {
1770 let credit = T::FeeInfo::withdraw_txfee(ed)
1771 .ok_or(Error::<T>::StorageDepositNotEnoughFunds)?;
1772 T::Currency::resolve(to, credit)
1773 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
1774 Ok(())
1775 } else {
1776 T::Currency::transfer(origin, to, ed, Preservation::Preserve)
1777 .map(|_| ())
1778 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds.into())
1779 }
1780 })
1781 .and_then(|_| transfer_with_dust::<T>(from, to, value, preservation))
1782 .and_then(|_| meter.charge_deposit(&StorageDeposit::Charge(ed)))
1783 {
1784 Ok(_) => TransactionOutcome::Commit(Ok(())),
1785 Err(err) => TransactionOutcome::Rollback(Err(err)),
1786 }
1787 })
1788 }
1789
1790 fn transfer_from_origin<S: State>(
1792 origin: &Origin<T>,
1793 from: &Origin<T>,
1794 to: &T::AccountId,
1795 value: U256,
1796 meter: &mut ResourceMeter<T, S>,
1797 exec_config: &ExecConfig<T>,
1798 ) -> ExecResult {
1799 let from = match from {
1802 Origin::Signed(caller) => caller,
1803 Origin::Root if value.is_zero() => return Ok(Default::default()),
1804 Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1805 };
1806 Self::transfer(origin, from, to, value, Preservation::Preserve, meter, exec_config)
1807 .map(|_| Default::default())
1808 .map_err(Into::into)
1809 }
1810
1811 fn do_terminate(
1813 transaction_meter: &mut TransactionMeter<T>,
1814 exec_config: &ExecConfig<T>,
1815 contract_account: &T::AccountId,
1816 origin: &Origin<T>,
1817 args: &TerminateArgs<T>,
1818 ) -> Result<(), DispatchError> {
1819 let contract_address = T::AddressMapper::to_address(contract_account);
1820
1821 let origin: Origin<T> = match origin {
1824 Origin::Signed(o) => Origin::Signed(o.clone()),
1825 Origin::Root => Origin::from_account_id(crate::Pallet::<T>::account_id()),
1826 };
1827
1828 let mut delete_contract = |trie_id: &TrieId, code_hash: &H256| {
1829 let refund =
1831 T::Deposit::refund_all(&contract_account, exec_config.funds(origin.account_id()?))?;
1832
1833 System::<T>::dec_consumers(&contract_account);
1835
1836 T::Deposit::destroy_contract(contract_account)?;
1838
1839 let balance = <Contracts<T>>::convert_native_to_evm(<AccountInfo<T>>::total_balance(
1843 contract_address.into(),
1844 ));
1845 Self::transfer(
1846 &origin,
1847 contract_account,
1848 &args.beneficiary,
1849 balance,
1850 Preservation::Expendable,
1851 transaction_meter,
1852 exec_config,
1853 )?;
1854
1855 let _code_removed = <CodeInfo<T>>::decrement_refcount(*code_hash)?;
1857
1858 ContractInfo::<T>::queue_for_deletion(trie_id.clone(), contract_account.clone());
1860 AccountInfoOf::<T>::remove(contract_address);
1861 ImmutableDataOf::<T>::remove(contract_address);
1862
1863 transaction_meter.terminate(contract_account.clone(), refund);
1866
1867 Ok(())
1868 };
1869
1870 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1874 match delete_contract(&args.trie_id, &args.code_hash) {
1875 Ok(()) => {
1876 log::trace!(target: LOG_TARGET, "Terminated {contract_address:?}");
1877 TransactionOutcome::Commit(Ok(()))
1878 },
1879 Err(e) => {
1880 log::debug!(target: LOG_TARGET, "Contract at {contract_address:?} failed to terminate: {e:?}");
1881 TransactionOutcome::Rollback(Err(e))
1882 },
1883 }
1884 })
1885 }
1886
1887 fn top_frame(&self) -> &Frame<T> {
1889 top_frame!(self)
1890 }
1891
1892 fn top_frame_mut(&mut self) -> &mut Frame<T> {
1894 top_frame_mut!(self)
1895 }
1896
1897 fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1901 core::iter::once(&self.first_frame).chain(&self.frames).rev()
1902 }
1903
1904 fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1906 core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1907 }
1908
1909 fn allows_reentry(&self, id: &T::AccountId) -> bool {
1911 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1912 }
1913
1914 fn account_balance(&self, who: &T::AccountId) -> U256 {
1916 let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
1917 crate::Pallet::<T>::convert_native_to_evm(balance)
1918 }
1919
1920 #[cfg(feature = "runtime-benchmarks")]
1923 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
1924 self.top_frame_mut().entry_point = export;
1925 }
1926
1927 #[cfg(feature = "runtime-benchmarks")]
1928 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
1929 self.block_number = block_number;
1930 }
1931
1932 fn block_hash(&self, block_number: U256) -> Option<H256> {
1933 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
1934 return None;
1935 };
1936 if block_number >= self.block_number {
1937 return None;
1938 }
1939 if block_number < self.block_number.saturating_sub(256u32.into()) {
1940 return None;
1941 }
1942
1943 match crate::Pallet::<T>::eth_block_hash_from_number(block_number.into()) {
1947 Some(hash) => Some(hash),
1948 None => {
1949 use codec::Decode;
1950 let block_hash = System::<T>::block_hash(&block_number);
1951 Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
1952 },
1953 }
1954 }
1955
1956 fn has_contract_info(&self) -> bool {
1959 let address = self.address();
1960 let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
1961 if let Some(precompile) = precompile {
1962 return precompile.has_contract_info();
1963 }
1964 true
1965 }
1966
1967 fn with_transient_storage_mut<R, F: FnOnce(&mut TransientStorage<T>) -> R>(
1968 &mut self,
1969 f: F,
1970 ) -> R {
1971 if let Some(transient) = &self.exec_config.test_env_transient_storage {
1972 f(&mut transient.borrow_mut())
1973 } else {
1974 f(&mut self.transient_storage)
1975 }
1976 }
1977 fn with_transient_storage<R, F: FnOnce(&TransientStorage<T>) -> R>(&self, f: F) -> R {
1978 if let Some(transient) = &self.exec_config.test_env_transient_storage {
1979 f(&transient.borrow())
1980 } else {
1981 f(&self.transient_storage)
1982 }
1983 }
1984}
1985
1986impl<'a, T, E> Ext for Stack<'a, T, E>
1987where
1988 T: Config,
1989 E: Executable<T>,
1990{
1991 fn delegate_call(
1992 &mut self,
1993 call_resources: &CallResources<T>,
1994 address: H160,
1995 input_data: Vec<u8>,
1996 ) -> Result<(), ExecError> {
1997 *self.last_frame_output_mut() = Default::default();
2000
2001 let top_frame = self.top_frame_mut();
2002 let mut contract_info = top_frame.contract_info().clone();
2006 top_frame.frame_meter.apply_pending_storage_changes(&mut contract_info);
2007 let account_id = top_frame.account_id.clone();
2008 let value = top_frame.value_transferred;
2009 if let Some(executable) = self.push_frame(
2010 FrameArgs::Call {
2011 dest: account_id,
2012 cached_info: Some(contract_info),
2013 delegated_call: Some(DelegateInfo {
2014 caller: self.caller().clone(),
2015 callee: address,
2016 }),
2017 },
2018 value,
2019 call_resources,
2020 self.is_read_only(),
2021 &input_data,
2022 )? {
2023 self.run(executable, input_data)
2024 } else {
2025 Ok(())
2027 }
2028 }
2029
2030 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
2031 if_tracing(|tracer| {
2032 let addr = T::AddressMapper::to_address(self.account_id());
2033 tracer.terminate(
2034 addr,
2035 *beneficiary,
2036 self.top_frame()
2037 .frame_meter
2038 .eth_gas_left()
2039 .unwrap_or_default()
2040 .try_into()
2041 .unwrap_or_default(),
2042 crate::Pallet::<T>::evm_balance(&addr),
2043 );
2044 });
2045 let frame = top_frame_mut!(self);
2046 let info = frame.contract_info();
2047 let trie_id = info.trie_id.clone();
2048 let code_hash = info.code_hash;
2049 let contract_address = T::AddressMapper::to_address(&frame.account_id);
2050 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2051
2052 Self::transfer(
2054 &self.origin,
2055 &frame.account_id,
2056 &beneficiary,
2057 <Contracts<T>>::evm_balance(&contract_address),
2058 Preservation::Preserve,
2059 &mut frame.frame_meter,
2060 self.exec_config,
2061 )?;
2062
2063 let account_id = frame.account_id.clone();
2065 self.top_frame_mut().contracts_to_be_destroyed.insert(
2066 account_id,
2067 TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: true },
2068 );
2069 Ok(CodeRemoved::Yes)
2070 }
2071
2072 fn own_code_hash(&mut self) -> &H256 {
2073 &self.top_frame_mut().contract_info().code_hash
2074 }
2075
2076 fn immutable_data_len(&mut self) -> u32 {
2077 self.top_frame_mut().contract_info().immutable_data_len()
2078 }
2079
2080 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
2081 if self.top_frame().entry_point == ExportedFunction::Constructor {
2082 return Err(Error::<T>::InvalidImmutableAccess.into());
2083 }
2084
2085 let address = self
2087 .top_frame()
2088 .delegate
2089 .as_ref()
2090 .map(|d| d.callee)
2091 .unwrap_or(T::AddressMapper::to_address(self.account_id()));
2092 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
2093 }
2094
2095 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
2096 let frame = self.top_frame_mut();
2097 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
2098 return Err(Error::<T>::InvalidImmutableAccess.into());
2099 }
2100 frame.contract_info().set_immutable_data_len(data.len() as u32);
2101 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
2102 Ok(())
2103 }
2104}
2105
2106impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
2107where
2108 T: Config,
2109 E: Executable<T>,
2110{
2111 fn instantiate(
2112 &mut self,
2113 call_resources: &CallResources<T>,
2114 mut code: Code,
2115 value: U256,
2116 input_data: Vec<u8>,
2117 salt: Option<&[u8; 32]>,
2118 ) -> Result<H160, ExecError> {
2119 *self.last_frame_output_mut() = Default::default();
2122
2123 let sender = self.top_frame().account_id.clone();
2124 let executable = {
2125 let executable = match &mut code {
2126 Code::Upload(initcode) => {
2127 if !T::AllowEVMBytecode::get() {
2128 return Err(<Error<T>>::CodeRejected.into());
2129 }
2130 ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
2131 let initcode = crate::tracing::if_tracing(|_| initcode.clone())
2132 .unwrap_or_else(|| mem::take(initcode));
2133 E::from_evm_init_code(initcode, sender.clone())?
2134 },
2135 Code::Existing(hash) => {
2136 let executable = E::from_storage(*hash, self.frame_meter_mut())?;
2137 ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
2138 executable
2139 },
2140 };
2141 self.push_frame(
2142 FrameArgs::Instantiate {
2143 sender,
2144 executable,
2145 salt,
2146 input_data: input_data.as_ref(),
2147 },
2148 value,
2149 call_resources,
2150 self.is_read_only(),
2151 &input_data,
2152 )?
2153 };
2154 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
2155
2156 let account_id = self.top_frame().account_id.clone();
2158 self.top_frame_mut().contracts_created.insert(account_id);
2159
2160 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
2161 if_tracing(|t| t.instantiate_code(&code, salt));
2162 self.run(executable, input_data).map(|_| address)
2163 }
2164}
2165
2166impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
2167where
2168 T: Config,
2169 E: Executable<T>,
2170{
2171 type T = T;
2172
2173 fn call(
2174 &mut self,
2175 call_resources: &CallResources<T>,
2176 dest_addr: &H160,
2177 value: U256,
2178 input_data: Vec<u8>,
2179 allows_reentry: ReentrancyProtection,
2180 read_only: bool,
2181 ) -> Result<(), ExecError> {
2182 if allows_reentry == ReentrancyProtection::Strict {
2187 self.top_frame_mut().allows_reentry = false;
2188 }
2189
2190 *self.last_frame_output_mut() = Default::default();
2193
2194 let try_call = || {
2195 let is_read_only = read_only || self.is_read_only();
2197
2198 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2200 T::AddressMapper::to_fallback_account_id(dest_addr)
2201 } else {
2202 T::AddressMapper::to_account_id(dest_addr)
2203 };
2204
2205 if !self.allows_reentry(&dest) {
2206 return Err(<Error<T>>::ReentranceDenied.into());
2207 }
2208
2209 if allows_reentry == ReentrancyProtection::AllowNext {
2210 self.top_frame_mut().allows_reentry = false;
2211 }
2212
2213 let cached_info = self
2221 .frames()
2222 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2223 .and_then(|f| match &f.contract_info {
2224 CachedContract::Cached(contract) => {
2225 let mut contract_with_pending = contract.clone();
2226 f.frame_meter.apply_pending_storage_changes(&mut contract_with_pending);
2227 Some(contract_with_pending)
2228 },
2229 _ => None,
2230 });
2231
2232 if let Some(executable) = self.push_frame(
2233 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2234 value,
2235 call_resources,
2236 is_read_only,
2237 &input_data,
2238 )? {
2239 self.run(executable, input_data)
2240 } else {
2241 if_tracing(|t| {
2242 t.enter_child_span(
2243 T::AddressMapper::to_address(self.account_id()),
2244 T::AddressMapper::to_address(&dest),
2245 None,
2246 is_read_only,
2247 value,
2248 &input_data,
2249 Default::default(),
2250 );
2251 });
2252
2253 let snapshot = if_tracing(|_| top_frame!(self).frame_meter.snapshot());
2254
2255 let result = if let Some(mock_answer) =
2256 self.exec_config.mock_handler.as_ref().and_then(|handler| {
2257 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2258 }) {
2259 *self.last_frame_output_mut() = mock_answer.clone();
2260 Ok(mock_answer)
2261 } else if is_read_only && value.is_zero() {
2262 Ok(Default::default())
2263 } else if is_read_only {
2264 Err(Error::<T>::StateChangeDenied.into())
2265 } else {
2266 let account_id = self.account_id().clone();
2267 let frame = top_frame_mut!(self);
2268 Self::transfer_from_origin(
2269 &self.origin,
2270 &Origin::from_account_id(account_id),
2271 &dest,
2272 value,
2273 &mut frame.frame_meter,
2274 self.exec_config,
2275 )
2276 };
2277
2278 if_tracing(|t| {
2279 let snapshot = snapshot.as_ref().expect(
2280 "snapshot is taken inside if_tracing above; tracing state cannot \
2281 change mid-call, so it is Some whenever this closure runs; qed",
2282 );
2283 let (gas_used, weight_delta) =
2284 top_frame!(self).frame_meter.delta_since(snapshot);
2285 match result {
2286 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_delta),
2287 Err(e) => {
2288 t.exit_child_span_with_error(e.error.into(), gas_used, weight_delta)
2289 },
2290 }
2291 });
2292
2293 result.map(|_| ())
2294 }
2295 };
2296
2297 let result = try_call();
2299
2300 self.top_frame_mut().allows_reentry = true;
2302
2303 result
2304 }
2305
2306 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2307 self.with_transient_storage(|transient_storage| {
2308 transient_storage.read(self.account_id(), key)
2309 })
2310 }
2311
2312 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2313 self.with_transient_storage(|transient_storage| {
2314 transient_storage.read(self.account_id(), key).map(|value| value.len() as _)
2315 })
2316 }
2317
2318 fn set_transient_storage(
2319 &mut self,
2320 key: &Key,
2321 value: Option<Vec<u8>>,
2322 take_old: bool,
2323 ) -> Result<WriteOutcome, DispatchError> {
2324 let account_id = self.account_id().clone();
2325 self.with_transient_storage_mut(|transient_storage| {
2326 transient_storage.write(&account_id, key, value, take_old)
2327 })
2328 }
2329
2330 fn account_id(&self) -> &T::AccountId {
2331 &self.top_frame().account_id
2332 }
2333
2334 fn caller(&self) -> Origin<T> {
2335 if let Some(Ok(mock_caller)) = self
2336 .exec_config
2337 .mock_handler
2338 .as_ref()
2339 .and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2340 .map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2341 {
2342 return mock_caller;
2343 }
2344
2345 if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
2346 caller.clone()
2347 } else {
2348 self.frames()
2349 .nth(1)
2350 .map(|f| Origin::from_account_id(f.account_id.clone()))
2351 .unwrap_or(self.origin.clone())
2352 }
2353 }
2354
2355 fn caller_of_caller(&self) -> Origin<T> {
2356 let caller_of_caller_frame = match self.frames().nth(2) {
2358 None => return self.origin.clone(),
2359 Some(frame) => frame,
2360 };
2361 if let Some(DelegateInfo { caller, .. }) = &caller_of_caller_frame.delegate {
2362 caller.clone()
2363 } else {
2364 Origin::from_account_id(caller_of_caller_frame.account_id.clone())
2365 }
2366 }
2367
2368 fn origin(&self) -> &Origin<T> {
2369 if let Some(mock_origin) = self
2370 .exec_config
2371 .mock_handler
2372 .as_ref()
2373 .and_then(|mock_handler| mock_handler.mock_origin())
2374 {
2375 return mock_origin;
2376 }
2377
2378 &self.origin
2379 }
2380
2381 fn to_account_id(&self, address: &H160) -> T::AccountId {
2382 T::AddressMapper::to_account_id(address)
2383 }
2384
2385 fn code_hash(&self, address: &H160) -> H256 {
2386 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2387 self.exec_config
2388 .mock_handler
2389 .as_ref()
2390 .and_then(|handler| handler.mocked_code(*address))
2391 }) {
2392 return sp_io::hashing::keccak_256(code).into();
2393 }
2394
2395 <AccountInfo<T>>::load_contract(&address)
2396 .map(|contract| contract.code_hash)
2397 .unwrap_or_else(|| {
2398 if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) {
2399 return EMPTY_CODE_HASH;
2400 }
2401 H256::zero()
2402 })
2403 }
2404
2405 fn code_size(&self, address: &H160) -> u64 {
2406 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2407 self.exec_config
2408 .mock_handler
2409 .as_ref()
2410 .and_then(|handler| handler.mocked_code(*address))
2411 }) {
2412 return code.len() as u64;
2413 }
2414
2415 <AccountInfo<T>>::load_contract(&address)
2416 .and_then(|contract| CodeInfoOf::<T>::get(contract.code_hash))
2417 .map(|info| info.code_len())
2418 .unwrap_or_default()
2419 }
2420
2421 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2422 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2423 self.origin == caller
2424 }
2425
2426 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2427 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2429 }
2430
2431 fn origin_is_root(&self) -> bool {
2432 self.origin == Origin::Root
2433 }
2434
2435 fn balance(&self) -> U256 {
2436 self.account_balance(&self.top_frame().account_id)
2437 }
2438
2439 fn balance_of(&self, address: &H160) -> U256 {
2440 let balance =
2441 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2442 if_tracing(|tracer| {
2443 tracer.balance_read(address, balance);
2444 });
2445 balance
2446 }
2447
2448 fn value_transferred(&self) -> U256 {
2449 self.top_frame().value_transferred.into()
2450 }
2451
2452 fn now(&self) -> U256 {
2453 (self.timestamp / 1000u32.into()).into()
2454 }
2455
2456 fn minimum_balance(&self) -> U256 {
2457 let min = T::Currency::minimum_balance();
2458 crate::Pallet::<T>::convert_native_to_evm(min)
2459 }
2460
2461 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2462 let contract = T::AddressMapper::to_address(self.account_id());
2463 if_tracing(|tracer| {
2464 let log_index = frame_system::Pallet::<Self::T>::event_count();
2465 tracer.log_event(contract, &topics, &data, log_index);
2466 });
2467
2468 block_storage::capture_ethereum_log(&contract, &data, &topics);
2470
2471 Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2472 }
2473
2474 fn block_number(&self) -> U256 {
2475 self.block_number.into()
2476 }
2477
2478 fn block_hash(&self, block_number: U256) -> Option<H256> {
2479 self.block_hash(block_number)
2480 }
2481
2482 fn block_author(&self) -> H160 {
2483 Contracts::<Self::T>::block_author()
2484 }
2485
2486 fn gas_limit(&self) -> u64 {
2487 <Contracts<T>>::evm_block_gas_limit().saturated_into()
2488 }
2489
2490 fn chain_id(&self) -> u64 {
2491 <T as Config>::ChainId::get()
2492 }
2493
2494 fn gas_meter(&self) -> &FrameMeter<Self::T> {
2495 &self.top_frame().frame_meter
2496 }
2497
2498 #[inline]
2499 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2500 &mut self.top_frame_mut().frame_meter
2501 }
2502
2503 fn frame_meter(&self) -> &FrameMeter<Self::T> {
2504 &self.top_frame().frame_meter
2505 }
2506
2507 #[inline]
2508 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2509 &mut self.top_frame_mut().frame_meter
2510 }
2511
2512 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2513 secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2514 }
2515
2516 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2517 sp_io::crypto::sr25519_verify(
2518 &SR25519Signature::from(*signature),
2519 message,
2520 &SR25519Public::from(*pub_key),
2521 )
2522 }
2523
2524 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError> {
2525 Ok(ECDSAPublic::from(*pk)
2526 .to_eth_address()
2527 .or_else(|()| Err(Error::<T>::EcdsaRecoveryFailed))?)
2528 }
2529
2530 #[cfg(any(test, feature = "runtime-benchmarks"))]
2531 fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2532 self.top_frame_mut().contract_info()
2533 }
2534
2535 #[cfg(any(feature = "runtime-benchmarks", test))]
2536 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2537 &mut self.transient_storage
2538 }
2539
2540 fn is_read_only(&self) -> bool {
2541 self.top_frame().read_only
2542 }
2543
2544 fn is_delegate_call(&self) -> bool {
2545 self.top_frame().delegate.is_some()
2546 }
2547
2548 fn last_frame_output(&self) -> &ExecReturnValue {
2549 &self.top_frame().last_frame_output
2550 }
2551
2552 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2553 &mut self.top_frame_mut().last_frame_output
2554 }
2555
2556 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2557 let len = buf.len();
2558 if len == 0 {
2559 return;
2560 }
2561
2562 let code_hash = self.code_hash(address);
2563 let code = crate::PristineCode::<T>::get(&code_hash).unwrap_or_default();
2564
2565 let len = len.min(code.len().saturating_sub(code_offset));
2566 if len > 0 {
2567 buf[..len].copy_from_slice(&code[code_offset..code_offset + len]);
2568 }
2569
2570 buf[len..].fill(0);
2571 }
2572
2573 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2574 ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2575 let parent = self.frames_mut().nth(1).ok_or_else(|| Error::<T>::ContractNotFound)?;
2576 ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2577 ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2578
2579 let info = parent.contract_info();
2580 let trie_id = info.trie_id.clone();
2581 let code_hash = info.code_hash;
2582 let contract_address = T::AddressMapper::to_address(&parent.account_id);
2583 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2584
2585 let parent_account_id = parent.account_id.clone();
2586
2587 Self::transfer(
2589 &self.origin,
2590 &parent_account_id,
2591 &beneficiary,
2592 <Contracts<T>>::evm_balance(&contract_address),
2593 Preservation::Preserve,
2594 &mut top_frame_mut!(self).frame_meter,
2595 &self.exec_config,
2596 )?;
2597
2598 let args = TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: false };
2600 self.top_frame_mut().contracts_to_be_destroyed.insert(parent_account_id, args);
2601
2602 Ok(())
2603 }
2604
2605 fn effective_gas_price(&self) -> U256 {
2606 self.exec_config
2607 .effective_gas_price
2608 .unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2609 }
2610
2611 fn gas_left(&self) -> u64 {
2612 let frame = self.top_frame();
2613
2614 frame.frame_meter.eth_gas_left().unwrap_or_default().saturated_into::<u64>()
2615 }
2616
2617 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2618 assert!(self.has_contract_info());
2619 self.top_frame_mut().contract_info().read(key)
2620 }
2621
2622 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2623 assert!(self.has_contract_info());
2624 self.top_frame_mut().contract_info().size(key.into())
2625 }
2626
2627 fn set_storage(
2628 &mut self,
2629 key: &Key,
2630 value: Option<Vec<u8>>,
2631 take_old: bool,
2632 ) -> Result<WriteOutcome, DispatchError> {
2633 assert!(self.has_contract_info());
2634 let frame = self.top_frame_mut();
2635 frame.contract_info.get(&frame.account_id).write(
2636 key.into(),
2637 value,
2638 Some(&mut frame.frame_meter),
2639 take_old,
2640 )
2641 }
2642
2643 fn touch_storage_access(
2644 &mut self,
2645 transient: bool,
2646 key: &Key,
2647 op: StorageOp,
2648 ) -> StorageAccessKind {
2649 if transient {
2650 return StorageAccessKind::Transient;
2651 }
2652 let address = self.address();
2653 StorageAccessKind::Persistent(
2654 self.access_list.touch(AccessEntry { address, slot: key.into() }, op),
2655 )
2656 }
2657
2658 fn peek_storage_access(&self, transient: bool, key: &Key) -> StorageAccessKind {
2659 if transient {
2660 return StorageAccessKind::Transient;
2661 }
2662 let address = self.address();
2663 StorageAccessKind::Persistent(
2664 self.access_list.peek(&AccessEntry { address, slot: key.into() }),
2665 )
2666 }
2667
2668 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult {
2669 assert!(self.has_contract_info());
2670 self.top_frame_mut().frame_meter.record_contract_storage_changes(diff)
2671 }
2672}
2673
2674pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2676 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2677}
2678
2679#[cfg(feature = "runtime-benchmarks")]
2680pub fn bench_do_terminate<T: Config>(
2681 transaction_meter: &mut TransactionMeter<T>,
2682 exec_config: &ExecConfig<T>,
2683 contract_account: &T::AccountId,
2684 origin: &Origin<T>,
2685 beneficiary: T::AccountId,
2686 trie_id: TrieId,
2687 code_hash: H256,
2688 only_if_same_tx: bool,
2689) -> Result<(), DispatchError> {
2690 Stack::<T, crate::ContractBlob<T>>::do_terminate(
2691 transaction_meter,
2692 exec_config,
2693 contract_account,
2694 origin,
2695 &TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx },
2696 )
2697}
2698
2699mod sealing {
2700 use super::*;
2701
2702 pub trait Sealed {}
2703 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2704
2705 #[cfg(test)]
2706 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2707}