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,
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, AccountType, WriteOutcome},
32 tracing::if_tracing,
33 transient_storage::TransientStorage,
34};
35use alloc::{
36 collections::{BTreeMap, BTreeSet, btree_map},
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 defensive,
44 dispatch::DispatchResult,
45 ensure,
46 storage::{TransactionOutcome, with_transaction},
47 traits::{
48 Time,
49 fungible::{Balanced as _, Inspect, Mutate},
50 tokens::Preservation,
51 },
52 weights::Weight,
53};
54use frame_system::{
55 Pallet as System, RawOrigin,
56 pallet_prelude::{BlockNumberFor, OriginFor},
57};
58use sp_core::{
59 ConstU32, Get, H160, H256, U256,
60 ecdsa::Public as ECDSAPublic,
61 sr25519::{Public as SR25519Public, Signature as SR25519Signature},
62};
63use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
64use sp_runtime::{
65 DispatchError, SaturatedConversion,
66 traits::{BadOrigin, Saturating, TrailingZeroInput, Zero},
67};
68
69#[cfg(test)]
70mod tests;
71
72#[cfg(test)]
73pub mod mock_ext;
74
75pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
76pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
77pub type ExecResult = Result<ExecReturnValue, ExecError>;
78
79type VarSizedKey = BoundedVec<u8, ConstU32<{ limits::STORAGE_KEY_BYTES }>>;
81
82const 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";
83
84pub const EMPTY_CODE_HASH: H256 =
86 H256(sp_core::hex2array!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
87
88#[derive(Debug)]
90pub enum Key {
91 Fix([u8; 32]),
93 Var(VarSizedKey),
95}
96
97impl Key {
98 pub fn unhashed(&self) -> &[u8] {
100 match self {
101 Key::Fix(v) => v.as_ref(),
102 Key::Var(v) => v.as_ref(),
103 }
104 }
105
106 pub fn hash(&self) -> Vec<u8> {
108 match self {
109 Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
110 Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
111 }
112 }
113
114 pub fn from_fixed(v: [u8; 32]) -> Self {
115 Self::Fix(v)
116 }
117
118 pub fn try_from_var(v: Vec<u8>) -> Result<Self, ()> {
119 VarSizedKey::try_from(v).map(Self::Var).map_err(|_| ())
120 }
121}
122
123#[derive(Copy, Clone, PartialEq, Debug)]
129pub enum ReentrancyProtection {
130 AllowReentry,
132 Strict,
135 AllowNext,
143}
144
145#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
151pub enum ErrorOrigin {
152 Caller,
157 Callee,
159}
160
161#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
163pub struct ExecError {
164 pub error: DispatchError,
166 pub origin: ErrorOrigin,
168}
169
170impl<T: Into<DispatchError>> From<T> for ExecError {
171 fn from(error: T) -> Self {
172 Self { error: error.into(), origin: ErrorOrigin::Caller }
173 }
174}
175
176#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, DebugNoBound)]
178pub enum Origin<T: Config> {
179 Root,
180 Signed(T::AccountId),
181}
182
183impl<T: Config> Origin<T> {
184 pub fn from_account_id(account_id: T::AccountId) -> Self {
186 Origin::Signed(account_id)
187 }
188
189 pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
191 match o.into() {
192 Ok(RawOrigin::Root) => Ok(Self::Root),
193 Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
194 _ => Err(BadOrigin.into()),
195 }
196 }
197
198 pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
200 match self {
201 Origin::Signed(id) => Ok(id),
202 Origin::Root => Err(DispatchError::RootNotAllowed),
203 }
204 }
205
206 fn ensure_mapped(&self) -> DispatchResult {
211 match self {
212 Self::Root => Ok(()),
213 Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()),
214 Self::Signed(_) => Err(<Error<T>>::AccountUnmapped.into()),
215 }
216 }
217}
218
219#[derive(DebugNoBound)]
222pub enum CallResources<T: Config> {
223 NoLimits,
225 WeightDeposit { weight: Weight, deposit_limit: BalanceOf<T> },
227 Ethereum { gas: BalanceOf<T>, add_stipend: bool },
229}
230
231impl<T: Config> CallResources<T> {
232 pub fn from_weight_and_deposit(weight: Weight, deposit_limit: U256) -> Self {
234 Self::WeightDeposit {
235 weight,
236 deposit_limit: deposit_limit.saturated_into::<BalanceOf<T>>(),
237 }
238 }
239
240 pub fn from_ethereum_gas(gas: U256, add_stipend: bool) -> Self {
242 Self::Ethereum { gas: gas.saturated_into::<BalanceOf<T>>(), add_stipend }
243 }
244}
245
246impl<T: Config> Default for CallResources<T> {
247 fn default() -> Self {
248 Self::WeightDeposit { weight: Default::default(), deposit_limit: Default::default() }
249 }
250}
251
252struct TerminateArgs<T: Config> {
254 beneficiary: T::AccountId,
256 only_if_same_tx: bool,
258 refunded: BalanceOf<T>,
260}
261
262pub trait Ext: PrecompileWithInfoExt {
264 fn delegate_call(
268 &mut self,
269 call_resources: &CallResources<Self::T>,
270 address: H160,
271 input_data: Vec<u8>,
272 ) -> Result<(), ExecError>;
273
274 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError>;
281
282 #[allow(dead_code)]
284 fn own_code_hash(&mut self) -> &H256;
285
286 fn immutable_data_len(&mut self) -> u32;
290
291 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError>;
295
296 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError>;
302}
303
304pub trait PrecompileWithInfoExt: PrecompileExt {
306 fn instantiate(
312 &mut self,
313 limits: &CallResources<Self::T>,
314 code: Code,
315 value: U256,
316 input_data: Vec<u8>,
317 salt: Option<&[u8; 32]>,
318 ) -> Result<H160, ExecError>;
319}
320
321pub trait PrecompileExt: sealing::Sealed {
323 type T: Config;
324
325 fn charge(&mut self, weight: Weight) -> Result<ChargedAmount, DispatchError> {
327 self.frame_meter_mut().charge_weight_token(RuntimeCosts::Precompile(weight))
328 }
329
330 fn adjust_gas(&mut self, charged: ChargedAmount, actual_weight: Weight) {
333 self.frame_meter_mut()
334 .adjust_weight(charged, RuntimeCosts::Precompile(actual_weight));
335 }
336
337 #[inline]
340 fn charge_or_halt<Tok: Token<Self::T>>(
341 &mut self,
342 token: Tok,
343 ) -> ControlFlow<crate::vm::evm::Halt, ChargedAmount> {
344 self.frame_meter_mut().charge_or_halt(token)
345 }
346
347 fn call(
349 &mut self,
350 call_resources: &CallResources<Self::T>,
351 to: &H160,
352 value: U256,
353 input_data: Vec<u8>,
354 reentrancy: ReentrancyProtection,
355 read_only: bool,
356 ) -> Result<(), ExecError>;
357
358 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>>;
363
364 fn get_transient_storage_size(&self, key: &Key) -> Option<u32>;
369
370 fn set_transient_storage(
373 &mut self,
374 key: &Key,
375 value: Option<Vec<u8>>,
376 take_old: bool,
377 ) -> Result<WriteOutcome, DispatchError>;
378
379 fn caller(&self) -> Origin<Self::T>;
381
382 fn caller_of_caller(&self) -> Origin<Self::T>;
384
385 fn origin(&self) -> &Origin<Self::T>;
387
388 fn to_account_id(&self, address: &H160) -> AccountIdOf<Self::T>;
390
391 fn code_hash(&self, address: &H160) -> H256;
394
395 fn code_size(&self, address: &H160) -> u64;
397
398 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool;
400
401 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool;
403
404 fn origin_is_root(&self) -> bool;
409
410 fn account_id(&self) -> &AccountIdOf<Self::T>;
412
413 fn address(&self) -> H160 {
415 <Self::T as Config>::AddressMapper::to_address(self.account_id())
416 }
417
418 fn balance(&self) -> U256;
422
423 fn balance_of(&self, address: &H160) -> U256;
427
428 fn value_transferred(&self) -> U256;
430
431 fn now(&self) -> U256;
433
434 fn minimum_balance(&self) -> U256;
436
437 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
441
442 fn block_number(&self) -> U256;
444
445 fn block_hash(&self, block_number: U256) -> Option<H256>;
448
449 fn block_author(&self) -> H160;
451
452 fn gas_limit(&self) -> u64;
454
455 fn chain_id(&self) -> u64;
457
458 #[deprecated(note = "Renamed to `frame_meter`; this alias will be removed in future versions")]
460 fn gas_meter(&self) -> &FrameMeter<Self::T>;
461
462 #[deprecated(
464 note = "Renamed to `frame_meter_mut`; this alias will be removed in future versions"
465 )]
466 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
467
468 fn frame_meter(&self) -> &FrameMeter<Self::T>;
470
471 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
473
474 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
476
477 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
479
480 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError>;
482
483 #[cfg(any(test, feature = "runtime-benchmarks"))]
485 fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
486
487 #[cfg(any(feature = "runtime-benchmarks", test))]
491 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
492
493 fn is_read_only(&self) -> bool;
495
496 fn is_delegate_call(&self) -> bool;
498
499 fn last_frame_output(&self) -> &ExecReturnValue;
501
502 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
504
505 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize);
513
514 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError>;
523
524 fn effective_gas_price(&self) -> U256;
526
527 fn gas_left(&self) -> u64;
529
530 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
535
536 fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
541
542 fn set_storage(
545 &mut self,
546 key: &Key,
547 value: Option<Vec<u8>>,
548 take_old: bool,
549 ) -> Result<WriteOutcome, DispatchError>;
550
551 fn touch_storage_access(&mut self, key: &Key, op: StorageOp) -> Warmth;
556
557 fn peek_storage_access(&self, key: &Key) -> Warmth;
560
561 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult;
563}
564
565#[derive(
567 Copy,
568 Clone,
569 PartialEq,
570 Eq,
571 Debug,
572 codec::Decode,
573 codec::Encode,
574 codec::MaxEncodedLen,
575 scale_info::TypeInfo,
576)]
577pub enum ExportedFunction {
578 Constructor,
580 Call,
582}
583
584pub trait Executable<T: Config>: Sized {
589 fn from_storage<S: State>(
594 code_hash: H256,
595 meter: &mut ResourceMeter<T, S>,
596 ) -> Result<Self, DispatchError>;
597
598 fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
600
601 fn execute<E: Ext<T = T>>(
611 self,
612 ext: &mut E,
613 function: ExportedFunction,
614 input_data: Vec<u8>,
615 ) -> ExecResult;
616
617 fn code_info(&self) -> &CodeInfo<T>;
619
620 fn code(&self) -> &[u8];
622
623 fn code_hash(&self) -> &H256;
625}
626
627pub struct Stack<'a, T: Config, E> {
633 origin: Origin<T>,
642 transaction_meter: &'a mut TransactionMeter<T>,
644 timestamp: MomentOf<T>,
646 block_number: BlockNumberFor<T>,
648 frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
651 first_frame: Frame<T>,
653 transient_storage: TransientStorage<T>,
655 access_list: AccessList,
657 exec_config: &'a ExecConfig<T>,
659 _phantom: PhantomData<E>,
661}
662
663struct Frame<T: Config> {
668 account_id: T::AccountId,
670 contract_info: CachedContract<T>,
672 value_transferred: U256,
674 entry_point: ExportedFunction,
676 frame_meter: FrameMeter<T>,
678 allows_reentry: bool,
680 read_only: bool,
682 delegate: Option<DelegateInfo<T>>,
685 code_address: H160,
691 last_frame_output: ExecReturnValue,
693 contracts_created: BTreeSet<T::AccountId>,
695 contracts_to_be_destroyed: BTreeMap<T::AccountId, TerminateArgs<T>>,
697}
698
699#[derive(Clone, DebugNoBound)]
702pub struct DelegateInfo<T: Config> {
703 pub caller: Origin<T>,
705 pub callee: H160,
707}
708
709enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
711 Executable(E),
713 Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
715}
716
717impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
718 fn as_executable(&self) -> Option<&E> {
719 if let Self::Executable(executable) = self { Some(executable) } else { None }
720 }
721
722 fn is_pvm(&self) -> bool {
723 match self {
724 Self::Executable(e) => e.code_info().is_pvm(),
725 _ => false,
726 }
727 }
728
729 fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
730 if let Self::Precompile { instance, .. } = self { Some(instance) } else { None }
731 }
732
733 #[cfg(any(feature = "runtime-benchmarks", test))]
734 fn into_executable(self) -> Option<E> {
735 if let Self::Executable(executable) = self { Some(executable) } else { None }
736 }
737}
738
739enum FrameArgs<'a, T: Config, E> {
743 Call {
744 dest: T::AccountId,
746 cached_info: Option<ContractInfo<T>>,
748 delegated_call: Option<DelegateInfo<T>>,
752 },
753 Instantiate {
754 sender: T::AccountId,
756 executable: E,
758 salt: Option<&'a [u8; 32]>,
760 input_data: &'a [u8],
762 },
763}
764
765enum CachedContract<T: Config> {
767 Cached(ContractInfo<T>),
769 Invalidated,
773 None,
775}
776
777impl<T: Config> Frame<T> {
778 fn contract_info(&mut self) -> &mut ContractInfo<T> {
780 self.contract_info.get(&self.account_id)
781 }
782
783 fn schedule_termination(&mut self, account_id: T::AccountId, args: TerminateArgs<T>) {
792 match self.contracts_to_be_destroyed.entry(account_id) {
793 btree_map::Entry::Occupied(mut entry) => {
794 let old = entry.get();
795 let only_if_same_tx = old.only_if_same_tx && args.only_if_same_tx;
796 let refunded = old.refunded.saturating_add(args.refunded);
797 entry.insert(TerminateArgs { only_if_same_tx, refunded, ..args });
798 },
799 btree_map::Entry::Vacant(entry) => {
800 entry.insert(args);
801 },
802 }
803 }
804}
805
806macro_rules! get_cached_or_panic_after_load {
810 ($c:expr) => {{
811 if let CachedContract::Cached(contract) = $c {
812 contract
813 } else {
814 panic!(
815 "It is impossible to remove a contract that is on the call stack;\
816 See implementations of terminate;\
817 Therefore fetching a contract will never fail while using an account id
818 that is currently active on the call stack;\
819 qed"
820 );
821 }
822 }};
823}
824
825macro_rules! top_frame {
830 ($stack:expr) => {
831 $stack.frames.last().unwrap_or(&$stack.first_frame)
832 };
833}
834
835macro_rules! top_frame_mut {
840 ($stack:expr) => {
841 $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
842 };
843}
844
845impl<T: Config> CachedContract<T> {
846 fn into_contract(self) -> Option<ContractInfo<T>> {
848 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
849 }
850
851 fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
853 if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
854 }
855
856 fn load(&mut self, account_id: &T::AccountId) {
858 if let CachedContract::Invalidated = self &&
859 let Some(contract) =
860 AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
861 {
862 *self = CachedContract::Cached(contract);
863 }
864 }
865
866 fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
868 self.load(account_id);
869 get_cached_or_panic_after_load!(self)
870 }
871
872 fn invalidate(&mut self) {
874 if matches!(self, CachedContract::Cached(_)) {
875 *self = CachedContract::Invalidated;
876 }
877 }
878}
879
880impl<'a, T, E> Stack<'a, T, E>
881where
882 T: Config,
883 E: Executable<T>,
884{
885 pub fn run_call(
891 origin: Origin<T>,
892 dest: H160,
893 transaction_meter: &'a mut TransactionMeter<T>,
894 value: U256,
895 input_data: Vec<u8>,
896 exec_config: &ExecConfig<T>,
897 ) -> ExecResult {
898 let dest = T::AddressMapper::to_account_id(&dest);
899 if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
900 FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
901 origin.clone(),
902 transaction_meter,
903 value,
904 exec_config,
905 &input_data,
906 )? {
907 stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
908 } else {
909 if_tracing(|t| {
910 t.enter_child_span(
911 origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
912 T::AddressMapper::to_address(&dest),
913 None,
914 false,
915 false,
916 value,
917 &input_data,
918 Default::default(),
919 );
920 });
921
922 let result = if let Some(mock_answer) =
923 exec_config.mock_handler.as_ref().and_then(|handler| {
924 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
925 }) {
926 Ok(mock_answer)
927 } else {
928 Self::transfer_from_origin(
929 &origin,
930 &origin,
931 &dest,
932 value,
933 transaction_meter,
934 exec_config,
935 )
936 };
937
938 if_tracing(|t| {
939 let gas_used =
940 transaction_meter.total_consumed_gas().try_into().unwrap_or(u64::MAX);
941 let weight_consumed = transaction_meter.weight_consumed();
942 match result {
943 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_consumed),
944 Err(e) => {
945 t.exit_child_span_with_error(e.error.into(), gas_used, weight_consumed)
946 },
947 }
948 });
949
950 log::trace!(target: LOG_TARGET, "call finished with: {result:?}");
951
952 result
953 }
954 }
955
956 pub fn run_instantiate(
962 origin: T::AccountId,
963 executable: E,
964 transaction_meter: &'a mut TransactionMeter<T>,
965 value: U256,
966 input_data: Vec<u8>,
967 salt: Option<&[u8; 32]>,
968 exec_config: &ExecConfig<T>,
969 ) -> Result<(H160, ExecReturnValue), ExecError> {
970 let deployer = T::AddressMapper::to_address(&origin);
971 let (mut stack, executable) = Stack::<'_, T, E>::new(
972 FrameArgs::Instantiate {
973 sender: origin.clone(),
974 executable,
975 salt,
976 input_data: input_data.as_ref(),
977 },
978 Origin::from_account_id(origin),
979 transaction_meter,
980 value,
981 exec_config,
982 &input_data,
983 )?
984 .expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
985 let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
986 let result = stack
987 .run(executable, input_data)
988 .map(|_| (address, stack.first_frame.last_frame_output));
989 if let Ok((contract, output)) = &result &&
990 !output.did_revert()
991 {
992 Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract: *contract });
993 }
994 log::trace!(target: LOG_TARGET, "instantiate finished with: {result:?}");
995 result
996 }
997
998 #[cfg(any(feature = "runtime-benchmarks", test))]
999 pub fn bench_new_call(
1000 dest: H160,
1001 origin: Origin<T>,
1002 transaction_meter: &'a mut TransactionMeter<T>,
1003 value: BalanceOf<T>,
1004 exec_config: &'a ExecConfig<T>,
1005 read_only: bool,
1006 delegate_call: bool,
1007 ) -> (Self, E) {
1008 let call = Self::new(
1009 FrameArgs::Call {
1010 dest: T::AddressMapper::to_account_id(&dest),
1011 cached_info: None,
1012 delegated_call: None,
1013 },
1014 origin,
1015 transaction_meter,
1016 value.into(),
1017 exec_config,
1018 &Default::default(),
1019 )
1020 .unwrap()
1021 .unwrap();
1022 let mut stack = call.0;
1023 if read_only {
1024 stack.top_frame_mut().read_only = true;
1025 }
1026 if delegate_call {
1027 let frame = stack.top_frame_mut();
1028 frame.delegate = Some(DelegateInfo {
1029 caller: Origin::from_account_id(frame.account_id.clone()),
1030 callee: H160::zero(),
1031 });
1032 }
1033 (stack, call.1.into_executable().unwrap())
1034 }
1035
1036 fn new(
1041 args: FrameArgs<T, E>,
1042 origin: Origin<T>,
1043 transaction_meter: &'a mut TransactionMeter<T>,
1044 value: U256,
1045 exec_config: &'a ExecConfig<T>,
1046 input_data: &Vec<u8>,
1047 ) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1048 origin.ensure_mapped()?;
1049 let Some((first_frame, executable)) = Self::new_frame(
1050 args,
1051 value,
1052 transaction_meter,
1053 &CallResources::NoLimits,
1054 false,
1055 true,
1056 input_data,
1057 exec_config,
1058 )?
1059 else {
1060 return Ok(None);
1061 };
1062
1063 let mut timestamp = T::Time::now();
1064 let mut block_number = <frame_system::Pallet<T>>::block_number();
1065 if let Some(timestamp_override) =
1067 exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override)
1068 {
1069 block_number = block_number.saturating_add(1u32.into());
1070 let delta = 1000u32.into();
1072 timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override);
1073 }
1074
1075 let stack = Self {
1076 origin,
1077 transaction_meter,
1078 timestamp,
1079 block_number,
1080 first_frame,
1081 frames: Default::default(),
1082 transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
1083 access_list: AccessList::new(),
1084 exec_config,
1085 _phantom: Default::default(),
1086 };
1087 Ok(Some((stack, executable)))
1088 }
1089
1090 fn fail_if_chained_delegation(target: Option<H160>) -> Result<(), ExecError> {
1100 if let Some(target) = target &&
1101 AccountInfo::<T>::is_delegated(&target)
1102 {
1103 return Err(ExecError {
1104 error: <Error<T>>::ContractTrapped.into(),
1105 origin: ErrorOrigin::Callee,
1106 });
1107 }
1108 Ok(())
1109 }
1110
1111 fn new_frame<S: State>(
1116 frame_args: FrameArgs<T, E>,
1117 value_transferred: U256,
1118 meter: &mut ResourceMeter<T, S>,
1119 call_resources: &CallResources<T>,
1120 read_only: bool,
1121 origin_is_caller: bool,
1122 input_data: &[u8],
1123 exec_config: &ExecConfig<T>,
1124 ) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1125 let mut read_delegation: Option<Option<H160>> = None;
1128 let mut delegate_code_target: Option<H160> = None;
1132
1133 let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
1134 FrameArgs::Call { dest, cached_info, delegated_call } => {
1135 let address = T::AddressMapper::to_address(&dest);
1136 let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
1137
1138 let mut contract = match (cached_info, &precompile) {
1141 (Some(info), _) => CachedContract::Cached(info),
1142 (None, None) => {
1143 let (info, target) =
1144 AccountInfo::<T>::load_contract_with_delegation(&address);
1145 read_delegation = Some(target);
1146 if let Some(info) = info {
1147 CachedContract::Cached(info)
1148 } else {
1149 Self::fail_if_chained_delegation(target)?;
1150 return Ok(None);
1151 }
1152 },
1153 (None, Some(precompile)) if precompile.has_contract_info() => {
1154 log::trace!(target: LOG_TARGET, "found precompile for address {address:?}");
1155 let (info, target) =
1156 AccountInfo::<T>::load_contract_with_delegation(&address);
1157 read_delegation = Some(target);
1158 if let Some(info) = info {
1159 CachedContract::Cached(info)
1160 } else {
1161 let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
1162 CachedContract::Cached(info)
1163 }
1164 },
1165 (None, Some(_)) => {
1168 read_delegation = Some(None);
1169 CachedContract::None
1170 },
1171 };
1172
1173 let delegated_call = delegated_call.or_else(|| {
1174 exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1175 mock_handler.mock_delegated_caller(address, input_data)
1176 })
1177 });
1178 let executable = if let Some(delegated_call) = &delegated_call {
1180 if let Some(precompile) =
1181 <AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
1182 {
1183 ExecutableOrPrecompile::Precompile {
1184 instance: precompile,
1185 _phantom: Default::default(),
1186 }
1187 } else {
1188 let (info, target) =
1189 AccountInfo::<T>::load_contract_with_delegation(&delegated_call.callee);
1190 let Some(info) = info else {
1191 Self::fail_if_chained_delegation(target)?;
1192 return Ok(None);
1193 };
1194 delegate_code_target = target;
1195 let executable = E::from_storage(info.code_hash, meter)?;
1196 ExecutableOrPrecompile::Executable(executable)
1197 }
1198 } else {
1199 if let Some(precompile) = precompile {
1200 ExecutableOrPrecompile::Precompile {
1201 instance: precompile,
1202 _phantom: Default::default(),
1203 }
1204 } else {
1205 let executable = E::from_storage(
1206 contract
1207 .as_contract()
1208 .expect("When not a precompile the contract was loaded above; qed")
1209 .code_hash,
1210 meter,
1211 )?;
1212 ExecutableOrPrecompile::Executable(executable)
1213 }
1214 };
1215
1216 (dest, contract, executable, delegated_call, ExportedFunction::Call)
1217 },
1218 FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1219 let deployer = T::AddressMapper::to_address(&sender);
1220 let account_nonce = <System<T>>::account_nonce(&sender);
1221 let address = if let Some(salt) = salt {
1222 address::create2(&deployer, executable.code(), input_data, salt)
1223 } else {
1224 use sp_runtime::Saturating;
1225 address::create1(
1226 &deployer,
1227 if origin_is_caller {
1230 account_nonce.saturating_sub(1u32.into()).saturated_into()
1231 } else {
1232 account_nonce.saturated_into()
1233 },
1234 )
1235 };
1236 let contract = ContractInfo::new(
1237 &address,
1238 <System<T>>::account_nonce(&sender),
1239 *executable.code_hash(),
1240 )?;
1241 (
1242 T::AddressMapper::to_fallback_account_id(&address),
1243 CachedContract::Cached(contract),
1244 ExecutableOrPrecompile::Executable(executable),
1245 None,
1246 ExportedFunction::Constructor,
1247 )
1248 },
1249 };
1250
1251 let address = T::AddressMapper::to_address(&account_id);
1256 let code_address = delegate
1257 .as_ref()
1258 .map(|d| delegate_code_target.unwrap_or(d.callee))
1259 .or_else(|| {
1260 if entry_point == ExportedFunction::Constructor {
1262 return None;
1263 }
1264 read_delegation.unwrap_or_else(|| AccountInfo::<T>::get_delegation_target(&address))
1265 })
1266 .unwrap_or(address);
1267
1268 let mut contracts_created = BTreeSet::new();
1271 if entry_point == ExportedFunction::Constructor {
1272 contracts_created.insert(account_id.clone());
1273 }
1274
1275 let frame = Frame {
1276 delegate,
1277 value_transferred,
1278 contract_info,
1279 account_id,
1280 entry_point,
1281 code_address,
1282 frame_meter: meter.new_nested(call_resources)?,
1283 allows_reentry: true,
1284 read_only,
1285 last_frame_output: Default::default(),
1286 contracts_created,
1287 contracts_to_be_destroyed: Default::default(),
1288 };
1289
1290 Ok(Some((frame, executable)))
1291 }
1292
1293 fn push_frame(
1295 &mut self,
1296 frame_args: FrameArgs<T, E>,
1297 value_transferred: U256,
1298 call_resources: &CallResources<T>,
1299 read_only: bool,
1300 input_data: &[u8],
1301 ) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1302 if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1303 return Err(Error::<T>::MaxCallDepthReached.into());
1304 }
1305
1306 let frame = self.top_frame();
1315 if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1316 (&frame.contract_info, frame.entry_point)
1317 {
1318 let mut contract_with_pending_changes = contract.clone();
1319 frame
1320 .frame_meter
1321 .apply_pending_storage_changes(&mut contract_with_pending_changes);
1322 AccountInfo::<T>::insert_contract(
1323 &T::AddressMapper::to_address(&frame.account_id),
1324 contract_with_pending_changes,
1325 );
1326 }
1327
1328 let frame = top_frame_mut!(self);
1329 let meter = &mut frame.frame_meter;
1330 if let Some((frame, executable)) = Self::new_frame(
1331 frame_args,
1332 value_transferred,
1333 meter,
1334 call_resources,
1335 read_only,
1336 false,
1337 input_data,
1338 self.exec_config,
1339 )? {
1340 if frame.entry_point == ExportedFunction::Constructor &&
1343 self.frames().any(|f| {
1344 f.entry_point == ExportedFunction::Constructor &&
1345 f.account_id == frame.account_id
1346 }) {
1347 return Err(Error::<T>::DuplicateContract.into());
1348 }
1349 self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1350 Ok(Some(executable))
1351 } else {
1352 Ok(None)
1353 }
1354 }
1355
1356 fn run(
1360 &mut self,
1361 executable: ExecutableOrPrecompile<T, E, Self>,
1362 input_data: Vec<u8>,
1363 ) -> Result<(), ExecError> {
1364 let frame = self.top_frame();
1365 let entry_point = frame.entry_point;
1366 let is_pvm = executable.is_pvm();
1367
1368 if_tracing(|tracer| {
1369 let (from, to) = match frame.delegate.as_ref() {
1372 Some(delegate) => {
1373 (T::AddressMapper::to_address(&frame.account_id), delegate.callee)
1374 },
1375 None => (
1376 self.caller()
1377 .account_id()
1378 .map(T::AddressMapper::to_address)
1379 .unwrap_or_default(),
1380 T::AddressMapper::to_address(&frame.account_id),
1381 ),
1382 };
1383 tracer.enter_child_span(
1384 from,
1385 to,
1386 (frame.code_address != to).then_some(frame.code_address),
1387 frame.delegate.is_some(),
1388 frame.read_only,
1389 frame.value_transferred,
1390 &input_data,
1391 frame
1392 .frame_meter
1393 .eth_gas_left()
1394 .unwrap_or_default()
1395 .try_into()
1396 .unwrap_or_default(),
1397 );
1398 });
1399 let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1400 handler.mock_call(
1401 frame
1402 .delegate
1403 .as_ref()
1404 .map(|delegate| delegate.callee)
1405 .unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1406 &input_data,
1407 frame.value_transferred,
1408 )
1409 });
1410 let frames_len = self.frames.len();
1414 if let Some(caller_frame) = match frames_len {
1415 0 => None,
1416 1 => Some(&mut self.first_frame.last_frame_output),
1417 _ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1418 } {
1419 *caller_frame = Default::default();
1420 }
1421
1422 self.with_transient_storage_mut(|transient_storage| {
1423 transient_storage.start_transaction();
1424 });
1425 let is_first_frame = self.frames.is_empty();
1426 let access_list_checkpoints_len = self.access_list.frame_depth();
1427 if !is_first_frame {
1431 self.access_list.enter_frame();
1432 }
1433
1434 let do_transaction = || -> ExecResult {
1435 let caller = self.caller();
1436 let bump_nonce = self.exec_config.bump_nonce;
1437 let frame = top_frame_mut!(self);
1438 let account_id = &frame.account_id.clone();
1439
1440 if u32::try_from(input_data.len())
1441 .map(|len| len > limits::CALLDATA_BYTES)
1442 .unwrap_or(true)
1443 {
1444 Err(<Error<T>>::CallDataTooLarge)?;
1445 }
1446
1447 if entry_point == ExportedFunction::Constructor {
1450 if !frame_system::Pallet::<T>::account_exists(&account_id) {
1451 T::Deposit::init_contract(account_id)?;
1452 }
1453
1454 <System<T>>::inc_consumers(account_id)?;
1459
1460 <System<T>>::inc_account_nonce(account_id);
1462
1463 if bump_nonce || !is_first_frame {
1464 <System<T>>::inc_account_nonce(caller.account_id()?);
1467 }
1468 if is_pvm {
1470 <CodeInfo<T>>::increment_refcount(
1471 *executable
1472 .as_executable()
1473 .expect("Precompiles cannot be instantiated; qed")
1474 .code_hash(),
1475 )?;
1476 }
1477 }
1478
1479 if frame.delegate.is_none() {
1483 Self::transfer_from_origin(
1484 &self.origin,
1485 &caller,
1486 account_id,
1487 frame.value_transferred,
1488 &mut frame.frame_meter,
1489 self.exec_config,
1490 )?;
1491 }
1492
1493 if let Some(precompile) = executable.as_precompile() &&
1500 precompile.has_contract_info() &&
1501 frame.delegate.is_none() &&
1502 !<System<T>>::account_exists(account_id)
1503 {
1504 T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1507 <System<T>>::inc_consumers(account_id)?;
1509 }
1510
1511 let mut code_deposit = executable
1512 .as_executable()
1513 .map(|exec| exec.code_info().deposit())
1514 .unwrap_or_default();
1515
1516 let mut output = match executable {
1517 ExecutableOrPrecompile::Executable(executable) => {
1518 executable.execute(self, entry_point, input_data)
1519 },
1520 ExecutableOrPrecompile::Precompile { instance, .. } => {
1521 instance.call(input_data, self)
1522 },
1523 }
1524 .and_then(|output| {
1525 if u32::try_from(output.data.len())
1526 .map(|len| len > limits::CALLDATA_BYTES)
1527 .unwrap_or(true)
1528 {
1529 Err(<Error<T>>::ReturnDataTooLarge)?;
1530 }
1531 Ok(output)
1532 })
1533 .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1534
1535 if output.did_revert() {
1537 return Ok(output);
1538 }
1539
1540 let frame = if entry_point == ExportedFunction::Constructor {
1543 let frame = top_frame_mut!(self);
1544 if !is_pvm {
1547 let data = if crate::tracing::if_tracing(|_| {}).is_none() &&
1551 self.exec_config.is_dry_run.is_none()
1552 {
1553 core::mem::replace(&mut output.data, Default::default())
1554 } else {
1555 output.data.clone()
1556 };
1557
1558 let mut module = match &self.origin {
1562 Origin::Signed(o) => {
1563 crate::ContractBlob::<T>::from_evm_runtime_code(data, o.clone())?
1564 },
1565 Origin::Root => {
1566 crate::ContractBlob::<T>::from_evm_runtime_code_with_deposit(
1567 data,
1568 crate::Pallet::<T>::account_id(),
1569 Zero::zero(),
1570 )?
1571 },
1572 };
1573 module.store_code(&self.exec_config, &mut frame.frame_meter)?;
1574 code_deposit = module.code_info().deposit();
1575
1576 let code_hash = *module.code_hash();
1577 frame.contract_info().code_hash = code_hash;
1578 <CodeInfo<T>>::increment_refcount(code_hash)?;
1579 }
1580
1581 let deposit = frame.contract_info().update_base_deposit(code_deposit);
1582 frame.frame_meter.charge_contract_deposit_and_transfer(
1583 frame.account_id.clone(),
1584 StorageDeposit::Charge(deposit),
1585 )?;
1586 frame
1587 } else {
1588 self.top_frame_mut()
1589 };
1590
1591 let contract = frame.contract_info.as_contract();
1595 frame
1596 .frame_meter
1597 .finalize(contract)
1598 .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1599
1600 Ok(output)
1601 };
1602
1603 let transaction_outcome =
1610 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1611 let output = if let Some(mock_answer) = mock_answer {
1612 Ok(mock_answer)
1613 } else {
1614 do_transaction()
1615 };
1616 match &output {
1617 Ok(result) if !result.did_revert() => {
1618 TransactionOutcome::Commit(Ok((true, output)))
1619 },
1620 _ => TransactionOutcome::Rollback(Ok((false, output))),
1621 }
1622 });
1623
1624 let (success, output) = match transaction_outcome {
1625 Ok((success, output)) => {
1627 if_tracing(|tracer| {
1628 let frame_meter = &top_frame!(self).frame_meter;
1629
1630 let gas_consumed = if is_first_frame {
1633 frame_meter.total_consumed_gas()
1634 } else {
1635 frame_meter.eth_gas_consumed()
1636 };
1637
1638 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1639 let weight_consumed = frame_meter.weight_consumed();
1640
1641 match &output {
1642 Ok(output) => {
1643 tracer.exit_child_span(&output, gas_consumed, weight_consumed)
1644 },
1645 Err(e) => tracer.exit_child_span_with_error(
1646 e.error.into(),
1647 gas_consumed,
1648 weight_consumed,
1649 ),
1650 }
1651 });
1652
1653 (success, output)
1654 },
1655 Err(error) => {
1658 if_tracing(|tracer| {
1659 let frame_meter = &top_frame!(self).frame_meter;
1660
1661 let gas_consumed = if is_first_frame {
1664 frame_meter.total_consumed_gas()
1665 } else {
1666 frame_meter.eth_gas_consumed()
1667 };
1668
1669 let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1670 let weight_consumed = frame_meter.weight_consumed();
1671 tracer.exit_child_span_with_error(error.into(), gas_consumed, weight_consumed);
1672 });
1673
1674 (false, Err(error.into()))
1675 },
1676 };
1677 self.with_transient_storage_mut(|transient_storage| {
1678 if success {
1679 transient_storage.commit_transaction();
1680 } else {
1681 transient_storage.rollback_transaction();
1682 }
1683 });
1684 if is_first_frame {
1687 let m = self.access_list.metrics();
1688 log::trace!(
1689 target: LOG_TARGET,
1690 "access list metrics: size={size} cold={cold} hot={hot}",
1691 size = m.size, cold = m.cold, hot = m.hot,
1692 );
1693 } else if success {
1694 self.access_list.commit_frame();
1695 } else {
1696 self.access_list.rollback_frame();
1697 }
1698 debug_assert_eq!(
1699 self.access_list.frame_depth(),
1700 access_list_checkpoints_len,
1701 "this frame closed exactly the checkpoint it opened",
1702 );
1703 log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1704
1705 self.pop_frame(success);
1706 output.map(|output| {
1707 self.top_frame_mut().last_frame_output = output;
1708 })
1709 }
1710
1711 fn pop_frame(&mut self, persist: bool) {
1716 fn bank_pending_changes_and_invalidate<T: Config>(f: &mut Frame<T>) {
1723 let contract = f.account_id.clone();
1724 f.contract_info.load(&f.account_id);
1725 if let Some(info) = f.contract_info.as_contract() {
1726 f.frame_meter.bank_pending_storage_changes(contract, info);
1727 }
1728 f.contract_info.invalidate();
1735 }
1736
1737 let frame = self.frames.pop();
1741
1742 if let Some(mut frame) = frame {
1745 let account_id = &frame.account_id;
1746 let prev = top_frame_mut!(self);
1747
1748 if !persist {
1750 prev.frame_meter.absorb_weight_meter_only(frame.frame_meter);
1751 return;
1752 }
1753
1754 frame.contract_info.load(account_id);
1759 let mut contract = frame.contract_info.into_contract();
1760 prev.frame_meter
1761 .absorb_all_meters(frame.frame_meter, account_id, contract.as_mut());
1762
1763 prev.contracts_created.extend(frame.contracts_created);
1765 for (account, args) in frame.contracts_to_be_destroyed {
1766 prev.schedule_termination(account, args);
1767 }
1768
1769 if let Some(contract) = contract {
1770 AccountInfo::<T>::insert_contract(
1775 &T::AddressMapper::to_address(account_id),
1776 contract,
1777 );
1778 if let Some(f) = self.frames_mut().find(|f| f.account_id == *account_id) {
1779 bank_pending_changes_and_invalidate(f);
1781 }
1782 }
1783 } else {
1784 if !persist {
1785 self.transaction_meter
1786 .absorb_weight_meter_only(mem::take(&mut self.first_frame.frame_meter));
1787 return;
1788 }
1789
1790 let mut contract = self.first_frame.contract_info.as_contract();
1791 self.transaction_meter.absorb_all_meters(
1792 mem::take(&mut self.first_frame.frame_meter),
1793 &self.first_frame.account_id,
1794 contract.as_deref_mut(),
1795 );
1796
1797 if let Some(contract) = contract {
1798 AccountInfo::<T>::insert_contract(
1799 &T::AddressMapper::to_address(&self.first_frame.account_id),
1800 contract.clone(),
1801 );
1802 }
1803 let contracts_created = mem::take(&mut self.first_frame.contracts_created);
1805 let contracts_to_destroy = mem::take(&mut self.first_frame.contracts_to_be_destroyed);
1806 for (contract_account, args) in contracts_to_destroy {
1807 if args.only_if_same_tx && !contracts_created.contains(&contract_account) {
1808 continue;
1809 }
1810 Self::do_terminate(
1811 &mut self.transaction_meter,
1812 self.exec_config,
1813 &contract_account,
1814 &self.origin,
1815 &args,
1816 );
1817 }
1818 }
1819 }
1820
1821 fn transfer<S: State>(
1834 origin: &Origin<T>,
1835 from: &T::AccountId,
1836 to: &T::AccountId,
1837 value: U256,
1838 preservation: Preservation,
1839 meter: &mut ResourceMeter<T, S>,
1840 exec_config: &ExecConfig<T>,
1841 ) -> DispatchResult {
1842 let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1843 .map_err(|_| Error::<T>::BalanceConversionFailed)?;
1844 if value.is_zero() {
1845 return Ok(());
1846 }
1847
1848 if <System<T>>::account_exists(to) {
1849 return transfer_with_dust::<T>(from, to, value, preservation);
1850 }
1851
1852 let origin = origin.account_id()?;
1853 let ed = <T as Config>::Currency::minimum_balance();
1854 let is_eth_tx = exec_config.collect_deposit_from_hold.is_some();
1855 with_transaction(|| -> TransactionOutcome<DispatchResult> {
1856 match Ok::<(), DispatchError>(())
1859 .and_then(|_| {
1860 if is_eth_tx {
1861 let credit = T::FeeInfo::withdraw_txfee(ed)
1862 .ok_or(Error::<T>::StorageDepositNotEnoughFunds)?;
1863 T::Currency::resolve(to, credit)
1864 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
1865 Ok(())
1866 } else {
1867 T::Currency::transfer(origin, to, ed, Preservation::Preserve)
1868 .map(|_| ())
1869 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds.into())
1870 }
1871 })
1872 .and_then(|_| transfer_with_dust::<T>(from, to, value, preservation))
1873 .and_then(|_| meter.charge_deposit(&StorageDeposit::Charge(ed)))
1874 {
1875 Ok(_) => TransactionOutcome::Commit(Ok(())),
1876 Err(err) => TransactionOutcome::Rollback(Err(err)),
1877 }
1878 })
1879 }
1880
1881 fn transfer_from_origin<S: State>(
1883 origin: &Origin<T>,
1884 from: &Origin<T>,
1885 to: &T::AccountId,
1886 value: U256,
1887 meter: &mut ResourceMeter<T, S>,
1888 exec_config: &ExecConfig<T>,
1889 ) -> ExecResult {
1890 let from = match from {
1893 Origin::Signed(caller) => caller,
1894 Origin::Root if value.is_zero() => return Ok(Default::default()),
1895 Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1896 };
1897 Self::transfer(origin, from, to, value, Preservation::Preserve, meter, exec_config)
1898 .map(|_| Default::default())
1899 .map_err(Into::into)
1900 }
1901
1902 fn do_terminate(
1908 transaction_meter: &mut TransactionMeter<T>,
1909 exec_config: &ExecConfig<T>,
1910 contract_account: &T::AccountId,
1911 origin: &Origin<T>,
1912 args: &TerminateArgs<T>,
1913 ) {
1914 let contract_address = T::AddressMapper::to_address(contract_account);
1915 let account_info = AccountInfoOf::<T>::get(contract_address).unwrap_or_default();
1917
1918 let refund = Self::best_effort(&contract_address, "refund the storage deposit", || {
1922 Self::refund_on_terminate(exec_config, contract_account, origin)
1923 })
1924 .unwrap_or_default();
1925
1926 System::<T>::dec_consumers(contract_account);
1928
1929 let origin = Self::termination_origin(origin);
1939 let balance = <Contracts<T>>::convert_native_to_evm(
1940 account_info.balance(contract_account, Preservation::Preserve),
1941 );
1942 Self::best_effort(&contract_address, "send the remaining balance", || {
1943 Self::transfer(
1944 &origin,
1945 contract_account,
1946 &args.beneficiary,
1947 balance,
1948 Preservation::Preserve,
1949 transaction_meter,
1950 exec_config,
1951 )
1952 });
1953
1954 let dust = AccountInfoOf::<T>::get(contract_address)
1956 .map(|info| info.dust)
1957 .unwrap_or_default();
1958
1959 if dust == 0 &&
1969 T::Currency::total_balance(contract_account) == T::Currency::minimum_balance()
1970 {
1971 Self::best_effort(&contract_address, "burn the existential deposit", || {
1972 T::Deposit::destroy_contract(contract_account)
1973 });
1974 }
1975
1976 if let Some(info) = account_info.account_type.contract_info() {
1977 Self::best_effort(&contract_address, "release the code", || {
1979 CodeInfo::<T>::decrement_refcount(info.code_hash)
1980 });
1981 ContractInfo::<T>::queue_for_deletion(info.trie_id, contract_account.clone());
1982 } else {
1983 defensive!("Terminated contract has no contract info", contract_address);
1984 }
1985 AccountInfoOf::<T>::set(
1987 contract_address,
1988 (dust != 0).then(|| AccountInfo { account_type: AccountType::EOA, dust }),
1989 );
1990 ImmutableDataOf::<T>::remove(contract_address);
1991
1992 transaction_meter.terminate(contract_account.clone(), args.refunded.saturating_add(refund));
1994
1995 log::trace!(target: LOG_TARGET, "Terminated {contract_address:?}");
1996 }
1997
1998 fn termination_origin(origin: &Origin<T>) -> Origin<T> {
2003 match origin {
2004 Origin::Signed(o) => Origin::Signed(o.clone()),
2005 Origin::Root => Origin::from_account_id(crate::Pallet::<T>::account_id()),
2006 }
2007 }
2008
2009 fn refund_on_terminate(
2014 exec_config: &ExecConfig<T>,
2015 contract_account: &T::AccountId,
2016 origin: &Origin<T>,
2017 ) -> Result<BalanceOf<T>, DispatchError> {
2018 let origin = Self::termination_origin(origin);
2019 T::Deposit::refund_all(contract_account, exec_config.funds(origin.account_id()?))
2020 }
2021
2022 fn best_effort<R>(
2027 contract_address: &H160,
2028 step: &str,
2029 f: impl FnOnce() -> Result<R, DispatchError>,
2030 ) -> Option<R> {
2031 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
2032 match f() {
2033 Ok(value) => TransactionOutcome::Commit(Ok(Some(value))),
2034 Err(e) => {
2035 log::debug!(
2036 target: LOG_TARGET,
2037 "Terminating {contract_address:?}: failed to {step}: {e:?}",
2038 );
2039 TransactionOutcome::Rollback(Ok(None))
2040 },
2041 }
2042 })
2043 .ok()
2044 .flatten()
2045 }
2046
2047 fn top_frame(&self) -> &Frame<T> {
2049 top_frame!(self)
2050 }
2051
2052 fn top_frame_mut(&mut self) -> &mut Frame<T> {
2054 top_frame_mut!(self)
2055 }
2056
2057 fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
2061 core::iter::once(&self.first_frame).chain(&self.frames).rev()
2062 }
2063
2064 fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
2066 core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
2067 }
2068
2069 fn caller_at(&self, depth: usize) -> Origin<T> {
2075 let Some(frame) = self.frames().nth(depth) else { return self.origin.clone() };
2076 if let Some(DelegateInfo { caller, .. }) = &frame.delegate {
2077 caller.clone()
2078 } else {
2079 self.frames()
2080 .nth(depth + 1)
2081 .map(|f| Origin::from_account_id(f.account_id.clone()))
2082 .unwrap_or(self.origin.clone())
2083 }
2084 }
2085
2086 fn allows_reentry(&self, id: &T::AccountId) -> bool {
2088 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
2089 }
2090
2091 fn account_balance(&self, who: &T::AccountId) -> U256 {
2093 let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
2094 crate::Pallet::<T>::convert_native_to_evm(balance)
2095 }
2096
2097 #[cfg(feature = "runtime-benchmarks")]
2100 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
2101 self.top_frame_mut().entry_point = export;
2102 }
2103
2104 #[cfg(feature = "runtime-benchmarks")]
2105 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
2106 self.block_number = block_number;
2107 }
2108
2109 fn block_hash(&self, block_number: U256) -> Option<H256> {
2110 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
2111 return None;
2112 };
2113 if block_number >= self.block_number {
2114 return None;
2115 }
2116 if block_number < self.block_number.saturating_sub(256u32.into()) {
2117 return None;
2118 }
2119
2120 match crate::Pallet::<T>::eth_block_hash_from_number(block_number.into()) {
2124 Some(hash) => Some(hash),
2125 None => {
2126 use codec::Decode;
2127 let block_hash = System::<T>::block_hash(&block_number);
2128 Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
2129 },
2130 }
2131 }
2132
2133 fn has_contract_info(&self) -> bool {
2136 let address = self.address();
2137 let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
2138 if let Some(precompile) = precompile {
2139 return precompile.has_contract_info();
2140 }
2141 true
2142 }
2143
2144 fn with_transient_storage_mut<R, F: FnOnce(&mut TransientStorage<T>) -> R>(
2145 &mut self,
2146 f: F,
2147 ) -> R {
2148 if let Some(transient) = &self.exec_config.test_env_transient_storage {
2149 f(&mut transient.borrow_mut())
2150 } else {
2151 f(&mut self.transient_storage)
2152 }
2153 }
2154 fn with_transient_storage<R, F: FnOnce(&TransientStorage<T>) -> R>(&self, f: F) -> R {
2155 if let Some(transient) = &self.exec_config.test_env_transient_storage {
2156 f(&transient.borrow())
2157 } else {
2158 f(&self.transient_storage)
2159 }
2160 }
2161
2162 fn code_source(&self, address: &H160) -> Option<CodeSource<'_>> {
2168 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2169 self.exec_config
2170 .mock_handler
2171 .as_ref()
2172 .and_then(|handler| handler.mocked_code(*address))
2173 }) {
2174 return Some(CodeSource::Virtual(code));
2175 }
2176
2177 let (contract, target) = <AccountInfo<T>>::load_contract_with_delegation(address);
2178
2179 if let Some(target) = target {
2186 return Some(CodeSource::Indicator(<AccountInfo<T>>::delegation_indicator(&target)));
2187 }
2188
2189 contract.map(|contract| CodeSource::Contract(contract.code_hash))
2190 }
2191}
2192
2193enum CodeSource<'a> {
2195 Virtual(&'a [u8]),
2197 Indicator([u8; 23]),
2199 Contract(H256),
2201}
2202
2203impl<'a, T, E> Ext for Stack<'a, T, E>
2204where
2205 T: Config,
2206 E: Executable<T>,
2207{
2208 fn delegate_call(
2209 &mut self,
2210 call_resources: &CallResources<T>,
2211 address: H160,
2212 input_data: Vec<u8>,
2213 ) -> Result<(), ExecError> {
2214 *self.last_frame_output_mut() = Default::default();
2217
2218 let top_frame = self.top_frame_mut();
2219 let mut contract_info = top_frame.contract_info().clone();
2223 top_frame.frame_meter.apply_pending_storage_changes(&mut contract_info);
2224 let account_id = top_frame.account_id.clone();
2225 let value = top_frame.value_transferred;
2226 if let Some(executable) = self.push_frame(
2227 FrameArgs::Call {
2228 dest: account_id,
2229 cached_info: Some(contract_info),
2230 delegated_call: Some(DelegateInfo {
2231 caller: self.caller().clone(),
2232 callee: address,
2233 }),
2234 },
2235 value,
2236 call_resources,
2237 self.is_read_only(),
2238 &input_data,
2239 )? {
2240 self.run(executable, input_data)
2241 } else {
2242 Ok(())
2244 }
2245 }
2246
2247 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
2248 if_tracing(|tracer| {
2249 let addr = T::AddressMapper::to_address(self.account_id());
2250 tracer.terminate(
2251 addr,
2252 *beneficiary,
2253 self.top_frame()
2254 .frame_meter
2255 .eth_gas_left()
2256 .unwrap_or_default()
2257 .try_into()
2258 .unwrap_or_default(),
2259 crate::Pallet::<T>::evm_balance(&addr),
2260 );
2261 });
2262 let frame = top_frame_mut!(self);
2263 let contract_address = T::AddressMapper::to_address(&frame.account_id);
2264 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2265
2266 Self::transfer(
2268 &self.origin,
2269 &frame.account_id,
2270 &beneficiary,
2271 <Contracts<T>>::evm_balance(&contract_address),
2272 Preservation::Preserve,
2273 &mut frame.frame_meter,
2274 self.exec_config,
2275 )?;
2276
2277 let account_id = frame.account_id.clone();
2279 self.top_frame_mut().schedule_termination(
2280 account_id,
2281 TerminateArgs { beneficiary, only_if_same_tx: true, refunded: Zero::zero() },
2282 );
2283 Ok(CodeRemoved::Yes)
2284 }
2285
2286 fn own_code_hash(&mut self) -> &H256 {
2287 &self.top_frame_mut().contract_info().code_hash
2288 }
2289
2290 fn immutable_data_len(&mut self) -> u32 {
2291 let frame = self.top_frame_mut();
2292 if frame.code_address == T::AddressMapper::to_address(&frame.account_id) {
2293 frame.contract_info().immutable_data_len()
2294 } else {
2295 limits::IMMUTABLE_BYTES
2296 }
2297 }
2298
2299 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
2300 if self.top_frame().entry_point == ExportedFunction::Constructor {
2301 return Err(Error::<T>::InvalidImmutableAccess.into());
2302 }
2303
2304 let address = self.top_frame().code_address;
2307 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
2308 }
2309
2310 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
2311 let frame = self.top_frame_mut();
2312 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
2313 return Err(Error::<T>::InvalidImmutableAccess.into());
2314 }
2315 frame.contract_info().set_immutable_data_len(data.len() as u32);
2316 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
2317 Ok(())
2318 }
2319}
2320
2321impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
2322where
2323 T: Config,
2324 E: Executable<T>,
2325{
2326 fn instantiate(
2327 &mut self,
2328 call_resources: &CallResources<T>,
2329 mut code: Code,
2330 value: U256,
2331 input_data: Vec<u8>,
2332 salt: Option<&[u8; 32]>,
2333 ) -> Result<H160, ExecError> {
2334 *self.last_frame_output_mut() = Default::default();
2337
2338 let sender = self.top_frame().account_id.clone();
2339 let executable = {
2340 let executable = match &mut code {
2341 Code::Upload(initcode) => {
2342 if !T::AllowEVMBytecode::get() {
2343 return Err(<Error<T>>::CodeRejected.into());
2344 }
2345 ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
2346 let initcode = crate::tracing::if_tracing(|_| initcode.clone())
2347 .unwrap_or_else(|| mem::take(initcode));
2348 E::from_evm_init_code(initcode, sender.clone())?
2349 },
2350 Code::Existing(hash) => {
2351 let executable = E::from_storage(*hash, self.frame_meter_mut())?;
2352 ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
2353 executable
2354 },
2355 };
2356 self.push_frame(
2357 FrameArgs::Instantiate {
2358 sender,
2359 executable,
2360 salt,
2361 input_data: input_data.as_ref(),
2362 },
2363 value,
2364 call_resources,
2365 self.is_read_only(),
2366 &input_data,
2367 )?
2368 };
2369 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
2370
2371 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
2372 if_tracing(|t| t.instantiate_code(&code, salt));
2373 self.run(executable, input_data).map(|_| address)
2374 }
2375}
2376
2377impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
2378where
2379 T: Config,
2380 E: Executable<T>,
2381{
2382 type T = T;
2383
2384 fn call(
2385 &mut self,
2386 call_resources: &CallResources<T>,
2387 dest_addr: &H160,
2388 value: U256,
2389 input_data: Vec<u8>,
2390 allows_reentry: ReentrancyProtection,
2391 read_only: bool,
2392 ) -> Result<(), ExecError> {
2393 *self.last_frame_output_mut() = Default::default();
2396
2397 if allows_reentry == ReentrancyProtection::Strict {
2402 self.top_frame_mut().allows_reentry = false;
2403 }
2404
2405 let try_call = || {
2406 let is_read_only = read_only || self.is_read_only();
2408
2409 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2411 T::AddressMapper::to_fallback_account_id(dest_addr)
2412 } else {
2413 T::AddressMapper::to_account_id(dest_addr)
2414 };
2415
2416 if !self.allows_reentry(&dest) {
2417 return Err(<Error<T>>::ReentranceDenied.into());
2418 }
2419
2420 if allows_reentry == ReentrancyProtection::AllowNext {
2421 self.top_frame_mut().allows_reentry = false;
2422 }
2423
2424 let cached_info = self
2432 .frames()
2433 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2434 .and_then(|f| match &f.contract_info {
2435 CachedContract::Cached(contract) => {
2436 let mut contract_with_pending = contract.clone();
2437 f.frame_meter.apply_pending_storage_changes(&mut contract_with_pending);
2438 Some(contract_with_pending)
2439 },
2440 _ => None,
2441 });
2442
2443 if let Some(executable) = self.push_frame(
2444 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2445 value,
2446 call_resources,
2447 is_read_only,
2448 &input_data,
2449 )? {
2450 self.run(executable, input_data)
2451 } else {
2452 if_tracing(|t| {
2453 t.enter_child_span(
2454 T::AddressMapper::to_address(self.account_id()),
2455 T::AddressMapper::to_address(&dest),
2456 None,
2457 false,
2458 is_read_only,
2459 value,
2460 &input_data,
2461 Default::default(),
2462 );
2463 });
2464
2465 let snapshot = if_tracing(|_| top_frame!(self).frame_meter.snapshot());
2466
2467 let result = if let Some(mock_answer) =
2468 self.exec_config.mock_handler.as_ref().and_then(|handler| {
2469 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2470 }) {
2471 *self.last_frame_output_mut() = mock_answer.clone();
2472 Ok(mock_answer)
2473 } else if is_read_only && value.is_zero() {
2474 Ok(Default::default())
2475 } else if is_read_only {
2476 Err(Error::<T>::StateChangeDenied.into())
2477 } else {
2478 let account_id = self.account_id().clone();
2479 let frame = top_frame_mut!(self);
2480 Self::transfer_from_origin(
2481 &self.origin,
2482 &Origin::from_account_id(account_id),
2483 &dest,
2484 value,
2485 &mut frame.frame_meter,
2486 self.exec_config,
2487 )
2488 };
2489
2490 if_tracing(|t| {
2491 let snapshot = snapshot.as_ref().expect(
2492 "snapshot is taken inside if_tracing above; tracing state cannot \
2493 change mid-call, so it is Some whenever this closure runs; qed",
2494 );
2495 let (gas_used, weight_delta) =
2496 top_frame!(self).frame_meter.delta_since(snapshot);
2497 match result {
2498 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_delta),
2499 Err(e) => {
2500 t.exit_child_span_with_error(e.error.into(), gas_used, weight_delta)
2501 },
2502 }
2503 });
2504
2505 result.map(|_| ())
2506 }
2507 };
2508
2509 let result = try_call();
2511
2512 self.top_frame_mut().allows_reentry = true;
2514
2515 result
2516 }
2517
2518 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2519 self.with_transient_storage(|transient_storage| {
2520 transient_storage.read(self.account_id(), key)
2521 })
2522 }
2523
2524 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2525 self.with_transient_storage(|transient_storage| {
2526 transient_storage.read(self.account_id(), key).map(|value| value.len() as _)
2527 })
2528 }
2529
2530 fn set_transient_storage(
2531 &mut self,
2532 key: &Key,
2533 value: Option<Vec<u8>>,
2534 take_old: bool,
2535 ) -> Result<WriteOutcome, DispatchError> {
2536 let account_id = self.account_id().clone();
2537 self.with_transient_storage_mut(|transient_storage| {
2538 transient_storage.write(&account_id, key, value, take_old)
2539 })
2540 }
2541
2542 fn account_id(&self) -> &T::AccountId {
2543 &self.top_frame().account_id
2544 }
2545
2546 fn caller(&self) -> Origin<T> {
2547 if let Some(Ok(mock_caller)) = self
2548 .exec_config
2549 .mock_handler
2550 .as_ref()
2551 .and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2552 .map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2553 {
2554 return mock_caller;
2555 }
2556
2557 self.caller_at(0)
2558 }
2559
2560 fn caller_of_caller(&self) -> Origin<T> {
2561 self.caller_at(1)
2562 }
2563
2564 fn origin(&self) -> &Origin<T> {
2565 if let Some(mock_origin) = self
2566 .exec_config
2567 .mock_handler
2568 .as_ref()
2569 .and_then(|mock_handler| mock_handler.mock_origin())
2570 {
2571 return mock_origin;
2572 }
2573
2574 &self.origin
2575 }
2576
2577 fn to_account_id(&self, address: &H160) -> T::AccountId {
2578 T::AddressMapper::to_account_id(address)
2579 }
2580
2581 fn code_hash(&self, address: &H160) -> H256 {
2582 match self.code_source(address) {
2583 Some(CodeSource::Virtual(code)) => sp_io::hashing::keccak_256(code).into(),
2584 Some(CodeSource::Indicator(indicator)) => sp_io::hashing::keccak_256(&indicator).into(),
2585 Some(CodeSource::Contract(code_hash)) => code_hash,
2586 None if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) => {
2587 EMPTY_CODE_HASH
2588 },
2589 None => H256::zero(),
2590 }
2591 }
2592
2593 fn code_size(&self, address: &H160) -> u64 {
2594 match self.code_source(address) {
2595 Some(CodeSource::Virtual(code)) => code.len() as u64,
2596 Some(CodeSource::Indicator(indicator)) => indicator.len() as u64,
2597 Some(CodeSource::Contract(code_hash)) => {
2598 CodeInfoOf::<T>::get(code_hash).map(|info| info.code_len()).unwrap_or_default()
2599 },
2600 None => 0,
2601 }
2602 }
2603
2604 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2605 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2606 self.origin == caller
2607 }
2608
2609 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2610 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2612 }
2613
2614 fn origin_is_root(&self) -> bool {
2615 self.origin == Origin::Root
2616 }
2617
2618 fn balance(&self) -> U256 {
2619 self.account_balance(&self.top_frame().account_id)
2620 }
2621
2622 fn balance_of(&self, address: &H160) -> U256 {
2623 let balance =
2624 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2625 if_tracing(|tracer| {
2626 tracer.balance_read(address, balance);
2627 });
2628 balance
2629 }
2630
2631 fn value_transferred(&self) -> U256 {
2632 self.top_frame().value_transferred.into()
2633 }
2634
2635 fn now(&self) -> U256 {
2636 (self.timestamp / 1000u32.into()).into()
2637 }
2638
2639 fn minimum_balance(&self) -> U256 {
2640 let min = T::Currency::minimum_balance();
2641 crate::Pallet::<T>::convert_native_to_evm(min)
2642 }
2643
2644 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2645 let contract = T::AddressMapper::to_address(self.account_id());
2646 if_tracing(|tracer| {
2647 let log_index = frame_system::Pallet::<Self::T>::event_count();
2648 tracer.log_event(contract, &topics, &data, log_index);
2649 });
2650
2651 block_storage::capture_frame_log::<T>(&contract, &data, &topics);
2652
2653 Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2654 }
2655
2656 fn block_number(&self) -> U256 {
2657 self.block_number.into()
2658 }
2659
2660 fn block_hash(&self, block_number: U256) -> Option<H256> {
2661 self.block_hash(block_number)
2662 }
2663
2664 fn block_author(&self) -> H160 {
2665 Contracts::<Self::T>::block_author()
2666 }
2667
2668 fn gas_limit(&self) -> u64 {
2669 <Contracts<T>>::evm_block_gas_limit().saturated_into()
2670 }
2671
2672 fn chain_id(&self) -> u64 {
2673 <T as Config>::ChainId::get()
2674 }
2675
2676 fn gas_meter(&self) -> &FrameMeter<Self::T> {
2677 &self.top_frame().frame_meter
2678 }
2679
2680 #[inline]
2681 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2682 &mut self.top_frame_mut().frame_meter
2683 }
2684
2685 fn frame_meter(&self) -> &FrameMeter<Self::T> {
2686 &self.top_frame().frame_meter
2687 }
2688
2689 #[inline]
2690 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2691 &mut self.top_frame_mut().frame_meter
2692 }
2693
2694 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2695 secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2696 }
2697
2698 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2699 sp_io::crypto::sr25519_verify(
2700 &SR25519Signature::from(*signature),
2701 message,
2702 &SR25519Public::from(*pub_key),
2703 )
2704 }
2705
2706 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError> {
2707 Ok(ECDSAPublic::from(*pk)
2708 .to_eth_address()
2709 .or_else(|()| Err(Error::<T>::EcdsaRecoveryFailed))?)
2710 }
2711
2712 #[cfg(any(test, feature = "runtime-benchmarks"))]
2713 fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2714 self.top_frame_mut().contract_info()
2715 }
2716
2717 #[cfg(any(feature = "runtime-benchmarks", test))]
2718 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2719 &mut self.transient_storage
2720 }
2721
2722 fn is_read_only(&self) -> bool {
2723 self.top_frame().read_only
2724 }
2725
2726 fn is_delegate_call(&self) -> bool {
2727 self.top_frame().delegate.is_some()
2728 }
2729
2730 fn last_frame_output(&self) -> &ExecReturnValue {
2731 &self.top_frame().last_frame_output
2732 }
2733
2734 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2735 &mut self.top_frame_mut().last_frame_output
2736 }
2737
2738 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2739 fn copy_padded(buf: &mut [u8], code: &[u8], code_offset: usize) {
2740 let code = code.get(code_offset..).unwrap_or_default();
2741 let len = buf.len().min(code.len());
2742 buf[..len].copy_from_slice(&code[..len]);
2743 buf[len..].fill(0);
2744 }
2745
2746 if buf.is_empty() {
2747 return;
2748 }
2749
2750 match self.code_source(address) {
2751 Some(CodeSource::Virtual(code)) => copy_padded(buf, code, code_offset),
2752 Some(CodeSource::Indicator(indicator)) => copy_padded(buf, &indicator, code_offset),
2753 Some(CodeSource::Contract(code_hash)) => copy_padded(
2754 buf,
2755 &crate::PristineCode::<T>::get(&code_hash).unwrap_or_default(),
2756 code_offset,
2757 ),
2758 None => buf.fill(0),
2759 }
2760 }
2761
2762 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2763 ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2764 let parent = self.frames_mut().nth(1).ok_or_else(|| Error::<T>::ContractNotFound)?;
2765 ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2766 ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2767
2768 let contract_address = T::AddressMapper::to_address(&parent.account_id);
2769
2770 ensure!(
2772 !AccountInfo::<T>::is_delegated(&contract_address),
2773 Error::<T>::CannotTerminateDelegatedAccount,
2774 );
2775
2776 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2777
2778 let parent_account_id = parent.account_id.clone();
2779
2780 let refunded =
2784 Self::refund_on_terminate(&self.exec_config, &parent_account_id, &self.origin)?;
2785
2786 Self::transfer(
2788 &self.origin,
2789 &parent_account_id,
2790 &beneficiary,
2791 <Contracts<T>>::evm_balance(&contract_address),
2792 Preservation::Preserve,
2793 &mut top_frame_mut!(self).frame_meter,
2794 &self.exec_config,
2795 )?;
2796
2797 let args = TerminateArgs { beneficiary, only_if_same_tx: false, refunded };
2799 self.top_frame_mut().schedule_termination(parent_account_id, args);
2800
2801 Ok(())
2802 }
2803
2804 fn effective_gas_price(&self) -> U256 {
2805 self.exec_config
2806 .effective_gas_price
2807 .unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2808 }
2809
2810 fn gas_left(&self) -> u64 {
2811 let frame = self.top_frame();
2812
2813 frame.frame_meter.eth_gas_left().unwrap_or_default().saturated_into::<u64>()
2814 }
2815
2816 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2817 assert!(self.has_contract_info());
2818 self.top_frame_mut().contract_info().read(key)
2819 }
2820
2821 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2822 assert!(self.has_contract_info());
2823 self.top_frame_mut().contract_info().size(key.into())
2824 }
2825
2826 fn set_storage(
2827 &mut self,
2828 key: &Key,
2829 value: Option<Vec<u8>>,
2830 take_old: bool,
2831 ) -> Result<WriteOutcome, DispatchError> {
2832 assert!(self.has_contract_info());
2833 let frame = self.top_frame_mut();
2834 frame.contract_info.get(&frame.account_id).write(
2835 key.into(),
2836 value,
2837 Some(&mut frame.frame_meter),
2838 take_old,
2839 )
2840 }
2841
2842 fn touch_storage_access(&mut self, key: &Key, op: StorageOp) -> Warmth {
2843 let address = self.address();
2844 self.access_list.touch(AccessEntry { address, slot: key.into() }, op)
2845 }
2846
2847 fn peek_storage_access(&self, key: &Key) -> Warmth {
2848 let address = self.address();
2849 self.access_list.peek(&AccessEntry { address, slot: key.into() })
2850 }
2851
2852 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult {
2853 assert!(self.has_contract_info());
2854 self.top_frame_mut().frame_meter.record_contract_storage_changes(diff)
2855 }
2856}
2857
2858pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2860 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2861}
2862
2863#[cfg(feature = "runtime-benchmarks")]
2867pub fn bench_do_terminate<T: Config>(
2868 transaction_meter: &mut TransactionMeter<T>,
2869 exec_config: &ExecConfig<T>,
2870 contract_account: &T::AccountId,
2871 origin: &Origin<T>,
2872 beneficiary: T::AccountId,
2873 only_if_same_tx: bool,
2874) -> Result<(), DispatchError> {
2875 type BenchStack<'a, T> = Stack<'a, T, crate::ContractBlob<T>>;
2876 let refunded = if only_if_same_tx {
2877 Zero::zero()
2878 } else {
2879 BenchStack::<T>::refund_on_terminate(exec_config, contract_account, origin)?
2880 };
2881 BenchStack::<T>::do_terminate(
2882 transaction_meter,
2883 exec_config,
2884 contract_account,
2885 origin,
2886 &TerminateArgs { beneficiary, only_if_same_tx, refunded },
2887 );
2888 Ok(())
2889}
2890
2891mod sealing {
2892 use super::*;
2893
2894 pub trait Sealed {}
2895 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2896
2897 #[cfg(test)]
2898 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2899}