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, StorageOp, Warmth},
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(&mut self, key: &Key, op: StorageOp) -> Warmth;
557
558 fn peek_storage_access(&self, key: &Key) -> Warmth;
561
562 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult;
564}
565
566#[derive(
568 Copy,
569 Clone,
570 PartialEq,
571 Eq,
572 Debug,
573 codec::Decode,
574 codec::Encode,
575 codec::MaxEncodedLen,
576 scale_info::TypeInfo,
577)]
578pub enum ExportedFunction {
579 Constructor,
581 Call,
583}
584
585pub trait Executable<T: Config>: Sized {
590 fn from_storage<S: State>(
595 code_hash: H256,
596 meter: &mut ResourceMeter<T, S>,
597 ) -> Result<Self, DispatchError>;
598
599 fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
601
602 fn execute<E: Ext<T = T>>(
612 self,
613 ext: &mut E,
614 function: ExportedFunction,
615 input_data: Vec<u8>,
616 ) -> ExecResult;
617
618 fn code_info(&self) -> &CodeInfo<T>;
620
621 fn code(&self) -> &[u8];
623
624 fn code_hash(&self) -> &H256;
626}
627
628pub struct Stack<'a, T: Config, E> {
634 origin: Origin<T>,
643 transaction_meter: &'a mut TransactionMeter<T>,
645 timestamp: MomentOf<T>,
647 block_number: BlockNumberFor<T>,
649 frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
652 first_frame: Frame<T>,
654 transient_storage: TransientStorage<T>,
656 access_list: AccessList,
658 exec_config: &'a ExecConfig<T>,
660 _phantom: PhantomData<E>,
662}
663
664struct Frame<T: Config> {
669 account_id: T::AccountId,
671 contract_info: CachedContract<T>,
673 value_transferred: U256,
675 entry_point: ExportedFunction,
677 frame_meter: FrameMeter<T>,
679 allows_reentry: bool,
681 read_only: bool,
683 delegate: Option<DelegateInfo<T>>,
686 code_address: H160,
692 last_frame_output: ExecReturnValue,
694 contracts_created: BTreeSet<T::AccountId>,
696 contracts_to_be_destroyed: BTreeMap<T::AccountId, TerminateArgs<T>>,
698}
699
700#[derive(Clone, DebugNoBound)]
703pub struct DelegateInfo<T: Config> {
704 pub caller: Origin<T>,
706 pub callee: H160,
708}
709
710enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
712 Executable(E),
714 Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
716}
717
718impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
719 fn as_executable(&self) -> Option<&E> {
720 if let Self::Executable(executable) = self { Some(executable) } else { None }
721 }
722
723 fn is_pvm(&self) -> bool {
724 match self {
725 Self::Executable(e) => e.code_info().is_pvm(),
726 _ => false,
727 }
728 }
729
730 fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
731 if let Self::Precompile { instance, .. } = self { Some(instance) } else { None }
732 }
733
734 #[cfg(any(feature = "runtime-benchmarks", test))]
735 fn into_executable(self) -> Option<E> {
736 if let Self::Executable(executable) = self { Some(executable) } else { None }
737 }
738}
739
740enum FrameArgs<'a, T: Config, E> {
744 Call {
745 dest: T::AccountId,
747 cached_info: Option<ContractInfo<T>>,
749 delegated_call: Option<DelegateInfo<T>>,
753 },
754 Instantiate {
755 sender: T::AccountId,
757 executable: E,
759 salt: Option<&'a [u8; 32]>,
761 input_data: &'a [u8],
763 },
764}
765
766enum CachedContract<T: Config> {
768 Cached(ContractInfo<T>),
770 Invalidated,
774 None,
776}
777
778impl<T: Config> Frame<T> {
779 fn contract_info(&mut self) -> &mut ContractInfo<T> {
781 self.contract_info.get(&self.account_id)
782 }
783}
784
785macro_rules! get_cached_or_panic_after_load {
789 ($c:expr) => {{
790 if let CachedContract::Cached(contract) = $c {
791 contract
792 } else {
793 panic!(
794 "It is impossible to remove a contract that is on the call stack;\
795 See implementations of terminate;\
796 Therefore fetching a contract will never fail while using an account id
797 that is currently active on the call stack;\
798 qed"
799 );
800 }
801 }};
802}
803
804macro_rules! top_frame {
809 ($stack:expr) => {
810 $stack.frames.last().unwrap_or(&$stack.first_frame)
811 };
812}
813
814macro_rules! top_frame_mut {
819 ($stack:expr) => {
820 $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
821 };
822}
823
824impl<T: Config> CachedContract<T> {
825 fn into_contract(self) -> Option<ContractInfo<T>> {
827 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
828 }
829
830 fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
832 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
833 }
834
835 fn load(&mut self, account_id: &T::AccountId) {
837 if let CachedContract::Invalidated = self &&
838 let Some(contract) =
839 AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
840 {
841 *self = CachedContract::Cached(contract);
842 }
843 }
844
845 fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
847 self.load(account_id);
848 get_cached_or_panic_after_load!(self)
849 }
850
851 fn invalidate(&mut self) {
853 if matches!(self, CachedContract::Cached(_)) {
854 *self = CachedContract::Invalidated;
855 }
856 }
857}
858
859impl<'a, T, E> Stack<'a, T, E>
860where
861 T: Config,
862 E: Executable<T>,
863{
864 pub fn run_call(
870 origin: Origin<T>,
871 dest: H160,
872 transaction_meter: &'a mut TransactionMeter<T>,
873 value: U256,
874 input_data: Vec<u8>,
875 exec_config: &ExecConfig<T>,
876 ) -> ExecResult {
877 let dest = T::AddressMapper::to_account_id(&dest);
878 if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
879 FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
880 origin.clone(),
881 transaction_meter,
882 value,
883 exec_config,
884 &input_data,
885 )? {
886 stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
887 } else {
888 if_tracing(|t| {
889 t.enter_child_span(
890 origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
891 T::AddressMapper::to_address(&dest),
892 None,
893 false,
894 false,
895 value,
896 &input_data,
897 Default::default(),
898 );
899 });
900
901 let result = if let Some(mock_answer) =
902 exec_config.mock_handler.as_ref().and_then(|handler| {
903 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
904 }) {
905 Ok(mock_answer)
906 } else {
907 Self::transfer_from_origin(
908 &origin,
909 &origin,
910 &dest,
911 value,
912 transaction_meter,
913 exec_config,
914 )
915 };
916
917 if_tracing(|t| {
918 let gas_used =
919 transaction_meter.total_consumed_gas().try_into().unwrap_or(u64::MAX);
920 let weight_consumed = transaction_meter.weight_consumed();
921 match result {
922 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_consumed),
923 Err(e) => {
924 t.exit_child_span_with_error(e.error.into(), gas_used, weight_consumed)
925 },
926 }
927 });
928
929 log::trace!(target: LOG_TARGET, "call finished with: {result:?}");
930
931 result
932 }
933 }
934
935 pub fn run_instantiate(
941 origin: T::AccountId,
942 executable: E,
943 transaction_meter: &'a mut TransactionMeter<T>,
944 value: U256,
945 input_data: Vec<u8>,
946 salt: Option<&[u8; 32]>,
947 exec_config: &ExecConfig<T>,
948 ) -> Result<(H160, ExecReturnValue), ExecError> {
949 let deployer = T::AddressMapper::to_address(&origin);
950 let (mut stack, executable) = Stack::<'_, T, E>::new(
951 FrameArgs::Instantiate {
952 sender: origin.clone(),
953 executable,
954 salt,
955 input_data: input_data.as_ref(),
956 },
957 Origin::from_account_id(origin),
958 transaction_meter,
959 value,
960 exec_config,
961 &input_data,
962 )?
963 .expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
964 let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
965 let result = stack
966 .run(executable, input_data)
967 .map(|_| (address, stack.first_frame.last_frame_output));
968 if let Ok((contract, output)) = &result &&
969 !output.did_revert()
970 {
971 Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract: *contract });
972 }
973 log::trace!(target: LOG_TARGET, "instantiate finished with: {result:?}");
974 result
975 }
976
977 #[cfg(any(feature = "runtime-benchmarks", test))]
978 pub fn bench_new_call(
979 dest: H160,
980 origin: Origin<T>,
981 transaction_meter: &'a mut TransactionMeter<T>,
982 value: BalanceOf<T>,
983 exec_config: &'a ExecConfig<T>,
984 read_only: bool,
985 delegate_call: bool,
986 ) -> (Self, E) {
987 let call = Self::new(
988 FrameArgs::Call {
989 dest: T::AddressMapper::to_account_id(&dest),
990 cached_info: None,
991 delegated_call: None,
992 },
993 origin,
994 transaction_meter,
995 value.into(),
996 exec_config,
997 &Default::default(),
998 )
999 .unwrap()
1000 .unwrap();
1001 let mut stack = call.0;
1002 if read_only {
1003 stack.top_frame_mut().read_only = true;
1004 }
1005 if delegate_call {
1006 let frame = stack.top_frame_mut();
1007 frame.delegate = Some(DelegateInfo {
1008 caller: Origin::from_account_id(frame.account_id.clone()),
1009 callee: H160::zero(),
1010 });
1011 }
1012 (stack, call.1.into_executable().unwrap())
1013 }
1014
1015 fn new(
1020 args: FrameArgs<T, E>,
1021 origin: Origin<T>,
1022 transaction_meter: &'a mut TransactionMeter<T>,
1023 value: U256,
1024 exec_config: &'a ExecConfig<T>,
1025 input_data: &Vec<u8>,
1026 ) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1027 origin.ensure_mapped()?;
1028 let Some((first_frame, executable)) = Self::new_frame(
1029 args,
1030 value,
1031 transaction_meter,
1032 &CallResources::NoLimits,
1033 false,
1034 true,
1035 input_data,
1036 exec_config,
1037 )?
1038 else {
1039 return Ok(None);
1040 };
1041
1042 let mut timestamp = T::Time::now();
1043 let mut block_number = <frame_system::Pallet<T>>::block_number();
1044 if let Some(timestamp_override) =
1046 exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override)
1047 {
1048 block_number = block_number.saturating_add(1u32.into());
1049 let delta = 1000u32.into();
1051 timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override);
1052 }
1053
1054 let stack = Self {
1055 origin,
1056 transaction_meter,
1057 timestamp,
1058 block_number,
1059 first_frame,
1060 frames: Default::default(),
1061 transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
1062 access_list: AccessList::new(),
1063 exec_config,
1064 _phantom: Default::default(),
1065 };
1066 Ok(Some((stack, executable)))
1067 }
1068
1069 fn fail_if_chained_delegation(target: Option<H160>) -> Result<(), ExecError> {
1079 if let Some(target) = target &&
1080 AccountInfo::<T>::is_delegated(&target)
1081 {
1082 return Err(ExecError {
1083 error: <Error<T>>::ContractTrapped.into(),
1084 origin: ErrorOrigin::Callee,
1085 });
1086 }
1087 Ok(())
1088 }
1089
1090 fn new_frame<S: State>(
1095 frame_args: FrameArgs<T, E>,
1096 value_transferred: U256,
1097 meter: &mut ResourceMeter<T, S>,
1098 call_resources: &CallResources<T>,
1099 read_only: bool,
1100 origin_is_caller: bool,
1101 input_data: &[u8],
1102 exec_config: &ExecConfig<T>,
1103 ) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1104 let mut read_delegation: Option<Option<H160>> = None;
1107 let mut delegate_code_target: Option<H160> = None;
1111
1112 let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
1113 FrameArgs::Call { dest, cached_info, delegated_call } => {
1114 let address = T::AddressMapper::to_address(&dest);
1115 let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
1116
1117 let mut contract = match (cached_info, &precompile) {
1120 (Some(info), _) => CachedContract::Cached(info),
1121 (None, None) => {
1122 let (info, target) =
1123 AccountInfo::<T>::load_contract_with_delegation(&address);
1124 read_delegation = Some(target);
1125 if let Some(info) = info {
1126 CachedContract::Cached(info)
1127 } else {
1128 Self::fail_if_chained_delegation(target)?;
1129 return Ok(None);
1130 }
1131 },
1132 (None, Some(precompile)) if precompile.has_contract_info() => {
1133 log::trace!(target: LOG_TARGET, "found precompile for address {address:?}");
1134 let (info, target) =
1135 AccountInfo::<T>::load_contract_with_delegation(&address);
1136 read_delegation = Some(target);
1137 if let Some(info) = info {
1138 CachedContract::Cached(info)
1139 } else {
1140 let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
1141 CachedContract::Cached(info)
1142 }
1143 },
1144 (None, Some(_)) => {
1147 read_delegation = Some(None);
1148 CachedContract::None
1149 },
1150 };
1151
1152 let delegated_call = delegated_call.or_else(|| {
1153 exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1154 mock_handler.mock_delegated_caller(address, input_data)
1155 })
1156 });
1157 let executable = if let Some(delegated_call) = &delegated_call {
1159 if let Some(precompile) =
1160 <AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
1161 {
1162 ExecutableOrPrecompile::Precompile {
1163 instance: precompile,
1164 _phantom: Default::default(),
1165 }
1166 } else {
1167 let (info, target) =
1168 AccountInfo::<T>::load_contract_with_delegation(&delegated_call.callee);
1169 let Some(info) = info else {
1170 Self::fail_if_chained_delegation(target)?;
1171 return Ok(None);
1172 };
1173 delegate_code_target = target;
1174 let executable = E::from_storage(info.code_hash, meter)?;
1175 ExecutableOrPrecompile::Executable(executable)
1176 }
1177 } else {
1178 if let Some(precompile) = precompile {
1179 ExecutableOrPrecompile::Precompile {
1180 instance: precompile,
1181 _phantom: Default::default(),
1182 }
1183 } else {
1184 let executable = E::from_storage(
1185 contract
1186 .as_contract()
1187 .expect("When not a precompile the contract was loaded above; qed")
1188 .code_hash,
1189 meter,
1190 )?;
1191 ExecutableOrPrecompile::Executable(executable)
1192 }
1193 };
1194
1195 (dest, contract, executable, delegated_call, ExportedFunction::Call)
1196 },
1197 FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1198 let deployer = T::AddressMapper::to_address(&sender);
1199 let account_nonce = <System<T>>::account_nonce(&sender);
1200 let address = if let Some(salt) = salt {
1201 address::create2(&deployer, executable.code(), input_data, salt)
1202 } else {
1203 use sp_runtime::Saturating;
1204 address::create1(
1205 &deployer,
1206 if origin_is_caller {
1209 account_nonce.saturating_sub(1u32.into()).saturated_into()
1210 } else {
1211 account_nonce.saturated_into()
1212 },
1213 )
1214 };
1215 let contract = ContractInfo::new(
1216 &address,
1217 <System<T>>::account_nonce(&sender),
1218 *executable.code_hash(),
1219 )?;
1220 (
1221 T::AddressMapper::to_fallback_account_id(&address),
1222 CachedContract::Cached(contract),
1223 ExecutableOrPrecompile::Executable(executable),
1224 None,
1225 ExportedFunction::Constructor,
1226 )
1227 },
1228 };
1229
1230 let address = T::AddressMapper::to_address(&account_id);
1235 let code_address = delegate
1236 .as_ref()
1237 .map(|d| delegate_code_target.unwrap_or(d.callee))
1238 .or_else(|| {
1239 if entry_point == ExportedFunction::Constructor {
1241 return None;
1242 }
1243 read_delegation.unwrap_or_else(|| AccountInfo::<T>::get_delegation_target(&address))
1244 })
1245 .unwrap_or(address);
1246
1247 let frame = Frame {
1248 delegate,
1249 value_transferred,
1250 contract_info,
1251 account_id,
1252 entry_point,
1253 code_address,
1254 frame_meter: meter.new_nested(call_resources)?,
1255 allows_reentry: true,
1256 read_only,
1257 last_frame_output: Default::default(),
1258 contracts_created: Default::default(),
1259 contracts_to_be_destroyed: Default::default(),
1260 };
1261
1262 Ok(Some((frame, executable)))
1263 }
1264
1265 fn push_frame(
1267 &mut self,
1268 frame_args: FrameArgs<T, E>,
1269 value_transferred: U256,
1270 call_resources: &CallResources<T>,
1271 read_only: bool,
1272 input_data: &[u8],
1273 ) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1274 if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1275 return Err(Error::<T>::MaxCallDepthReached.into());
1276 }
1277
1278 let frame = self.top_frame();
1287 if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1288 (&frame.contract_info, frame.entry_point)
1289 {
1290 let mut contract_with_pending_changes = contract.clone();
1291 frame
1292 .frame_meter
1293 .apply_pending_storage_changes(&mut contract_with_pending_changes);
1294 AccountInfo::<T>::insert_contract(
1295 &T::AddressMapper::to_address(&frame.account_id),
1296 contract_with_pending_changes,
1297 );
1298 }
1299
1300 let frame = top_frame_mut!(self);
1301 let meter = &mut frame.frame_meter;
1302 if let Some((frame, executable)) = Self::new_frame(
1303 frame_args,
1304 value_transferred,
1305 meter,
1306 call_resources,
1307 read_only,
1308 false,
1309 input_data,
1310 self.exec_config,
1311 )? {
1312 if frame.entry_point == ExportedFunction::Constructor &&
1315 self.frames().any(|f| {
1316 f.entry_point == ExportedFunction::Constructor &&
1317 f.account_id == frame.account_id
1318 }) {
1319 return Err(Error::<T>::DuplicateContract.into());
1320 }
1321 self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1322 Ok(Some(executable))
1323 } else {
1324 Ok(None)
1325 }
1326 }
1327
1328 fn run(
1332 &mut self,
1333 executable: ExecutableOrPrecompile<T, E, Self>,
1334 input_data: Vec<u8>,
1335 ) -> Result<(), ExecError> {
1336 let frame = self.top_frame();
1337 let entry_point = frame.entry_point;
1338 let is_pvm = executable.is_pvm();
1339
1340 if_tracing(|tracer| {
1341 let (from, to) = match frame.delegate.as_ref() {
1344 Some(delegate) => {
1345 (T::AddressMapper::to_address(&frame.account_id), delegate.callee)
1346 },
1347 None => (
1348 self.caller()
1349 .account_id()
1350 .map(T::AddressMapper::to_address)
1351 .unwrap_or_default(),
1352 T::AddressMapper::to_address(&frame.account_id),
1353 ),
1354 };
1355 tracer.enter_child_span(
1356 from,
1357 to,
1358 (frame.code_address != to).then_some(frame.code_address),
1359 frame.delegate.is_some(),
1360 frame.read_only,
1361 frame.value_transferred,
1362 &input_data,
1363 frame
1364 .frame_meter
1365 .eth_gas_left()
1366 .unwrap_or_default()
1367 .try_into()
1368 .unwrap_or_default(),
1369 );
1370 });
1371 let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1372 handler.mock_call(
1373 frame
1374 .delegate
1375 .as_ref()
1376 .map(|delegate| delegate.callee)
1377 .unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1378 &input_data,
1379 frame.value_transferred,
1380 )
1381 });
1382 let frames_len = self.frames.len();
1386 if let Some(caller_frame) = match frames_len {
1387 0 => None,
1388 1 => Some(&mut self.first_frame.last_frame_output),
1389 _ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1390 } {
1391 *caller_frame = Default::default();
1392 }
1393
1394 self.with_transient_storage_mut(|transient_storage| {
1395 transient_storage.start_transaction();
1396 });
1397 let is_first_frame = self.frames.is_empty();
1398 let access_list_checkpoints_len = self.access_list.frame_depth();
1399 if !is_first_frame {
1403 self.access_list.enter_frame();
1404 }
1405
1406 let do_transaction = || -> ExecResult {
1407 let caller = self.caller();
1408 let bump_nonce = self.exec_config.bump_nonce;
1409 let frame = top_frame_mut!(self);
1410 let account_id = &frame.account_id.clone();
1411
1412 if u32::try_from(input_data.len())
1413 .map(|len| len > limits::CALLDATA_BYTES)
1414 .unwrap_or(true)
1415 {
1416 Err(<Error<T>>::CallDataTooLarge)?;
1417 }
1418
1419 if entry_point == ExportedFunction::Constructor {
1422 if !frame_system::Pallet::<T>::account_exists(&account_id) {
1423 T::Deposit::init_contract(account_id)?;
1424 }
1425
1426 <System<T>>::inc_consumers(account_id)?;
1431
1432 <System<T>>::inc_account_nonce(account_id);
1434
1435 if bump_nonce || !is_first_frame {
1436 <System<T>>::inc_account_nonce(caller.account_id()?);
1439 }
1440 if is_pvm {
1442 <CodeInfo<T>>::increment_refcount(
1443 *executable
1444 .as_executable()
1445 .expect("Precompiles cannot be instantiated; qed")
1446 .code_hash(),
1447 )?;
1448 }
1449 }
1450
1451 if frame.delegate.is_none() {
1455 Self::transfer_from_origin(
1456 &self.origin,
1457 &caller,
1458 account_id,
1459 frame.value_transferred,
1460 &mut frame.frame_meter,
1461 self.exec_config,
1462 )?;
1463 }
1464
1465 if let Some(precompile) = executable.as_precompile() &&
1472 precompile.has_contract_info() &&
1473 frame.delegate.is_none() &&
1474 !<System<T>>::account_exists(account_id)
1475 {
1476 T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1479 <System<T>>::inc_consumers(account_id)?;
1481 }
1482
1483 let mut code_deposit = executable
1484 .as_executable()
1485 .map(|exec| exec.code_info().deposit())
1486 .unwrap_or_default();
1487
1488 let mut output = match executable {
1489 ExecutableOrPrecompile::Executable(executable) => {
1490 executable.execute(self, entry_point, input_data)
1491 },
1492 ExecutableOrPrecompile::Precompile { instance, .. } => {
1493 instance.call(input_data, self)
1494 },
1495 }
1496 .and_then(|output| {
1497 if u32::try_from(output.data.len())
1498 .map(|len| len > limits::CALLDATA_BYTES)
1499 .unwrap_or(true)
1500 {
1501 Err(<Error<T>>::ReturnDataTooLarge)?;
1502 }
1503 Ok(output)
1504 })
1505 .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1506
1507 if output.did_revert() {
1509 return Ok(output);
1510 }
1511
1512 let frame = if entry_point == ExportedFunction::Constructor {
1515 let frame = top_frame_mut!(self);
1516 if !is_pvm {
1519 let data = if crate::tracing::if_tracing(|_| {}).is_none() &&
1523 self.exec_config.is_dry_run.is_none()
1524 {
1525 core::mem::replace(&mut output.data, Default::default())
1526 } else {
1527 output.data.clone()
1528 };
1529
1530 let mut module = match &self.origin {
1534 Origin::Signed(o) => {
1535 crate::ContractBlob::<T>::from_evm_runtime_code(data, o.clone())?
1536 },
1537 Origin::Root => {
1538 crate::ContractBlob::<T>::from_evm_runtime_code_with_deposit(
1539 data,
1540 crate::Pallet::<T>::account_id(),
1541 Zero::zero(),
1542 )?
1543 },
1544 };
1545 module.store_code(&self.exec_config, &mut frame.frame_meter)?;
1546 code_deposit = module.code_info().deposit();
1547
1548 let contract_info = frame.contract_info();
1549 contract_info.code_hash = *module.code_hash();
1550 <CodeInfo<T>>::increment_refcount(contract_info.code_hash)?;
1551 }
1552
1553 let deposit = frame.contract_info().update_base_deposit(code_deposit);
1554 frame.frame_meter.charge_contract_deposit_and_transfer(
1555 frame.account_id.clone(),
1556 StorageDeposit::Charge(deposit),
1557 )?;
1558 frame
1559 } else {
1560 self.top_frame_mut()
1561 };
1562
1563 let contract = frame.contract_info.as_contract();
1567 frame
1568 .frame_meter
1569 .finalize(contract)
1570 .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1571
1572 Ok(output)
1573 };
1574
1575 let transaction_outcome =
1582 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1583 let output = if let Some(mock_answer) = mock_answer {
1584 Ok(mock_answer)
1585 } else {
1586 do_transaction()
1587 };
1588 match &output {
1589 Ok(result) if !result.did_revert() => {
1590 TransactionOutcome::Commit(Ok((true, output)))
1591 },
1592 _ => TransactionOutcome::Rollback(Ok((false, output))),
1593 }
1594 });
1595
1596 let (success, output) = match transaction_outcome {
1597 Ok((success, output)) => {
1599 if_tracing(|tracer| {
1600 let frame_meter = &top_frame!(self).frame_meter;
1601
1602 let gas_consumed = if is_first_frame {
1605 frame_meter.total_consumed_gas()
1606 } else {
1607 frame_meter.eth_gas_consumed()
1608 };
1609
1610 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1611 let weight_consumed = frame_meter.weight_consumed();
1612
1613 match &output {
1614 Ok(output) => {
1615 tracer.exit_child_span(&output, gas_consumed, weight_consumed)
1616 },
1617 Err(e) => tracer.exit_child_span_with_error(
1618 e.error.into(),
1619 gas_consumed,
1620 weight_consumed,
1621 ),
1622 }
1623 });
1624
1625 (success, output)
1626 },
1627 Err(error) => {
1630 if_tracing(|tracer| {
1631 let frame_meter = &top_frame!(self).frame_meter;
1632
1633 let gas_consumed = if is_first_frame {
1636 frame_meter.total_consumed_gas()
1637 } else {
1638 frame_meter.eth_gas_consumed()
1639 };
1640
1641 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1642 let weight_consumed = frame_meter.weight_consumed();
1643 tracer.exit_child_span_with_error(error.into(), gas_consumed, weight_consumed);
1644 });
1645
1646 (false, Err(error.into()))
1647 },
1648 };
1649 self.with_transient_storage_mut(|transient_storage| {
1650 if success {
1651 transient_storage.commit_transaction();
1652 } else {
1653 transient_storage.rollback_transaction();
1654 }
1655 });
1656 if is_first_frame {
1659 let m = self.access_list.metrics();
1660 log::trace!(
1661 target: LOG_TARGET,
1662 "access list metrics: size={size} cold={cold} hot={hot}",
1663 size = m.size, cold = m.cold, hot = m.hot,
1664 );
1665 } else if success {
1666 self.access_list.commit_frame();
1667 } else {
1668 self.access_list.rollback_frame();
1669 }
1670 debug_assert_eq!(
1671 self.access_list.frame_depth(),
1672 access_list_checkpoints_len,
1673 "this frame closed exactly the checkpoint it opened",
1674 );
1675 log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1676
1677 self.pop_frame(success);
1678 output.map(|output| {
1679 self.top_frame_mut().last_frame_output = output;
1680 })
1681 }
1682
1683 fn pop_frame(&mut self, persist: bool) {
1688 fn bank_pending_changes_and_invalidate<T: Config>(f: &mut Frame<T>) {
1695 let contract = f.account_id.clone();
1696 f.contract_info.load(&f.account_id);
1697 if let Some(info) = f.contract_info.as_contract() {
1698 f.frame_meter.bank_pending_storage_changes(contract, info);
1699 }
1700 f.contract_info.invalidate();
1707 }
1708
1709 let frame = self.frames.pop();
1713
1714 if let Some(mut frame) = frame {
1717 let account_id = &frame.account_id;
1718 let prev = top_frame_mut!(self);
1719
1720 if !persist {
1722 prev.frame_meter.absorb_weight_meter_only(frame.frame_meter);
1723 return;
1724 }
1725
1726 frame.contract_info.load(account_id);
1731 let mut contract = frame.contract_info.into_contract();
1732 prev.frame_meter
1733 .absorb_all_meters(frame.frame_meter, account_id, contract.as_mut());
1734
1735 prev.contracts_created.extend(frame.contracts_created);
1737 prev.contracts_to_be_destroyed.extend(frame.contracts_to_be_destroyed);
1738
1739 if let Some(contract) = contract {
1740 AccountInfo::<T>::insert_contract(
1745 &T::AddressMapper::to_address(account_id),
1746 contract,
1747 );
1748 if let Some(f) = self.frames_mut().find(|f| f.account_id == *account_id) {
1749 bank_pending_changes_and_invalidate(f);
1751 }
1752 }
1753 } else {
1754 if !persist {
1755 self.transaction_meter
1756 .absorb_weight_meter_only(mem::take(&mut self.first_frame.frame_meter));
1757 return;
1758 }
1759
1760 let mut contract = self.first_frame.contract_info.as_contract();
1761 self.transaction_meter.absorb_all_meters(
1762 mem::take(&mut self.first_frame.frame_meter),
1763 &self.first_frame.account_id,
1764 contract.as_deref_mut(),
1765 );
1766
1767 if let Some(contract) = contract {
1768 AccountInfo::<T>::insert_contract(
1769 &T::AddressMapper::to_address(&self.first_frame.account_id),
1770 contract.clone(),
1771 );
1772 }
1773 let contracts_created = mem::take(&mut self.first_frame.contracts_created);
1775 let contracts_to_destroy = mem::take(&mut self.first_frame.contracts_to_be_destroyed);
1776 for (contract_account, args) in contracts_to_destroy {
1777 if args.only_if_same_tx && !contracts_created.contains(&contract_account) {
1778 continue;
1779 }
1780 Self::do_terminate(
1781 &mut self.transaction_meter,
1782 self.exec_config,
1783 &contract_account,
1784 &self.origin,
1785 &args,
1786 )
1787 .ok();
1788 }
1789 }
1790 }
1791
1792 fn transfer<S: State>(
1805 origin: &Origin<T>,
1806 from: &T::AccountId,
1807 to: &T::AccountId,
1808 value: U256,
1809 preservation: Preservation,
1810 meter: &mut ResourceMeter<T, S>,
1811 exec_config: &ExecConfig<T>,
1812 ) -> DispatchResult {
1813 let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1814 .map_err(|_| Error::<T>::BalanceConversionFailed)?;
1815 if value.is_zero() {
1816 return Ok(());
1817 }
1818
1819 if <System<T>>::account_exists(to) {
1820 return transfer_with_dust::<T>(from, to, value, preservation);
1821 }
1822
1823 let origin = origin.account_id()?;
1824 let ed = <T as Config>::Currency::minimum_balance();
1825 let is_eth_tx = exec_config.collect_deposit_from_hold.is_some();
1826 with_transaction(|| -> TransactionOutcome<DispatchResult> {
1827 match Ok::<(), DispatchError>(())
1830 .and_then(|_| {
1831 if is_eth_tx {
1832 let credit = T::FeeInfo::withdraw_txfee(ed)
1833 .ok_or(Error::<T>::StorageDepositNotEnoughFunds)?;
1834 T::Currency::resolve(to, credit)
1835 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
1836 Ok(())
1837 } else {
1838 T::Currency::transfer(origin, to, ed, Preservation::Preserve)
1839 .map(|_| ())
1840 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds.into())
1841 }
1842 })
1843 .and_then(|_| transfer_with_dust::<T>(from, to, value, preservation))
1844 .and_then(|_| meter.charge_deposit(&StorageDeposit::Charge(ed)))
1845 {
1846 Ok(_) => TransactionOutcome::Commit(Ok(())),
1847 Err(err) => TransactionOutcome::Rollback(Err(err)),
1848 }
1849 })
1850 }
1851
1852 fn transfer_from_origin<S: State>(
1854 origin: &Origin<T>,
1855 from: &Origin<T>,
1856 to: &T::AccountId,
1857 value: U256,
1858 meter: &mut ResourceMeter<T, S>,
1859 exec_config: &ExecConfig<T>,
1860 ) -> ExecResult {
1861 let from = match from {
1864 Origin::Signed(caller) => caller,
1865 Origin::Root if value.is_zero() => return Ok(Default::default()),
1866 Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1867 };
1868 Self::transfer(origin, from, to, value, Preservation::Preserve, meter, exec_config)
1869 .map(|_| Default::default())
1870 .map_err(Into::into)
1871 }
1872
1873 fn do_terminate(
1875 transaction_meter: &mut TransactionMeter<T>,
1876 exec_config: &ExecConfig<T>,
1877 contract_account: &T::AccountId,
1878 origin: &Origin<T>,
1879 args: &TerminateArgs<T>,
1880 ) -> Result<(), DispatchError> {
1881 let contract_address = T::AddressMapper::to_address(contract_account);
1882
1883 let origin: Origin<T> = match origin {
1886 Origin::Signed(o) => Origin::Signed(o.clone()),
1887 Origin::Root => Origin::from_account_id(crate::Pallet::<T>::account_id()),
1888 };
1889
1890 let mut delete_contract = |trie_id: &TrieId, code_hash: &H256| {
1891 let refund =
1893 T::Deposit::refund_all(&contract_account, exec_config.funds(origin.account_id()?))?;
1894
1895 System::<T>::dec_consumers(&contract_account);
1897
1898 T::Deposit::destroy_contract(contract_account)?;
1900
1901 let balance = <Contracts<T>>::convert_native_to_evm(<AccountInfo<T>>::total_balance(
1905 contract_address.into(),
1906 ));
1907 Self::transfer(
1908 &origin,
1909 contract_account,
1910 &args.beneficiary,
1911 balance,
1912 Preservation::Expendable,
1913 transaction_meter,
1914 exec_config,
1915 )?;
1916
1917 let _code_removed = <CodeInfo<T>>::decrement_refcount(*code_hash)?;
1919
1920 ContractInfo::<T>::queue_for_deletion(trie_id.clone(), contract_account.clone());
1922 AccountInfoOf::<T>::remove(contract_address);
1923 ImmutableDataOf::<T>::remove(contract_address);
1924
1925 transaction_meter.terminate(contract_account.clone(), refund);
1928
1929 Ok(())
1930 };
1931
1932 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1936 match delete_contract(&args.trie_id, &args.code_hash) {
1937 Ok(()) => {
1938 log::trace!(target: LOG_TARGET, "Terminated {contract_address:?}");
1939 TransactionOutcome::Commit(Ok(()))
1940 },
1941 Err(e) => {
1942 log::debug!(target: LOG_TARGET, "Contract at {contract_address:?} failed to terminate: {e:?}");
1943 TransactionOutcome::Rollback(Err(e))
1944 },
1945 }
1946 })
1947 }
1948
1949 fn top_frame(&self) -> &Frame<T> {
1951 top_frame!(self)
1952 }
1953
1954 fn top_frame_mut(&mut self) -> &mut Frame<T> {
1956 top_frame_mut!(self)
1957 }
1958
1959 fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1963 core::iter::once(&self.first_frame).chain(&self.frames).rev()
1964 }
1965
1966 fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1968 core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1969 }
1970
1971 fn caller_at(&self, depth: usize) -> Origin<T> {
1977 let Some(frame) = self.frames().nth(depth) else { return self.origin.clone() };
1978 if let Some(DelegateInfo { caller, .. }) = &frame.delegate {
1979 caller.clone()
1980 } else {
1981 self.frames()
1982 .nth(depth + 1)
1983 .map(|f| Origin::from_account_id(f.account_id.clone()))
1984 .unwrap_or(self.origin.clone())
1985 }
1986 }
1987
1988 fn allows_reentry(&self, id: &T::AccountId) -> bool {
1990 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1991 }
1992
1993 fn account_balance(&self, who: &T::AccountId) -> U256 {
1995 let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
1996 crate::Pallet::<T>::convert_native_to_evm(balance)
1997 }
1998
1999 #[cfg(feature = "runtime-benchmarks")]
2002 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
2003 self.top_frame_mut().entry_point = export;
2004 }
2005
2006 #[cfg(feature = "runtime-benchmarks")]
2007 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
2008 self.block_number = block_number;
2009 }
2010
2011 fn block_hash(&self, block_number: U256) -> Option<H256> {
2012 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
2013 return None;
2014 };
2015 if block_number >= self.block_number {
2016 return None;
2017 }
2018 if block_number < self.block_number.saturating_sub(256u32.into()) {
2019 return None;
2020 }
2021
2022 match crate::Pallet::<T>::eth_block_hash_from_number(block_number.into()) {
2026 Some(hash) => Some(hash),
2027 None => {
2028 use codec::Decode;
2029 let block_hash = System::<T>::block_hash(&block_number);
2030 Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
2031 },
2032 }
2033 }
2034
2035 fn has_contract_info(&self) -> bool {
2038 let address = self.address();
2039 let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
2040 if let Some(precompile) = precompile {
2041 return precompile.has_contract_info();
2042 }
2043 true
2044 }
2045
2046 fn with_transient_storage_mut<R, F: FnOnce(&mut TransientStorage<T>) -> R>(
2047 &mut self,
2048 f: F,
2049 ) -> R {
2050 if let Some(transient) = &self.exec_config.test_env_transient_storage {
2051 f(&mut transient.borrow_mut())
2052 } else {
2053 f(&mut self.transient_storage)
2054 }
2055 }
2056 fn with_transient_storage<R, F: FnOnce(&TransientStorage<T>) -> R>(&self, f: F) -> R {
2057 if let Some(transient) = &self.exec_config.test_env_transient_storage {
2058 f(&transient.borrow())
2059 } else {
2060 f(&self.transient_storage)
2061 }
2062 }
2063
2064 fn code_source(&self, address: &H160) -> Option<CodeSource<'_>> {
2070 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2071 self.exec_config
2072 .mock_handler
2073 .as_ref()
2074 .and_then(|handler| handler.mocked_code(*address))
2075 }) {
2076 return Some(CodeSource::Virtual(code));
2077 }
2078
2079 let (contract, target) = <AccountInfo<T>>::load_contract_with_delegation(address);
2080
2081 if let Some(target) = target {
2088 return Some(CodeSource::Indicator(<AccountInfo<T>>::delegation_indicator(&target)));
2089 }
2090
2091 contract.map(|contract| CodeSource::Contract(contract.code_hash))
2092 }
2093}
2094
2095enum CodeSource<'a> {
2097 Virtual(&'a [u8]),
2099 Indicator([u8; 23]),
2101 Contract(H256),
2103}
2104
2105impl<'a, T, E> Ext for Stack<'a, T, E>
2106where
2107 T: Config,
2108 E: Executable<T>,
2109{
2110 fn delegate_call(
2111 &mut self,
2112 call_resources: &CallResources<T>,
2113 address: H160,
2114 input_data: Vec<u8>,
2115 ) -> Result<(), ExecError> {
2116 *self.last_frame_output_mut() = Default::default();
2119
2120 let top_frame = self.top_frame_mut();
2121 let mut contract_info = top_frame.contract_info().clone();
2125 top_frame.frame_meter.apply_pending_storage_changes(&mut contract_info);
2126 let account_id = top_frame.account_id.clone();
2127 let value = top_frame.value_transferred;
2128 if let Some(executable) = self.push_frame(
2129 FrameArgs::Call {
2130 dest: account_id,
2131 cached_info: Some(contract_info),
2132 delegated_call: Some(DelegateInfo {
2133 caller: self.caller().clone(),
2134 callee: address,
2135 }),
2136 },
2137 value,
2138 call_resources,
2139 self.is_read_only(),
2140 &input_data,
2141 )? {
2142 self.run(executable, input_data)
2143 } else {
2144 Ok(())
2146 }
2147 }
2148
2149 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
2150 if_tracing(|tracer| {
2151 let addr = T::AddressMapper::to_address(self.account_id());
2152 tracer.terminate(
2153 addr,
2154 *beneficiary,
2155 self.top_frame()
2156 .frame_meter
2157 .eth_gas_left()
2158 .unwrap_or_default()
2159 .try_into()
2160 .unwrap_or_default(),
2161 crate::Pallet::<T>::evm_balance(&addr),
2162 );
2163 });
2164 let frame = top_frame_mut!(self);
2165 let info = frame.contract_info();
2166 let trie_id = info.trie_id.clone();
2167 let code_hash = info.code_hash;
2168 let contract_address = T::AddressMapper::to_address(&frame.account_id);
2169 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2170
2171 Self::transfer(
2173 &self.origin,
2174 &frame.account_id,
2175 &beneficiary,
2176 <Contracts<T>>::evm_balance(&contract_address),
2177 Preservation::Preserve,
2178 &mut frame.frame_meter,
2179 self.exec_config,
2180 )?;
2181
2182 let account_id = frame.account_id.clone();
2184 self.top_frame_mut().contracts_to_be_destroyed.insert(
2185 account_id,
2186 TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: true },
2187 );
2188 Ok(CodeRemoved::Yes)
2189 }
2190
2191 fn own_code_hash(&mut self) -> &H256 {
2192 &self.top_frame_mut().contract_info().code_hash
2193 }
2194
2195 fn immutable_data_len(&mut self) -> u32 {
2196 let frame = self.top_frame_mut();
2197 if frame.code_address == T::AddressMapper::to_address(&frame.account_id) {
2198 frame.contract_info().immutable_data_len()
2199 } else {
2200 limits::IMMUTABLE_BYTES
2201 }
2202 }
2203
2204 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
2205 if self.top_frame().entry_point == ExportedFunction::Constructor {
2206 return Err(Error::<T>::InvalidImmutableAccess.into());
2207 }
2208
2209 let address = self.top_frame().code_address;
2212 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
2213 }
2214
2215 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
2216 let frame = self.top_frame_mut();
2217 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
2218 return Err(Error::<T>::InvalidImmutableAccess.into());
2219 }
2220 frame.contract_info().set_immutable_data_len(data.len() as u32);
2221 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
2222 Ok(())
2223 }
2224}
2225
2226impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
2227where
2228 T: Config,
2229 E: Executable<T>,
2230{
2231 fn instantiate(
2232 &mut self,
2233 call_resources: &CallResources<T>,
2234 mut code: Code,
2235 value: U256,
2236 input_data: Vec<u8>,
2237 salt: Option<&[u8; 32]>,
2238 ) -> Result<H160, ExecError> {
2239 *self.last_frame_output_mut() = Default::default();
2242
2243 let sender = self.top_frame().account_id.clone();
2244 let executable = {
2245 let executable = match &mut code {
2246 Code::Upload(initcode) => {
2247 if !T::AllowEVMBytecode::get() {
2248 return Err(<Error<T>>::CodeRejected.into());
2249 }
2250 ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
2251 let initcode = crate::tracing::if_tracing(|_| initcode.clone())
2252 .unwrap_or_else(|| mem::take(initcode));
2253 E::from_evm_init_code(initcode, sender.clone())?
2254 },
2255 Code::Existing(hash) => {
2256 let executable = E::from_storage(*hash, self.frame_meter_mut())?;
2257 ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
2258 executable
2259 },
2260 };
2261 self.push_frame(
2262 FrameArgs::Instantiate {
2263 sender,
2264 executable,
2265 salt,
2266 input_data: input_data.as_ref(),
2267 },
2268 value,
2269 call_resources,
2270 self.is_read_only(),
2271 &input_data,
2272 )?
2273 };
2274 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
2275
2276 let account_id = self.top_frame().account_id.clone();
2278 self.top_frame_mut().contracts_created.insert(account_id);
2279
2280 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
2281 if_tracing(|t| t.instantiate_code(&code, salt));
2282 self.run(executable, input_data).map(|_| address)
2283 }
2284}
2285
2286impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
2287where
2288 T: Config,
2289 E: Executable<T>,
2290{
2291 type T = T;
2292
2293 fn call(
2294 &mut self,
2295 call_resources: &CallResources<T>,
2296 dest_addr: &H160,
2297 value: U256,
2298 input_data: Vec<u8>,
2299 allows_reentry: ReentrancyProtection,
2300 read_only: bool,
2301 ) -> Result<(), ExecError> {
2302 *self.last_frame_output_mut() = Default::default();
2305
2306 if allows_reentry == ReentrancyProtection::Strict {
2311 self.top_frame_mut().allows_reentry = false;
2312 }
2313
2314 let try_call = || {
2315 let is_read_only = read_only || self.is_read_only();
2317
2318 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2320 T::AddressMapper::to_fallback_account_id(dest_addr)
2321 } else {
2322 T::AddressMapper::to_account_id(dest_addr)
2323 };
2324
2325 if !self.allows_reentry(&dest) {
2326 return Err(<Error<T>>::ReentranceDenied.into());
2327 }
2328
2329 if allows_reentry == ReentrancyProtection::AllowNext {
2330 self.top_frame_mut().allows_reentry = false;
2331 }
2332
2333 let cached_info = self
2341 .frames()
2342 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2343 .and_then(|f| match &f.contract_info {
2344 CachedContract::Cached(contract) => {
2345 let mut contract_with_pending = contract.clone();
2346 f.frame_meter.apply_pending_storage_changes(&mut contract_with_pending);
2347 Some(contract_with_pending)
2348 },
2349 _ => None,
2350 });
2351
2352 if let Some(executable) = self.push_frame(
2353 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2354 value,
2355 call_resources,
2356 is_read_only,
2357 &input_data,
2358 )? {
2359 self.run(executable, input_data)
2360 } else {
2361 if_tracing(|t| {
2362 t.enter_child_span(
2363 T::AddressMapper::to_address(self.account_id()),
2364 T::AddressMapper::to_address(&dest),
2365 None,
2366 false,
2367 is_read_only,
2368 value,
2369 &input_data,
2370 Default::default(),
2371 );
2372 });
2373
2374 let snapshot = if_tracing(|_| top_frame!(self).frame_meter.snapshot());
2375
2376 let result = if let Some(mock_answer) =
2377 self.exec_config.mock_handler.as_ref().and_then(|handler| {
2378 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2379 }) {
2380 *self.last_frame_output_mut() = mock_answer.clone();
2381 Ok(mock_answer)
2382 } else if is_read_only && value.is_zero() {
2383 Ok(Default::default())
2384 } else if is_read_only {
2385 Err(Error::<T>::StateChangeDenied.into())
2386 } else {
2387 let account_id = self.account_id().clone();
2388 let frame = top_frame_mut!(self);
2389 Self::transfer_from_origin(
2390 &self.origin,
2391 &Origin::from_account_id(account_id),
2392 &dest,
2393 value,
2394 &mut frame.frame_meter,
2395 self.exec_config,
2396 )
2397 };
2398
2399 if_tracing(|t| {
2400 let snapshot = snapshot.as_ref().expect(
2401 "snapshot is taken inside if_tracing above; tracing state cannot \
2402 change mid-call, so it is Some whenever this closure runs; qed",
2403 );
2404 let (gas_used, weight_delta) =
2405 top_frame!(self).frame_meter.delta_since(snapshot);
2406 match result {
2407 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_delta),
2408 Err(e) => {
2409 t.exit_child_span_with_error(e.error.into(), gas_used, weight_delta)
2410 },
2411 }
2412 });
2413
2414 result.map(|_| ())
2415 }
2416 };
2417
2418 let result = try_call();
2420
2421 self.top_frame_mut().allows_reentry = true;
2423
2424 result
2425 }
2426
2427 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2428 self.with_transient_storage(|transient_storage| {
2429 transient_storage.read(self.account_id(), key)
2430 })
2431 }
2432
2433 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2434 self.with_transient_storage(|transient_storage| {
2435 transient_storage.read(self.account_id(), key).map(|value| value.len() as _)
2436 })
2437 }
2438
2439 fn set_transient_storage(
2440 &mut self,
2441 key: &Key,
2442 value: Option<Vec<u8>>,
2443 take_old: bool,
2444 ) -> Result<WriteOutcome, DispatchError> {
2445 let account_id = self.account_id().clone();
2446 self.with_transient_storage_mut(|transient_storage| {
2447 transient_storage.write(&account_id, key, value, take_old)
2448 })
2449 }
2450
2451 fn account_id(&self) -> &T::AccountId {
2452 &self.top_frame().account_id
2453 }
2454
2455 fn caller(&self) -> Origin<T> {
2456 if let Some(Ok(mock_caller)) = self
2457 .exec_config
2458 .mock_handler
2459 .as_ref()
2460 .and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2461 .map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2462 {
2463 return mock_caller;
2464 }
2465
2466 self.caller_at(0)
2467 }
2468
2469 fn caller_of_caller(&self) -> Origin<T> {
2470 self.caller_at(1)
2471 }
2472
2473 fn origin(&self) -> &Origin<T> {
2474 if let Some(mock_origin) = self
2475 .exec_config
2476 .mock_handler
2477 .as_ref()
2478 .and_then(|mock_handler| mock_handler.mock_origin())
2479 {
2480 return mock_origin;
2481 }
2482
2483 &self.origin
2484 }
2485
2486 fn to_account_id(&self, address: &H160) -> T::AccountId {
2487 T::AddressMapper::to_account_id(address)
2488 }
2489
2490 fn code_hash(&self, address: &H160) -> H256 {
2491 match self.code_source(address) {
2492 Some(CodeSource::Virtual(code)) => sp_io::hashing::keccak_256(code).into(),
2493 Some(CodeSource::Indicator(indicator)) => sp_io::hashing::keccak_256(&indicator).into(),
2494 Some(CodeSource::Contract(code_hash)) => code_hash,
2495 None if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) => {
2496 EMPTY_CODE_HASH
2497 },
2498 None => H256::zero(),
2499 }
2500 }
2501
2502 fn code_size(&self, address: &H160) -> u64 {
2503 match self.code_source(address) {
2504 Some(CodeSource::Virtual(code)) => code.len() as u64,
2505 Some(CodeSource::Indicator(indicator)) => indicator.len() as u64,
2506 Some(CodeSource::Contract(code_hash)) => {
2507 CodeInfoOf::<T>::get(code_hash).map(|info| info.code_len()).unwrap_or_default()
2508 },
2509 None => 0,
2510 }
2511 }
2512
2513 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2514 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2515 self.origin == caller
2516 }
2517
2518 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2519 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2521 }
2522
2523 fn origin_is_root(&self) -> bool {
2524 self.origin == Origin::Root
2525 }
2526
2527 fn balance(&self) -> U256 {
2528 self.account_balance(&self.top_frame().account_id)
2529 }
2530
2531 fn balance_of(&self, address: &H160) -> U256 {
2532 let balance =
2533 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2534 if_tracing(|tracer| {
2535 tracer.balance_read(address, balance);
2536 });
2537 balance
2538 }
2539
2540 fn value_transferred(&self) -> U256 {
2541 self.top_frame().value_transferred.into()
2542 }
2543
2544 fn now(&self) -> U256 {
2545 (self.timestamp / 1000u32.into()).into()
2546 }
2547
2548 fn minimum_balance(&self) -> U256 {
2549 let min = T::Currency::minimum_balance();
2550 crate::Pallet::<T>::convert_native_to_evm(min)
2551 }
2552
2553 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2554 let contract = T::AddressMapper::to_address(self.account_id());
2555 if_tracing(|tracer| {
2556 let log_index = frame_system::Pallet::<Self::T>::event_count();
2557 tracer.log_event(contract, &topics, &data, log_index);
2558 });
2559
2560 block_storage::capture_frame_log::<T>(&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 fn copy_padded(buf: &mut [u8], code: &[u8], code_offset: usize) {
2649 let code = code.get(code_offset..).unwrap_or_default();
2650 let len = buf.len().min(code.len());
2651 buf[..len].copy_from_slice(&code[..len]);
2652 buf[len..].fill(0);
2653 }
2654
2655 if buf.is_empty() {
2656 return;
2657 }
2658
2659 match self.code_source(address) {
2660 Some(CodeSource::Virtual(code)) => copy_padded(buf, code, code_offset),
2661 Some(CodeSource::Indicator(indicator)) => copy_padded(buf, &indicator, code_offset),
2662 Some(CodeSource::Contract(code_hash)) => copy_padded(
2663 buf,
2664 &crate::PristineCode::<T>::get(&code_hash).unwrap_or_default(),
2665 code_offset,
2666 ),
2667 None => buf.fill(0),
2668 }
2669 }
2670
2671 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2672 ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2673 let parent = self.frames_mut().nth(1).ok_or_else(|| Error::<T>::ContractNotFound)?;
2674 ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2675 ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2676
2677 let contract_address = T::AddressMapper::to_address(&parent.account_id);
2678
2679 ensure!(
2681 !AccountInfo::<T>::is_delegated(&contract_address),
2682 Error::<T>::CannotTerminateDelegatedAccount,
2683 );
2684
2685 let info = parent.contract_info();
2686 let trie_id = info.trie_id.clone();
2687 let code_hash = info.code_hash;
2688 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2689
2690 let parent_account_id = parent.account_id.clone();
2691
2692 Self::transfer(
2694 &self.origin,
2695 &parent_account_id,
2696 &beneficiary,
2697 <Contracts<T>>::evm_balance(&contract_address),
2698 Preservation::Preserve,
2699 &mut top_frame_mut!(self).frame_meter,
2700 &self.exec_config,
2701 )?;
2702
2703 let args = TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: false };
2705 self.top_frame_mut().contracts_to_be_destroyed.insert(parent_account_id, args);
2706
2707 Ok(())
2708 }
2709
2710 fn effective_gas_price(&self) -> U256 {
2711 self.exec_config
2712 .effective_gas_price
2713 .unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2714 }
2715
2716 fn gas_left(&self) -> u64 {
2717 let frame = self.top_frame();
2718
2719 frame.frame_meter.eth_gas_left().unwrap_or_default().saturated_into::<u64>()
2720 }
2721
2722 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2723 assert!(self.has_contract_info());
2724 self.top_frame_mut().contract_info().read(key)
2725 }
2726
2727 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2728 assert!(self.has_contract_info());
2729 self.top_frame_mut().contract_info().size(key.into())
2730 }
2731
2732 fn set_storage(
2733 &mut self,
2734 key: &Key,
2735 value: Option<Vec<u8>>,
2736 take_old: bool,
2737 ) -> Result<WriteOutcome, DispatchError> {
2738 assert!(self.has_contract_info());
2739 let frame = self.top_frame_mut();
2740 frame.contract_info.get(&frame.account_id).write(
2741 key.into(),
2742 value,
2743 Some(&mut frame.frame_meter),
2744 take_old,
2745 )
2746 }
2747
2748 fn touch_storage_access(&mut self, key: &Key, op: StorageOp) -> Warmth {
2749 let address = self.address();
2750 self.access_list.touch(AccessEntry { address, slot: key.into() }, op)
2751 }
2752
2753 fn peek_storage_access(&self, key: &Key) -> Warmth {
2754 let address = self.address();
2755 self.access_list.peek(&AccessEntry { address, slot: key.into() })
2756 }
2757
2758 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult {
2759 assert!(self.has_contract_info());
2760 self.top_frame_mut().frame_meter.record_contract_storage_changes(diff)
2761 }
2762}
2763
2764pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2766 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2767}
2768
2769#[cfg(feature = "runtime-benchmarks")]
2770pub fn bench_do_terminate<T: Config>(
2771 transaction_meter: &mut TransactionMeter<T>,
2772 exec_config: &ExecConfig<T>,
2773 contract_account: &T::AccountId,
2774 origin: &Origin<T>,
2775 beneficiary: T::AccountId,
2776 trie_id: TrieId,
2777 code_hash: H256,
2778 only_if_same_tx: bool,
2779) -> Result<(), DispatchError> {
2780 Stack::<T, crate::ContractBlob<T>>::do_terminate(
2781 transaction_meter,
2782 exec_config,
2783 contract_account,
2784 origin,
2785 &TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx },
2786 )
2787}
2788
2789mod sealing {
2790 use super::*;
2791
2792 pub trait Sealed {}
2793 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2794
2795 #[cfg(test)]
2796 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2797}