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;
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 origin_is_root(&self) -> bool;
410
411 fn account_id(&self) -> &AccountIdOf<Self::T>;
413
414 fn address(&self) -> H160 {
416 <Self::T as Config>::AddressMapper::to_address(self.account_id())
417 }
418
419 fn balance(&self) -> U256;
423
424 fn balance_of(&self, address: &H160) -> U256;
428
429 fn value_transferred(&self) -> U256;
431
432 fn now(&self) -> U256;
434
435 fn minimum_balance(&self) -> U256;
437
438 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
442
443 fn block_number(&self) -> U256;
445
446 fn block_hash(&self, block_number: U256) -> Option<H256>;
449
450 fn block_author(&self) -> H160;
452
453 fn gas_limit(&self) -> u64;
455
456 fn chain_id(&self) -> u64;
458
459 #[deprecated(note = "Renamed to `frame_meter`; this alias will be removed in future versions")]
461 fn gas_meter(&self) -> &FrameMeter<Self::T>;
462
463 #[deprecated(
465 note = "Renamed to `frame_meter_mut`; this alias will be removed in future versions"
466 )]
467 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
468
469 fn frame_meter(&self) -> &FrameMeter<Self::T>;
471
472 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
474
475 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
477
478 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
480
481 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError>;
483
484 #[cfg(any(test, feature = "runtime-benchmarks"))]
486 fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
487
488 #[cfg(any(feature = "runtime-benchmarks", test))]
492 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
493
494 fn is_read_only(&self) -> bool;
496
497 fn is_delegate_call(&self) -> bool;
499
500 fn last_frame_output(&self) -> &ExecReturnValue;
502
503 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
505
506 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize);
514
515 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError>;
524
525 fn effective_gas_price(&self) -> U256;
527
528 fn gas_left(&self) -> u64;
530
531 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
536
537 fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
542
543 fn set_storage(
546 &mut self,
547 key: &Key,
548 value: Option<Vec<u8>>,
549 take_old: bool,
550 ) -> Result<WriteOutcome, DispatchError>;
551
552 fn touch_storage_access(
559 &mut self,
560 transient: bool,
561 key: &Key,
562 op: StorageOp,
563 ) -> StorageAccessKind;
564
565 fn peek_storage_access(&self, transient: bool, key: &Key) -> StorageAccessKind;
568
569 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult;
571}
572
573#[derive(
575 Copy,
576 Clone,
577 PartialEq,
578 Eq,
579 Debug,
580 codec::Decode,
581 codec::Encode,
582 codec::MaxEncodedLen,
583 scale_info::TypeInfo,
584)]
585pub enum ExportedFunction {
586 Constructor,
588 Call,
590}
591
592pub trait Executable<T: Config>: Sized {
597 fn from_storage<S: State>(
602 code_hash: H256,
603 meter: &mut ResourceMeter<T, S>,
604 ) -> Result<Self, DispatchError>;
605
606 fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
608
609 fn execute<E: Ext<T = T>>(
619 self,
620 ext: &mut E,
621 function: ExportedFunction,
622 input_data: Vec<u8>,
623 ) -> ExecResult;
624
625 fn code_info(&self) -> &CodeInfo<T>;
627
628 fn code(&self) -> &[u8];
630
631 fn code_hash(&self) -> &H256;
633}
634
635pub struct Stack<'a, T: Config, E> {
641 origin: Origin<T>,
650 transaction_meter: &'a mut TransactionMeter<T>,
652 timestamp: MomentOf<T>,
654 block_number: BlockNumberFor<T>,
656 frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
659 first_frame: Frame<T>,
661 transient_storage: TransientStorage<T>,
663 access_list: AccessList,
665 exec_config: &'a ExecConfig<T>,
667 _phantom: PhantomData<E>,
669}
670
671struct Frame<T: Config> {
676 account_id: T::AccountId,
678 contract_info: CachedContract<T>,
680 value_transferred: U256,
682 entry_point: ExportedFunction,
684 frame_meter: FrameMeter<T>,
686 allows_reentry: bool,
688 read_only: bool,
690 delegate: Option<DelegateInfo<T>>,
693 code_address: H160,
699 last_frame_output: ExecReturnValue,
701 contracts_created: BTreeSet<T::AccountId>,
703 contracts_to_be_destroyed: BTreeMap<T::AccountId, TerminateArgs<T>>,
705}
706
707#[derive(Clone, DebugNoBound)]
710pub struct DelegateInfo<T: Config> {
711 pub caller: Origin<T>,
713 pub callee: H160,
715}
716
717enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
719 Executable(E),
721 Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
723}
724
725impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
726 fn as_executable(&self) -> Option<&E> {
727 if let Self::Executable(executable) = self { Some(executable) } else { None }
728 }
729
730 fn is_pvm(&self) -> bool {
731 match self {
732 Self::Executable(e) => e.code_info().is_pvm(),
733 _ => false,
734 }
735 }
736
737 fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
738 if let Self::Precompile { instance, .. } = self { Some(instance) } else { None }
739 }
740
741 #[cfg(any(feature = "runtime-benchmarks", test))]
742 fn into_executable(self) -> Option<E> {
743 if let Self::Executable(executable) = self { Some(executable) } else { None }
744 }
745}
746
747enum FrameArgs<'a, T: Config, E> {
751 Call {
752 dest: T::AccountId,
754 cached_info: Option<ContractInfo<T>>,
756 delegated_call: Option<DelegateInfo<T>>,
760 },
761 Instantiate {
762 sender: T::AccountId,
764 executable: E,
766 salt: Option<&'a [u8; 32]>,
768 input_data: &'a [u8],
770 },
771}
772
773enum CachedContract<T: Config> {
775 Cached(ContractInfo<T>),
777 Invalidated,
781 None,
783}
784
785impl<T: Config> Frame<T> {
786 fn contract_info(&mut self) -> &mut ContractInfo<T> {
788 self.contract_info.get(&self.account_id)
789 }
790}
791
792macro_rules! get_cached_or_panic_after_load {
796 ($c:expr) => {{
797 if let CachedContract::Cached(contract) = $c {
798 contract
799 } else {
800 panic!(
801 "It is impossible to remove a contract that is on the call stack;\
802 See implementations of terminate;\
803 Therefore fetching a contract will never fail while using an account id
804 that is currently active on the call stack;\
805 qed"
806 );
807 }
808 }};
809}
810
811macro_rules! top_frame {
816 ($stack:expr) => {
817 $stack.frames.last().unwrap_or(&$stack.first_frame)
818 };
819}
820
821macro_rules! top_frame_mut {
826 ($stack:expr) => {
827 $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
828 };
829}
830
831impl<T: Config> CachedContract<T> {
832 fn into_contract(self) -> Option<ContractInfo<T>> {
834 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
835 }
836
837 fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
839 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
840 }
841
842 fn load(&mut self, account_id: &T::AccountId) {
844 if let CachedContract::Invalidated = self &&
845 let Some(contract) =
846 AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
847 {
848 *self = CachedContract::Cached(contract);
849 }
850 }
851
852 fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
854 self.load(account_id);
855 get_cached_or_panic_after_load!(self)
856 }
857
858 fn invalidate(&mut self) {
860 if matches!(self, CachedContract::Cached(_)) {
861 *self = CachedContract::Invalidated;
862 }
863 }
864}
865
866impl<'a, T, E> Stack<'a, T, E>
867where
868 T: Config,
869 E: Executable<T>,
870{
871 pub fn run_call(
877 origin: Origin<T>,
878 dest: H160,
879 transaction_meter: &'a mut TransactionMeter<T>,
880 value: U256,
881 input_data: Vec<u8>,
882 exec_config: &ExecConfig<T>,
883 ) -> ExecResult {
884 let dest = T::AddressMapper::to_account_id(&dest);
885 if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
886 FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
887 origin.clone(),
888 transaction_meter,
889 value,
890 exec_config,
891 &input_data,
892 )? {
893 stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
894 } else {
895 if_tracing(|t| {
896 t.enter_child_span(
897 origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
898 T::AddressMapper::to_address(&dest),
899 None,
900 false,
901 false,
902 value,
903 &input_data,
904 Default::default(),
905 );
906 });
907
908 let result = if let Some(mock_answer) =
909 exec_config.mock_handler.as_ref().and_then(|handler| {
910 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
911 }) {
912 Ok(mock_answer)
913 } else {
914 Self::transfer_from_origin(
915 &origin,
916 &origin,
917 &dest,
918 value,
919 transaction_meter,
920 exec_config,
921 )
922 };
923
924 if_tracing(|t| {
925 let gas_used =
926 transaction_meter.total_consumed_gas().try_into().unwrap_or(u64::MAX);
927 let weight_consumed = transaction_meter.weight_consumed();
928 match result {
929 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_consumed),
930 Err(e) => {
931 t.exit_child_span_with_error(e.error.into(), gas_used, weight_consumed)
932 },
933 }
934 });
935
936 log::trace!(target: LOG_TARGET, "call finished with: {result:?}");
937
938 result
939 }
940 }
941
942 pub fn run_instantiate(
948 origin: T::AccountId,
949 executable: E,
950 transaction_meter: &'a mut TransactionMeter<T>,
951 value: U256,
952 input_data: Vec<u8>,
953 salt: Option<&[u8; 32]>,
954 exec_config: &ExecConfig<T>,
955 ) -> Result<(H160, ExecReturnValue), ExecError> {
956 let deployer = T::AddressMapper::to_address(&origin);
957 let (mut stack, executable) = Stack::<'_, T, E>::new(
958 FrameArgs::Instantiate {
959 sender: origin.clone(),
960 executable,
961 salt,
962 input_data: input_data.as_ref(),
963 },
964 Origin::from_account_id(origin),
965 transaction_meter,
966 value,
967 exec_config,
968 &input_data,
969 )?
970 .expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
971 let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
972 let result = stack
973 .run(executable, input_data)
974 .map(|_| (address, stack.first_frame.last_frame_output));
975 if let Ok((contract, output)) = &result &&
976 !output.did_revert()
977 {
978 Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract: *contract });
979 }
980 log::trace!(target: LOG_TARGET, "instantiate finished with: {result:?}");
981 result
982 }
983
984 #[cfg(any(feature = "runtime-benchmarks", test))]
985 pub fn bench_new_call(
986 dest: H160,
987 origin: Origin<T>,
988 transaction_meter: &'a mut TransactionMeter<T>,
989 value: BalanceOf<T>,
990 exec_config: &'a ExecConfig<T>,
991 read_only: bool,
992 delegate_call: bool,
993 ) -> (Self, E) {
994 let call = Self::new(
995 FrameArgs::Call {
996 dest: T::AddressMapper::to_account_id(&dest),
997 cached_info: None,
998 delegated_call: None,
999 },
1000 origin,
1001 transaction_meter,
1002 value.into(),
1003 exec_config,
1004 &Default::default(),
1005 )
1006 .unwrap()
1007 .unwrap();
1008 let mut stack = call.0;
1009 if read_only {
1010 stack.top_frame_mut().read_only = true;
1011 }
1012 if delegate_call {
1013 let frame = stack.top_frame_mut();
1014 frame.delegate = Some(DelegateInfo {
1015 caller: Origin::from_account_id(frame.account_id.clone()),
1016 callee: H160::zero(),
1017 });
1018 }
1019 (stack, call.1.into_executable().unwrap())
1020 }
1021
1022 fn new(
1027 args: FrameArgs<T, E>,
1028 origin: Origin<T>,
1029 transaction_meter: &'a mut TransactionMeter<T>,
1030 value: U256,
1031 exec_config: &'a ExecConfig<T>,
1032 input_data: &Vec<u8>,
1033 ) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1034 origin.ensure_mapped()?;
1035 let Some((first_frame, executable)) = Self::new_frame(
1036 args,
1037 value,
1038 transaction_meter,
1039 &CallResources::NoLimits,
1040 false,
1041 true,
1042 input_data,
1043 exec_config,
1044 )?
1045 else {
1046 return Ok(None);
1047 };
1048
1049 let mut timestamp = T::Time::now();
1050 let mut block_number = <frame_system::Pallet<T>>::block_number();
1051 if let Some(timestamp_override) =
1053 exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override)
1054 {
1055 block_number = block_number.saturating_add(1u32.into());
1056 let delta = 1000u32.into();
1058 timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override);
1059 }
1060
1061 let stack = Self {
1062 origin,
1063 transaction_meter,
1064 timestamp,
1065 block_number,
1066 first_frame,
1067 frames: Default::default(),
1068 transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
1069 access_list: AccessList::new(),
1070 exec_config,
1071 _phantom: Default::default(),
1072 };
1073 Ok(Some((stack, executable)))
1074 }
1075
1076 fn fail_if_chained_delegation(target: Option<H160>) -> Result<(), ExecError> {
1086 if let Some(target) = target &&
1087 AccountInfo::<T>::is_delegated(&target)
1088 {
1089 return Err(ExecError {
1090 error: <Error<T>>::ContractTrapped.into(),
1091 origin: ErrorOrigin::Callee,
1092 });
1093 }
1094 Ok(())
1095 }
1096
1097 fn new_frame<S: State>(
1102 frame_args: FrameArgs<T, E>,
1103 value_transferred: U256,
1104 meter: &mut ResourceMeter<T, S>,
1105 call_resources: &CallResources<T>,
1106 read_only: bool,
1107 origin_is_caller: bool,
1108 input_data: &[u8],
1109 exec_config: &ExecConfig<T>,
1110 ) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1111 let mut read_delegation: Option<Option<H160>> = None;
1114 let mut delegate_code_target: Option<H160> = None;
1118
1119 let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
1120 FrameArgs::Call { dest, cached_info, delegated_call } => {
1121 let address = T::AddressMapper::to_address(&dest);
1122 let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
1123
1124 let mut contract = match (cached_info, &precompile) {
1127 (Some(info), _) => CachedContract::Cached(info),
1128 (None, None) => {
1129 let (info, target) =
1130 AccountInfo::<T>::load_contract_with_delegation(&address);
1131 read_delegation = Some(target);
1132 if let Some(info) = info {
1133 CachedContract::Cached(info)
1134 } else {
1135 Self::fail_if_chained_delegation(target)?;
1136 return Ok(None);
1137 }
1138 },
1139 (None, Some(precompile)) if precompile.has_contract_info() => {
1140 log::trace!(target: LOG_TARGET, "found precompile for address {address:?}");
1141 let (info, target) =
1142 AccountInfo::<T>::load_contract_with_delegation(&address);
1143 read_delegation = Some(target);
1144 if let Some(info) = info {
1145 CachedContract::Cached(info)
1146 } else {
1147 let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
1148 CachedContract::Cached(info)
1149 }
1150 },
1151 (None, Some(_)) => {
1154 read_delegation = Some(None);
1155 CachedContract::None
1156 },
1157 };
1158
1159 let delegated_call = delegated_call.or_else(|| {
1160 exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1161 mock_handler.mock_delegated_caller(address, input_data)
1162 })
1163 });
1164 let executable = if let Some(delegated_call) = &delegated_call {
1166 if let Some(precompile) =
1167 <AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
1168 {
1169 ExecutableOrPrecompile::Precompile {
1170 instance: precompile,
1171 _phantom: Default::default(),
1172 }
1173 } else {
1174 let (info, target) =
1175 AccountInfo::<T>::load_contract_with_delegation(&delegated_call.callee);
1176 let Some(info) = info else {
1177 Self::fail_if_chained_delegation(target)?;
1178 return Ok(None);
1179 };
1180 delegate_code_target = target;
1181 let executable = E::from_storage(info.code_hash, meter)?;
1182 ExecutableOrPrecompile::Executable(executable)
1183 }
1184 } else {
1185 if let Some(precompile) = precompile {
1186 ExecutableOrPrecompile::Precompile {
1187 instance: precompile,
1188 _phantom: Default::default(),
1189 }
1190 } else {
1191 let executable = E::from_storage(
1192 contract
1193 .as_contract()
1194 .expect("When not a precompile the contract was loaded above; qed")
1195 .code_hash,
1196 meter,
1197 )?;
1198 ExecutableOrPrecompile::Executable(executable)
1199 }
1200 };
1201
1202 (dest, contract, executable, delegated_call, ExportedFunction::Call)
1203 },
1204 FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1205 let deployer = T::AddressMapper::to_address(&sender);
1206 let account_nonce = <System<T>>::account_nonce(&sender);
1207 let address = if let Some(salt) = salt {
1208 address::create2(&deployer, executable.code(), input_data, salt)
1209 } else {
1210 use sp_runtime::Saturating;
1211 address::create1(
1212 &deployer,
1213 if origin_is_caller {
1216 account_nonce.saturating_sub(1u32.into()).saturated_into()
1217 } else {
1218 account_nonce.saturated_into()
1219 },
1220 )
1221 };
1222 let contract = ContractInfo::new(
1223 &address,
1224 <System<T>>::account_nonce(&sender),
1225 *executable.code_hash(),
1226 )?;
1227 (
1228 T::AddressMapper::to_fallback_account_id(&address),
1229 CachedContract::Cached(contract),
1230 ExecutableOrPrecompile::Executable(executable),
1231 None,
1232 ExportedFunction::Constructor,
1233 )
1234 },
1235 };
1236
1237 let address = T::AddressMapper::to_address(&account_id);
1242 let code_address = delegate
1243 .as_ref()
1244 .map(|d| delegate_code_target.unwrap_or(d.callee))
1245 .or_else(|| {
1246 if entry_point == ExportedFunction::Constructor {
1248 return None;
1249 }
1250 read_delegation.unwrap_or_else(|| AccountInfo::<T>::get_delegation_target(&address))
1251 })
1252 .unwrap_or(address);
1253
1254 let frame = Frame {
1255 delegate,
1256 value_transferred,
1257 contract_info,
1258 account_id,
1259 entry_point,
1260 code_address,
1261 frame_meter: meter.new_nested(call_resources)?,
1262 allows_reentry: true,
1263 read_only,
1264 last_frame_output: Default::default(),
1265 contracts_created: Default::default(),
1266 contracts_to_be_destroyed: Default::default(),
1267 };
1268
1269 Ok(Some((frame, executable)))
1270 }
1271
1272 fn push_frame(
1274 &mut self,
1275 frame_args: FrameArgs<T, E>,
1276 value_transferred: U256,
1277 call_resources: &CallResources<T>,
1278 read_only: bool,
1279 input_data: &[u8],
1280 ) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1281 if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1282 return Err(Error::<T>::MaxCallDepthReached.into());
1283 }
1284
1285 let frame = self.top_frame();
1294 if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1295 (&frame.contract_info, frame.entry_point)
1296 {
1297 let mut contract_with_pending_changes = contract.clone();
1298 frame
1299 .frame_meter
1300 .apply_pending_storage_changes(&mut contract_with_pending_changes);
1301 AccountInfo::<T>::insert_contract(
1302 &T::AddressMapper::to_address(&frame.account_id),
1303 contract_with_pending_changes,
1304 );
1305 }
1306
1307 let frame = top_frame_mut!(self);
1308 let meter = &mut frame.frame_meter;
1309 if let Some((frame, executable)) = Self::new_frame(
1310 frame_args,
1311 value_transferred,
1312 meter,
1313 call_resources,
1314 read_only,
1315 false,
1316 input_data,
1317 self.exec_config,
1318 )? {
1319 if frame.entry_point == ExportedFunction::Constructor &&
1322 self.frames().any(|f| {
1323 f.entry_point == ExportedFunction::Constructor &&
1324 f.account_id == frame.account_id
1325 }) {
1326 return Err(Error::<T>::DuplicateContract.into());
1327 }
1328 self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1329 Ok(Some(executable))
1330 } else {
1331 Ok(None)
1332 }
1333 }
1334
1335 fn run(
1339 &mut self,
1340 executable: ExecutableOrPrecompile<T, E, Self>,
1341 input_data: Vec<u8>,
1342 ) -> Result<(), ExecError> {
1343 let frame = self.top_frame();
1344 let entry_point = frame.entry_point;
1345 let is_pvm = executable.is_pvm();
1346
1347 if_tracing(|tracer| {
1348 let (from, to) = match frame.delegate.as_ref() {
1351 Some(delegate) => {
1352 (T::AddressMapper::to_address(&frame.account_id), delegate.callee)
1353 },
1354 None => (
1355 self.caller()
1356 .account_id()
1357 .map(T::AddressMapper::to_address)
1358 .unwrap_or_default(),
1359 T::AddressMapper::to_address(&frame.account_id),
1360 ),
1361 };
1362 tracer.enter_child_span(
1363 from,
1364 to,
1365 (frame.code_address != to).then_some(frame.code_address),
1366 frame.delegate.is_some(),
1367 frame.read_only,
1368 frame.value_transferred,
1369 &input_data,
1370 frame
1371 .frame_meter
1372 .eth_gas_left()
1373 .unwrap_or_default()
1374 .try_into()
1375 .unwrap_or_default(),
1376 );
1377 });
1378 let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1379 handler.mock_call(
1380 frame
1381 .delegate
1382 .as_ref()
1383 .map(|delegate| delegate.callee)
1384 .unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1385 &input_data,
1386 frame.value_transferred,
1387 )
1388 });
1389 let frames_len = self.frames.len();
1393 if let Some(caller_frame) = match frames_len {
1394 0 => None,
1395 1 => Some(&mut self.first_frame.last_frame_output),
1396 _ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1397 } {
1398 *caller_frame = Default::default();
1399 }
1400
1401 self.with_transient_storage_mut(|transient_storage| {
1402 transient_storage.start_transaction();
1403 });
1404 let is_first_frame = self.frames.is_empty();
1405 let access_list_checkpoints_len = self.access_list.frame_depth();
1406 if !is_first_frame {
1410 self.access_list.enter_frame();
1411 }
1412
1413 let do_transaction = || -> ExecResult {
1414 let caller = self.caller();
1415 let bump_nonce = self.exec_config.bump_nonce;
1416 let frame = top_frame_mut!(self);
1417 let account_id = &frame.account_id.clone();
1418
1419 if u32::try_from(input_data.len())
1420 .map(|len| len > limits::CALLDATA_BYTES)
1421 .unwrap_or(true)
1422 {
1423 Err(<Error<T>>::CallDataTooLarge)?;
1424 }
1425
1426 if entry_point == ExportedFunction::Constructor {
1429 if !frame_system::Pallet::<T>::account_exists(&account_id) {
1430 T::Deposit::init_contract(account_id)?;
1431 }
1432
1433 <System<T>>::inc_consumers(account_id)?;
1438
1439 <System<T>>::inc_account_nonce(account_id);
1441
1442 if bump_nonce || !is_first_frame {
1443 <System<T>>::inc_account_nonce(caller.account_id()?);
1446 }
1447 if is_pvm {
1449 <CodeInfo<T>>::increment_refcount(
1450 *executable
1451 .as_executable()
1452 .expect("Precompiles cannot be instantiated; qed")
1453 .code_hash(),
1454 )?;
1455 }
1456 }
1457
1458 if frame.delegate.is_none() {
1462 Self::transfer_from_origin(
1463 &self.origin,
1464 &caller,
1465 account_id,
1466 frame.value_transferred,
1467 &mut frame.frame_meter,
1468 self.exec_config,
1469 )?;
1470 }
1471
1472 if let Some(precompile) = executable.as_precompile() &&
1479 precompile.has_contract_info() &&
1480 frame.delegate.is_none() &&
1481 !<System<T>>::account_exists(account_id)
1482 {
1483 T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1486 <System<T>>::inc_consumers(account_id)?;
1488 }
1489
1490 let mut code_deposit = executable
1491 .as_executable()
1492 .map(|exec| exec.code_info().deposit())
1493 .unwrap_or_default();
1494
1495 let mut output = match executable {
1496 ExecutableOrPrecompile::Executable(executable) => {
1497 executable.execute(self, entry_point, input_data)
1498 },
1499 ExecutableOrPrecompile::Precompile { instance, .. } => {
1500 instance.call(input_data, self)
1501 },
1502 }
1503 .and_then(|output| {
1504 if u32::try_from(output.data.len())
1505 .map(|len| len > limits::CALLDATA_BYTES)
1506 .unwrap_or(true)
1507 {
1508 Err(<Error<T>>::ReturnDataTooLarge)?;
1509 }
1510 Ok(output)
1511 })
1512 .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1513
1514 if output.did_revert() {
1516 return Ok(output);
1517 }
1518
1519 let frame = if entry_point == ExportedFunction::Constructor {
1522 let frame = top_frame_mut!(self);
1523 if !is_pvm {
1526 let data = if crate::tracing::if_tracing(|_| {}).is_none() &&
1530 self.exec_config.is_dry_run.is_none()
1531 {
1532 core::mem::replace(&mut output.data, Default::default())
1533 } else {
1534 output.data.clone()
1535 };
1536
1537 let mut module = match &self.origin {
1541 Origin::Signed(o) => {
1542 crate::ContractBlob::<T>::from_evm_runtime_code(data, o.clone())?
1543 },
1544 Origin::Root => {
1545 crate::ContractBlob::<T>::from_evm_runtime_code_with_deposit(
1546 data,
1547 crate::Pallet::<T>::account_id(),
1548 Zero::zero(),
1549 )?
1550 },
1551 };
1552 module.store_code(&self.exec_config, &mut frame.frame_meter)?;
1553 code_deposit = module.code_info().deposit();
1554
1555 let contract_info = frame.contract_info();
1556 contract_info.code_hash = *module.code_hash();
1557 <CodeInfo<T>>::increment_refcount(contract_info.code_hash)?;
1558 }
1559
1560 let deposit = frame.contract_info().update_base_deposit(code_deposit);
1561 frame.frame_meter.charge_contract_deposit_and_transfer(
1562 frame.account_id.clone(),
1563 StorageDeposit::Charge(deposit),
1564 )?;
1565 frame
1566 } else {
1567 self.top_frame_mut()
1568 };
1569
1570 let contract = frame.contract_info.as_contract();
1574 frame
1575 .frame_meter
1576 .finalize(contract)
1577 .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1578
1579 Ok(output)
1580 };
1581
1582 let transaction_outcome =
1589 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1590 let output = if let Some(mock_answer) = mock_answer {
1591 Ok(mock_answer)
1592 } else {
1593 do_transaction()
1594 };
1595 match &output {
1596 Ok(result) if !result.did_revert() => {
1597 TransactionOutcome::Commit(Ok((true, output)))
1598 },
1599 _ => TransactionOutcome::Rollback(Ok((false, output))),
1600 }
1601 });
1602
1603 let (success, output) = match transaction_outcome {
1604 Ok((success, output)) => {
1606 if_tracing(|tracer| {
1607 let frame_meter = &top_frame!(self).frame_meter;
1608
1609 let gas_consumed = if is_first_frame {
1612 frame_meter.total_consumed_gas()
1613 } else {
1614 frame_meter.eth_gas_consumed()
1615 };
1616
1617 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1618 let weight_consumed = frame_meter.weight_consumed();
1619
1620 match &output {
1621 Ok(output) => {
1622 tracer.exit_child_span(&output, gas_consumed, weight_consumed)
1623 },
1624 Err(e) => tracer.exit_child_span_with_error(
1625 e.error.into(),
1626 gas_consumed,
1627 weight_consumed,
1628 ),
1629 }
1630 });
1631
1632 (success, output)
1633 },
1634 Err(error) => {
1637 if_tracing(|tracer| {
1638 let frame_meter = &top_frame!(self).frame_meter;
1639
1640 let gas_consumed = if is_first_frame {
1643 frame_meter.total_consumed_gas()
1644 } else {
1645 frame_meter.eth_gas_consumed()
1646 };
1647
1648 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1649 let weight_consumed = frame_meter.weight_consumed();
1650 tracer.exit_child_span_with_error(error.into(), gas_consumed, weight_consumed);
1651 });
1652
1653 (false, Err(error.into()))
1654 },
1655 };
1656 self.with_transient_storage_mut(|transient_storage| {
1657 if success {
1658 transient_storage.commit_transaction();
1659 } else {
1660 transient_storage.rollback_transaction();
1661 }
1662 });
1663 if is_first_frame {
1666 let m = self.access_list.metrics();
1667 log::trace!(
1668 target: LOG_TARGET,
1669 "access list metrics: size={size} cold={cold} hot={hot}",
1670 size = m.size, cold = m.cold, hot = m.hot,
1671 );
1672 } else if success {
1673 self.access_list.commit_frame();
1674 } else {
1675 self.access_list.rollback_frame();
1676 }
1677 debug_assert_eq!(
1678 self.access_list.frame_depth(),
1679 access_list_checkpoints_len,
1680 "this frame closed exactly the checkpoint it opened",
1681 );
1682 log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1683
1684 self.pop_frame(success);
1685 output.map(|output| {
1686 self.top_frame_mut().last_frame_output = output;
1687 })
1688 }
1689
1690 fn pop_frame(&mut self, persist: bool) {
1695 fn bank_pending_changes_and_invalidate<T: Config>(f: &mut Frame<T>) {
1702 let contract = f.account_id.clone();
1703 f.contract_info.load(&f.account_id);
1704 if let Some(info) = f.contract_info.as_contract() {
1705 f.frame_meter.bank_pending_storage_changes(contract, info);
1706 }
1707 f.contract_info.invalidate();
1714 }
1715
1716 let frame = self.frames.pop();
1720
1721 if let Some(mut frame) = frame {
1724 let account_id = &frame.account_id;
1725 let prev = top_frame_mut!(self);
1726
1727 if !persist {
1729 prev.frame_meter.absorb_weight_meter_only(frame.frame_meter);
1730 return;
1731 }
1732
1733 frame.contract_info.load(account_id);
1738 let mut contract = frame.contract_info.into_contract();
1739 prev.frame_meter
1740 .absorb_all_meters(frame.frame_meter, account_id, contract.as_mut());
1741
1742 prev.contracts_created.extend(frame.contracts_created);
1744 prev.contracts_to_be_destroyed.extend(frame.contracts_to_be_destroyed);
1745
1746 if let Some(contract) = contract {
1747 AccountInfo::<T>::insert_contract(
1752 &T::AddressMapper::to_address(account_id),
1753 contract,
1754 );
1755 if let Some(f) = self.frames_mut().find(|f| f.account_id == *account_id) {
1756 bank_pending_changes_and_invalidate(f);
1758 }
1759 }
1760 } else {
1761 if !persist {
1762 self.transaction_meter
1763 .absorb_weight_meter_only(mem::take(&mut self.first_frame.frame_meter));
1764 return;
1765 }
1766
1767 let mut contract = self.first_frame.contract_info.as_contract();
1768 self.transaction_meter.absorb_all_meters(
1769 mem::take(&mut self.first_frame.frame_meter),
1770 &self.first_frame.account_id,
1771 contract.as_deref_mut(),
1772 );
1773
1774 if let Some(contract) = contract {
1775 AccountInfo::<T>::insert_contract(
1776 &T::AddressMapper::to_address(&self.first_frame.account_id),
1777 contract.clone(),
1778 );
1779 }
1780 let contracts_created = mem::take(&mut self.first_frame.contracts_created);
1782 let contracts_to_destroy = mem::take(&mut self.first_frame.contracts_to_be_destroyed);
1783 for (contract_account, args) in contracts_to_destroy {
1784 if args.only_if_same_tx && !contracts_created.contains(&contract_account) {
1785 continue;
1786 }
1787 Self::do_terminate(
1788 &mut self.transaction_meter,
1789 self.exec_config,
1790 &contract_account,
1791 &self.origin,
1792 &args,
1793 )
1794 .ok();
1795 }
1796 }
1797 }
1798
1799 fn transfer<S: State>(
1812 origin: &Origin<T>,
1813 from: &T::AccountId,
1814 to: &T::AccountId,
1815 value: U256,
1816 preservation: Preservation,
1817 meter: &mut ResourceMeter<T, S>,
1818 exec_config: &ExecConfig<T>,
1819 ) -> DispatchResult {
1820 let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1821 .map_err(|_| Error::<T>::BalanceConversionFailed)?;
1822 if value.is_zero() {
1823 return Ok(());
1824 }
1825
1826 if <System<T>>::account_exists(to) {
1827 return transfer_with_dust::<T>(from, to, value, preservation);
1828 }
1829
1830 let origin = origin.account_id()?;
1831 let ed = <T as Config>::Currency::minimum_balance();
1832 let is_eth_tx = exec_config.collect_deposit_from_hold.is_some();
1833 with_transaction(|| -> TransactionOutcome<DispatchResult> {
1834 match Ok::<(), DispatchError>(())
1837 .and_then(|_| {
1838 if is_eth_tx {
1839 let credit = T::FeeInfo::withdraw_txfee(ed)
1840 .ok_or(Error::<T>::StorageDepositNotEnoughFunds)?;
1841 T::Currency::resolve(to, credit)
1842 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
1843 Ok(())
1844 } else {
1845 T::Currency::transfer(origin, to, ed, Preservation::Preserve)
1846 .map(|_| ())
1847 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds.into())
1848 }
1849 })
1850 .and_then(|_| transfer_with_dust::<T>(from, to, value, preservation))
1851 .and_then(|_| meter.charge_deposit(&StorageDeposit::Charge(ed)))
1852 {
1853 Ok(_) => TransactionOutcome::Commit(Ok(())),
1854 Err(err) => TransactionOutcome::Rollback(Err(err)),
1855 }
1856 })
1857 }
1858
1859 fn transfer_from_origin<S: State>(
1861 origin: &Origin<T>,
1862 from: &Origin<T>,
1863 to: &T::AccountId,
1864 value: U256,
1865 meter: &mut ResourceMeter<T, S>,
1866 exec_config: &ExecConfig<T>,
1867 ) -> ExecResult {
1868 let from = match from {
1871 Origin::Signed(caller) => caller,
1872 Origin::Root if value.is_zero() => return Ok(Default::default()),
1873 Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1874 };
1875 Self::transfer(origin, from, to, value, Preservation::Preserve, meter, exec_config)
1876 .map(|_| Default::default())
1877 .map_err(Into::into)
1878 }
1879
1880 fn do_terminate(
1882 transaction_meter: &mut TransactionMeter<T>,
1883 exec_config: &ExecConfig<T>,
1884 contract_account: &T::AccountId,
1885 origin: &Origin<T>,
1886 args: &TerminateArgs<T>,
1887 ) -> Result<(), DispatchError> {
1888 let contract_address = T::AddressMapper::to_address(contract_account);
1889
1890 let origin: Origin<T> = match origin {
1893 Origin::Signed(o) => Origin::Signed(o.clone()),
1894 Origin::Root => Origin::from_account_id(crate::Pallet::<T>::account_id()),
1895 };
1896
1897 let mut delete_contract = |trie_id: &TrieId, code_hash: &H256| {
1898 let refund =
1900 T::Deposit::refund_all(&contract_account, exec_config.funds(origin.account_id()?))?;
1901
1902 System::<T>::dec_consumers(&contract_account);
1904
1905 T::Deposit::destroy_contract(contract_account)?;
1907
1908 let balance = <Contracts<T>>::convert_native_to_evm(<AccountInfo<T>>::total_balance(
1912 contract_address.into(),
1913 ));
1914 Self::transfer(
1915 &origin,
1916 contract_account,
1917 &args.beneficiary,
1918 balance,
1919 Preservation::Expendable,
1920 transaction_meter,
1921 exec_config,
1922 )?;
1923
1924 let _code_removed = <CodeInfo<T>>::decrement_refcount(*code_hash)?;
1926
1927 ContractInfo::<T>::queue_for_deletion(trie_id.clone(), contract_account.clone());
1929 AccountInfoOf::<T>::remove(contract_address);
1930 ImmutableDataOf::<T>::remove(contract_address);
1931
1932 transaction_meter.terminate(contract_account.clone(), refund);
1935
1936 Ok(())
1937 };
1938
1939 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1943 match delete_contract(&args.trie_id, &args.code_hash) {
1944 Ok(()) => {
1945 log::trace!(target: LOG_TARGET, "Terminated {contract_address:?}");
1946 TransactionOutcome::Commit(Ok(()))
1947 },
1948 Err(e) => {
1949 log::debug!(target: LOG_TARGET, "Contract at {contract_address:?} failed to terminate: {e:?}");
1950 TransactionOutcome::Rollback(Err(e))
1951 },
1952 }
1953 })
1954 }
1955
1956 fn top_frame(&self) -> &Frame<T> {
1958 top_frame!(self)
1959 }
1960
1961 fn top_frame_mut(&mut self) -> &mut Frame<T> {
1963 top_frame_mut!(self)
1964 }
1965
1966 fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1970 core::iter::once(&self.first_frame).chain(&self.frames).rev()
1971 }
1972
1973 fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1975 core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1976 }
1977
1978 fn allows_reentry(&self, id: &T::AccountId) -> bool {
1980 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1981 }
1982
1983 fn account_balance(&self, who: &T::AccountId) -> U256 {
1985 let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
1986 crate::Pallet::<T>::convert_native_to_evm(balance)
1987 }
1988
1989 #[cfg(feature = "runtime-benchmarks")]
1992 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
1993 self.top_frame_mut().entry_point = export;
1994 }
1995
1996 #[cfg(feature = "runtime-benchmarks")]
1997 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
1998 self.block_number = block_number;
1999 }
2000
2001 fn block_hash(&self, block_number: U256) -> Option<H256> {
2002 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
2003 return None;
2004 };
2005 if block_number >= self.block_number {
2006 return None;
2007 }
2008 if block_number < self.block_number.saturating_sub(256u32.into()) {
2009 return None;
2010 }
2011
2012 match crate::Pallet::<T>::eth_block_hash_from_number(block_number.into()) {
2016 Some(hash) => Some(hash),
2017 None => {
2018 use codec::Decode;
2019 let block_hash = System::<T>::block_hash(&block_number);
2020 Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
2021 },
2022 }
2023 }
2024
2025 fn has_contract_info(&self) -> bool {
2028 let address = self.address();
2029 let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
2030 if let Some(precompile) = precompile {
2031 return precompile.has_contract_info();
2032 }
2033 true
2034 }
2035
2036 fn with_transient_storage_mut<R, F: FnOnce(&mut TransientStorage<T>) -> R>(
2037 &mut self,
2038 f: F,
2039 ) -> R {
2040 if let Some(transient) = &self.exec_config.test_env_transient_storage {
2041 f(&mut transient.borrow_mut())
2042 } else {
2043 f(&mut self.transient_storage)
2044 }
2045 }
2046 fn with_transient_storage<R, F: FnOnce(&TransientStorage<T>) -> R>(&self, f: F) -> R {
2047 if let Some(transient) = &self.exec_config.test_env_transient_storage {
2048 f(&transient.borrow())
2049 } else {
2050 f(&self.transient_storage)
2051 }
2052 }
2053}
2054
2055impl<'a, T, E> Ext for Stack<'a, T, E>
2056where
2057 T: Config,
2058 E: Executable<T>,
2059{
2060 fn delegate_call(
2061 &mut self,
2062 call_resources: &CallResources<T>,
2063 address: H160,
2064 input_data: Vec<u8>,
2065 ) -> Result<(), ExecError> {
2066 *self.last_frame_output_mut() = Default::default();
2069
2070 let top_frame = self.top_frame_mut();
2071 let mut contract_info = top_frame.contract_info().clone();
2075 top_frame.frame_meter.apply_pending_storage_changes(&mut contract_info);
2076 let account_id = top_frame.account_id.clone();
2077 let value = top_frame.value_transferred;
2078 if let Some(executable) = self.push_frame(
2079 FrameArgs::Call {
2080 dest: account_id,
2081 cached_info: Some(contract_info),
2082 delegated_call: Some(DelegateInfo {
2083 caller: self.caller().clone(),
2084 callee: address,
2085 }),
2086 },
2087 value,
2088 call_resources,
2089 self.is_read_only(),
2090 &input_data,
2091 )? {
2092 self.run(executable, input_data)
2093 } else {
2094 Ok(())
2096 }
2097 }
2098
2099 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
2100 if_tracing(|tracer| {
2101 let addr = T::AddressMapper::to_address(self.account_id());
2102 tracer.terminate(
2103 addr,
2104 *beneficiary,
2105 self.top_frame()
2106 .frame_meter
2107 .eth_gas_left()
2108 .unwrap_or_default()
2109 .try_into()
2110 .unwrap_or_default(),
2111 crate::Pallet::<T>::evm_balance(&addr),
2112 );
2113 });
2114 let frame = top_frame_mut!(self);
2115 let info = frame.contract_info();
2116 let trie_id = info.trie_id.clone();
2117 let code_hash = info.code_hash;
2118 let contract_address = T::AddressMapper::to_address(&frame.account_id);
2119 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2120
2121 Self::transfer(
2123 &self.origin,
2124 &frame.account_id,
2125 &beneficiary,
2126 <Contracts<T>>::evm_balance(&contract_address),
2127 Preservation::Preserve,
2128 &mut frame.frame_meter,
2129 self.exec_config,
2130 )?;
2131
2132 let account_id = frame.account_id.clone();
2134 self.top_frame_mut().contracts_to_be_destroyed.insert(
2135 account_id,
2136 TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: true },
2137 );
2138 Ok(CodeRemoved::Yes)
2139 }
2140
2141 fn own_code_hash(&mut self) -> &H256 {
2142 &self.top_frame_mut().contract_info().code_hash
2143 }
2144
2145 fn immutable_data_len(&mut self) -> u32 {
2146 let frame = self.top_frame_mut();
2147 if frame.code_address == T::AddressMapper::to_address(&frame.account_id) {
2148 frame.contract_info().immutable_data_len()
2149 } else {
2150 limits::IMMUTABLE_BYTES
2151 }
2152 }
2153
2154 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
2155 if self.top_frame().entry_point == ExportedFunction::Constructor {
2156 return Err(Error::<T>::InvalidImmutableAccess.into());
2157 }
2158
2159 let address = self.top_frame().code_address;
2162 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
2163 }
2164
2165 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
2166 let frame = self.top_frame_mut();
2167 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
2168 return Err(Error::<T>::InvalidImmutableAccess.into());
2169 }
2170 frame.contract_info().set_immutable_data_len(data.len() as u32);
2171 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
2172 Ok(())
2173 }
2174}
2175
2176impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
2177where
2178 T: Config,
2179 E: Executable<T>,
2180{
2181 fn instantiate(
2182 &mut self,
2183 call_resources: &CallResources<T>,
2184 mut code: Code,
2185 value: U256,
2186 input_data: Vec<u8>,
2187 salt: Option<&[u8; 32]>,
2188 ) -> Result<H160, ExecError> {
2189 *self.last_frame_output_mut() = Default::default();
2192
2193 let sender = self.top_frame().account_id.clone();
2194 let executable = {
2195 let executable = match &mut code {
2196 Code::Upload(initcode) => {
2197 if !T::AllowEVMBytecode::get() {
2198 return Err(<Error<T>>::CodeRejected.into());
2199 }
2200 ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
2201 let initcode = crate::tracing::if_tracing(|_| initcode.clone())
2202 .unwrap_or_else(|| mem::take(initcode));
2203 E::from_evm_init_code(initcode, sender.clone())?
2204 },
2205 Code::Existing(hash) => {
2206 let executable = E::from_storage(*hash, self.frame_meter_mut())?;
2207 ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
2208 executable
2209 },
2210 };
2211 self.push_frame(
2212 FrameArgs::Instantiate {
2213 sender,
2214 executable,
2215 salt,
2216 input_data: input_data.as_ref(),
2217 },
2218 value,
2219 call_resources,
2220 self.is_read_only(),
2221 &input_data,
2222 )?
2223 };
2224 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
2225
2226 let account_id = self.top_frame().account_id.clone();
2228 self.top_frame_mut().contracts_created.insert(account_id);
2229
2230 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
2231 if_tracing(|t| t.instantiate_code(&code, salt));
2232 self.run(executable, input_data).map(|_| address)
2233 }
2234}
2235
2236impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
2237where
2238 T: Config,
2239 E: Executable<T>,
2240{
2241 type T = T;
2242
2243 fn call(
2244 &mut self,
2245 call_resources: &CallResources<T>,
2246 dest_addr: &H160,
2247 value: U256,
2248 input_data: Vec<u8>,
2249 allows_reentry: ReentrancyProtection,
2250 read_only: bool,
2251 ) -> Result<(), ExecError> {
2252 *self.last_frame_output_mut() = Default::default();
2255
2256 if allows_reentry == ReentrancyProtection::Strict {
2261 self.top_frame_mut().allows_reentry = false;
2262 }
2263
2264 let try_call = || {
2265 let is_read_only = read_only || self.is_read_only();
2267
2268 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2270 T::AddressMapper::to_fallback_account_id(dest_addr)
2271 } else {
2272 T::AddressMapper::to_account_id(dest_addr)
2273 };
2274
2275 if !self.allows_reentry(&dest) {
2276 return Err(<Error<T>>::ReentranceDenied.into());
2277 }
2278
2279 if allows_reentry == ReentrancyProtection::AllowNext {
2280 self.top_frame_mut().allows_reentry = false;
2281 }
2282
2283 let cached_info = self
2291 .frames()
2292 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2293 .and_then(|f| match &f.contract_info {
2294 CachedContract::Cached(contract) => {
2295 let mut contract_with_pending = contract.clone();
2296 f.frame_meter.apply_pending_storage_changes(&mut contract_with_pending);
2297 Some(contract_with_pending)
2298 },
2299 _ => None,
2300 });
2301
2302 if let Some(executable) = self.push_frame(
2303 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2304 value,
2305 call_resources,
2306 is_read_only,
2307 &input_data,
2308 )? {
2309 self.run(executable, input_data)
2310 } else {
2311 if_tracing(|t| {
2312 t.enter_child_span(
2313 T::AddressMapper::to_address(self.account_id()),
2314 T::AddressMapper::to_address(&dest),
2315 None,
2316 false,
2317 is_read_only,
2318 value,
2319 &input_data,
2320 Default::default(),
2321 );
2322 });
2323
2324 let snapshot = if_tracing(|_| top_frame!(self).frame_meter.snapshot());
2325
2326 let result = if let Some(mock_answer) =
2327 self.exec_config.mock_handler.as_ref().and_then(|handler| {
2328 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2329 }) {
2330 *self.last_frame_output_mut() = mock_answer.clone();
2331 Ok(mock_answer)
2332 } else if is_read_only && value.is_zero() {
2333 Ok(Default::default())
2334 } else if is_read_only {
2335 Err(Error::<T>::StateChangeDenied.into())
2336 } else {
2337 let account_id = self.account_id().clone();
2338 let frame = top_frame_mut!(self);
2339 Self::transfer_from_origin(
2340 &self.origin,
2341 &Origin::from_account_id(account_id),
2342 &dest,
2343 value,
2344 &mut frame.frame_meter,
2345 self.exec_config,
2346 )
2347 };
2348
2349 if_tracing(|t| {
2350 let snapshot = snapshot.as_ref().expect(
2351 "snapshot is taken inside if_tracing above; tracing state cannot \
2352 change mid-call, so it is Some whenever this closure runs; qed",
2353 );
2354 let (gas_used, weight_delta) =
2355 top_frame!(self).frame_meter.delta_since(snapshot);
2356 match result {
2357 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_delta),
2358 Err(e) => {
2359 t.exit_child_span_with_error(e.error.into(), gas_used, weight_delta)
2360 },
2361 }
2362 });
2363
2364 result.map(|_| ())
2365 }
2366 };
2367
2368 let result = try_call();
2370
2371 self.top_frame_mut().allows_reentry = true;
2373
2374 result
2375 }
2376
2377 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2378 self.with_transient_storage(|transient_storage| {
2379 transient_storage.read(self.account_id(), key)
2380 })
2381 }
2382
2383 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2384 self.with_transient_storage(|transient_storage| {
2385 transient_storage.read(self.account_id(), key).map(|value| value.len() as _)
2386 })
2387 }
2388
2389 fn set_transient_storage(
2390 &mut self,
2391 key: &Key,
2392 value: Option<Vec<u8>>,
2393 take_old: bool,
2394 ) -> Result<WriteOutcome, DispatchError> {
2395 let account_id = self.account_id().clone();
2396 self.with_transient_storage_mut(|transient_storage| {
2397 transient_storage.write(&account_id, key, value, take_old)
2398 })
2399 }
2400
2401 fn account_id(&self) -> &T::AccountId {
2402 &self.top_frame().account_id
2403 }
2404
2405 fn caller(&self) -> Origin<T> {
2406 if let Some(Ok(mock_caller)) = self
2407 .exec_config
2408 .mock_handler
2409 .as_ref()
2410 .and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2411 .map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2412 {
2413 return mock_caller;
2414 }
2415
2416 if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
2417 caller.clone()
2418 } else {
2419 self.frames()
2420 .nth(1)
2421 .map(|f| Origin::from_account_id(f.account_id.clone()))
2422 .unwrap_or(self.origin.clone())
2423 }
2424 }
2425
2426 fn caller_of_caller(&self) -> Origin<T> {
2427 let caller_of_caller_frame = match self.frames().nth(2) {
2429 None => return self.origin.clone(),
2430 Some(frame) => frame,
2431 };
2432 if let Some(DelegateInfo { caller, .. }) = &caller_of_caller_frame.delegate {
2433 caller.clone()
2434 } else {
2435 Origin::from_account_id(caller_of_caller_frame.account_id.clone())
2436 }
2437 }
2438
2439 fn origin(&self) -> &Origin<T> {
2440 if let Some(mock_origin) = self
2441 .exec_config
2442 .mock_handler
2443 .as_ref()
2444 .and_then(|mock_handler| mock_handler.mock_origin())
2445 {
2446 return mock_origin;
2447 }
2448
2449 &self.origin
2450 }
2451
2452 fn to_account_id(&self, address: &H160) -> T::AccountId {
2453 T::AddressMapper::to_account_id(address)
2454 }
2455
2456 fn code_hash(&self, address: &H160) -> H256 {
2457 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2458 self.exec_config
2459 .mock_handler
2460 .as_ref()
2461 .and_then(|handler| handler.mocked_code(*address))
2462 }) {
2463 return sp_io::hashing::keccak_256(code).into();
2464 }
2465
2466 if let Some(target) = <AccountInfo<T>>::get_delegation_target(address) {
2470 let indicator = <AccountInfo<T>>::delegation_indicator(&target);
2471 return sp_io::hashing::keccak_256(&indicator).into();
2472 }
2473
2474 <AccountInfo<T>>::load_contract(&address)
2475 .map(|contract| contract.code_hash)
2476 .unwrap_or_else(|| {
2477 if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) {
2478 return EMPTY_CODE_HASH;
2479 }
2480 H256::zero()
2481 })
2482 }
2483
2484 fn code_size(&self, address: &H160) -> u64 {
2485 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2486 self.exec_config
2487 .mock_handler
2488 .as_ref()
2489 .and_then(|handler| handler.mocked_code(*address))
2490 }) {
2491 return code.len() as u64;
2492 }
2493
2494 if <AccountInfo<T>>::is_delegated(address) {
2503 return 23;
2504 }
2505
2506 <AccountInfo<T>>::load_contract(&address)
2507 .and_then(|contract| CodeInfoOf::<T>::get(contract.code_hash))
2508 .map(|info| info.code_len())
2509 .unwrap_or_default()
2510 }
2511
2512 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2513 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2514 self.origin == caller
2515 }
2516
2517 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2518 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2520 }
2521
2522 fn origin_is_root(&self) -> bool {
2523 self.origin == Origin::Root
2524 }
2525
2526 fn balance(&self) -> U256 {
2527 self.account_balance(&self.top_frame().account_id)
2528 }
2529
2530 fn balance_of(&self, address: &H160) -> U256 {
2531 let balance =
2532 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2533 if_tracing(|tracer| {
2534 tracer.balance_read(address, balance);
2535 });
2536 balance
2537 }
2538
2539 fn value_transferred(&self) -> U256 {
2540 self.top_frame().value_transferred.into()
2541 }
2542
2543 fn now(&self) -> U256 {
2544 (self.timestamp / 1000u32.into()).into()
2545 }
2546
2547 fn minimum_balance(&self) -> U256 {
2548 let min = T::Currency::minimum_balance();
2549 crate::Pallet::<T>::convert_native_to_evm(min)
2550 }
2551
2552 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2553 let contract = T::AddressMapper::to_address(self.account_id());
2554 if_tracing(|tracer| {
2555 let log_index = frame_system::Pallet::<Self::T>::event_count();
2556 tracer.log_event(contract, &topics, &data, log_index);
2557 });
2558
2559 block_storage::capture_ethereum_log(&contract, &data, &topics);
2561
2562 Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2563 }
2564
2565 fn block_number(&self) -> U256 {
2566 self.block_number.into()
2567 }
2568
2569 fn block_hash(&self, block_number: U256) -> Option<H256> {
2570 self.block_hash(block_number)
2571 }
2572
2573 fn block_author(&self) -> H160 {
2574 Contracts::<Self::T>::block_author()
2575 }
2576
2577 fn gas_limit(&self) -> u64 {
2578 <Contracts<T>>::evm_block_gas_limit().saturated_into()
2579 }
2580
2581 fn chain_id(&self) -> u64 {
2582 <T as Config>::ChainId::get()
2583 }
2584
2585 fn gas_meter(&self) -> &FrameMeter<Self::T> {
2586 &self.top_frame().frame_meter
2587 }
2588
2589 #[inline]
2590 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2591 &mut self.top_frame_mut().frame_meter
2592 }
2593
2594 fn frame_meter(&self) -> &FrameMeter<Self::T> {
2595 &self.top_frame().frame_meter
2596 }
2597
2598 #[inline]
2599 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2600 &mut self.top_frame_mut().frame_meter
2601 }
2602
2603 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2604 secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2605 }
2606
2607 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2608 sp_io::crypto::sr25519_verify(
2609 &SR25519Signature::from(*signature),
2610 message,
2611 &SR25519Public::from(*pub_key),
2612 )
2613 }
2614
2615 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError> {
2616 Ok(ECDSAPublic::from(*pk)
2617 .to_eth_address()
2618 .or_else(|()| Err(Error::<T>::EcdsaRecoveryFailed))?)
2619 }
2620
2621 #[cfg(any(test, feature = "runtime-benchmarks"))]
2622 fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2623 self.top_frame_mut().contract_info()
2624 }
2625
2626 #[cfg(any(feature = "runtime-benchmarks", test))]
2627 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2628 &mut self.transient_storage
2629 }
2630
2631 fn is_read_only(&self) -> bool {
2632 self.top_frame().read_only
2633 }
2634
2635 fn is_delegate_call(&self) -> bool {
2636 self.top_frame().delegate.is_some()
2637 }
2638
2639 fn last_frame_output(&self) -> &ExecReturnValue {
2640 &self.top_frame().last_frame_output
2641 }
2642
2643 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2644 &mut self.top_frame_mut().last_frame_output
2645 }
2646
2647 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2648 let len = buf.len();
2649 if len == 0 {
2650 return;
2651 }
2652
2653 let code = if let Some(code) =
2654 <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2655 self.exec_config
2656 .mock_handler
2657 .as_ref()
2658 .and_then(|handler| handler.mocked_code(*address))
2659 }) {
2660 code.to_vec()
2661 } else if let Some(target) = <AccountInfo<T>>::get_delegation_target(address) {
2662 <AccountInfo<T>>::delegation_indicator(&target).to_vec()
2671 } else {
2672 let code_hash = self.code_hash(address);
2673 crate::PristineCode::<T>::get(&code_hash).unwrap_or_default()
2674 };
2675
2676 let copy_len = len.min(code.len().saturating_sub(code_offset));
2677 if copy_len > 0 {
2678 buf[..copy_len].copy_from_slice(&code[code_offset..code_offset + copy_len]);
2679 }
2680 buf[copy_len..].fill(0);
2681 }
2682
2683 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2684 ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2685 let parent = self.frames_mut().nth(1).ok_or_else(|| Error::<T>::ContractNotFound)?;
2686 ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2687 ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2688
2689 let contract_address = T::AddressMapper::to_address(&parent.account_id);
2690
2691 ensure!(
2693 !AccountInfo::<T>::is_delegated(&contract_address),
2694 Error::<T>::CannotTerminateDelegatedAccount,
2695 );
2696
2697 let info = parent.contract_info();
2698 let trie_id = info.trie_id.clone();
2699 let code_hash = info.code_hash;
2700 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2701
2702 let parent_account_id = parent.account_id.clone();
2703
2704 Self::transfer(
2706 &self.origin,
2707 &parent_account_id,
2708 &beneficiary,
2709 <Contracts<T>>::evm_balance(&contract_address),
2710 Preservation::Preserve,
2711 &mut top_frame_mut!(self).frame_meter,
2712 &self.exec_config,
2713 )?;
2714
2715 let args = TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: false };
2717 self.top_frame_mut().contracts_to_be_destroyed.insert(parent_account_id, args);
2718
2719 Ok(())
2720 }
2721
2722 fn effective_gas_price(&self) -> U256 {
2723 self.exec_config
2724 .effective_gas_price
2725 .unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2726 }
2727
2728 fn gas_left(&self) -> u64 {
2729 let frame = self.top_frame();
2730
2731 frame.frame_meter.eth_gas_left().unwrap_or_default().saturated_into::<u64>()
2732 }
2733
2734 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2735 assert!(self.has_contract_info());
2736 self.top_frame_mut().contract_info().read(key)
2737 }
2738
2739 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2740 assert!(self.has_contract_info());
2741 self.top_frame_mut().contract_info().size(key.into())
2742 }
2743
2744 fn set_storage(
2745 &mut self,
2746 key: &Key,
2747 value: Option<Vec<u8>>,
2748 take_old: bool,
2749 ) -> Result<WriteOutcome, DispatchError> {
2750 assert!(self.has_contract_info());
2751 let frame = self.top_frame_mut();
2752 frame.contract_info.get(&frame.account_id).write(
2753 key.into(),
2754 value,
2755 Some(&mut frame.frame_meter),
2756 take_old,
2757 )
2758 }
2759
2760 fn touch_storage_access(
2761 &mut self,
2762 transient: bool,
2763 key: &Key,
2764 op: StorageOp,
2765 ) -> StorageAccessKind {
2766 if transient {
2767 return StorageAccessKind::Transient;
2768 }
2769 let address = self.address();
2770 StorageAccessKind::Persistent(
2771 self.access_list.touch(AccessEntry { address, slot: key.into() }, op),
2772 )
2773 }
2774
2775 fn peek_storage_access(&self, transient: bool, key: &Key) -> StorageAccessKind {
2776 if transient {
2777 return StorageAccessKind::Transient;
2778 }
2779 let address = self.address();
2780 StorageAccessKind::Persistent(
2781 self.access_list.peek(&AccessEntry { address, slot: key.into() }),
2782 )
2783 }
2784
2785 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult {
2786 assert!(self.has_contract_info());
2787 self.top_frame_mut().frame_meter.record_contract_storage_changes(diff)
2788 }
2789}
2790
2791pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2793 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2794}
2795
2796#[cfg(feature = "runtime-benchmarks")]
2797pub fn bench_do_terminate<T: Config>(
2798 transaction_meter: &mut TransactionMeter<T>,
2799 exec_config: &ExecConfig<T>,
2800 contract_account: &T::AccountId,
2801 origin: &Origin<T>,
2802 beneficiary: T::AccountId,
2803 trie_id: TrieId,
2804 code_hash: H256,
2805 only_if_same_tx: bool,
2806) -> Result<(), DispatchError> {
2807 Stack::<T, crate::ContractBlob<T>>::do_terminate(
2808 transaction_meter,
2809 exec_config,
2810 contract_account,
2811 origin,
2812 &TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx },
2813 )
2814}
2815
2816mod sealing {
2817 use super::*;
2818
2819 pub trait Sealed {}
2820 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2821
2822 #[cfg(test)]
2823 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2824}