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 allows_reentry(&self, id: &T::AccountId) -> bool {
1973 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1974 }
1975
1976 fn account_balance(&self, who: &T::AccountId) -> U256 {
1978 let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
1979 crate::Pallet::<T>::convert_native_to_evm(balance)
1980 }
1981
1982 #[cfg(feature = "runtime-benchmarks")]
1985 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
1986 self.top_frame_mut().entry_point = export;
1987 }
1988
1989 #[cfg(feature = "runtime-benchmarks")]
1990 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
1991 self.block_number = block_number;
1992 }
1993
1994 fn block_hash(&self, block_number: U256) -> Option<H256> {
1995 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
1996 return None;
1997 };
1998 if block_number >= self.block_number {
1999 return None;
2000 }
2001 if block_number < self.block_number.saturating_sub(256u32.into()) {
2002 return None;
2003 }
2004
2005 match crate::Pallet::<T>::eth_block_hash_from_number(block_number.into()) {
2009 Some(hash) => Some(hash),
2010 None => {
2011 use codec::Decode;
2012 let block_hash = System::<T>::block_hash(&block_number);
2013 Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
2014 },
2015 }
2016 }
2017
2018 fn has_contract_info(&self) -> bool {
2021 let address = self.address();
2022 let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
2023 if let Some(precompile) = precompile {
2024 return precompile.has_contract_info();
2025 }
2026 true
2027 }
2028
2029 fn with_transient_storage_mut<R, F: FnOnce(&mut TransientStorage<T>) -> R>(
2030 &mut self,
2031 f: F,
2032 ) -> R {
2033 if let Some(transient) = &self.exec_config.test_env_transient_storage {
2034 f(&mut transient.borrow_mut())
2035 } else {
2036 f(&mut self.transient_storage)
2037 }
2038 }
2039 fn with_transient_storage<R, F: FnOnce(&TransientStorage<T>) -> R>(&self, f: F) -> R {
2040 if let Some(transient) = &self.exec_config.test_env_transient_storage {
2041 f(&transient.borrow())
2042 } else {
2043 f(&self.transient_storage)
2044 }
2045 }
2046}
2047
2048impl<'a, T, E> Ext for Stack<'a, T, E>
2049where
2050 T: Config,
2051 E: Executable<T>,
2052{
2053 fn delegate_call(
2054 &mut self,
2055 call_resources: &CallResources<T>,
2056 address: H160,
2057 input_data: Vec<u8>,
2058 ) -> Result<(), ExecError> {
2059 *self.last_frame_output_mut() = Default::default();
2062
2063 let top_frame = self.top_frame_mut();
2064 let mut contract_info = top_frame.contract_info().clone();
2068 top_frame.frame_meter.apply_pending_storage_changes(&mut contract_info);
2069 let account_id = top_frame.account_id.clone();
2070 let value = top_frame.value_transferred;
2071 if let Some(executable) = self.push_frame(
2072 FrameArgs::Call {
2073 dest: account_id,
2074 cached_info: Some(contract_info),
2075 delegated_call: Some(DelegateInfo {
2076 caller: self.caller().clone(),
2077 callee: address,
2078 }),
2079 },
2080 value,
2081 call_resources,
2082 self.is_read_only(),
2083 &input_data,
2084 )? {
2085 self.run(executable, input_data)
2086 } else {
2087 Ok(())
2089 }
2090 }
2091
2092 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
2093 if_tracing(|tracer| {
2094 let addr = T::AddressMapper::to_address(self.account_id());
2095 tracer.terminate(
2096 addr,
2097 *beneficiary,
2098 self.top_frame()
2099 .frame_meter
2100 .eth_gas_left()
2101 .unwrap_or_default()
2102 .try_into()
2103 .unwrap_or_default(),
2104 crate::Pallet::<T>::evm_balance(&addr),
2105 );
2106 });
2107 let frame = top_frame_mut!(self);
2108 let info = frame.contract_info();
2109 let trie_id = info.trie_id.clone();
2110 let code_hash = info.code_hash;
2111 let contract_address = T::AddressMapper::to_address(&frame.account_id);
2112 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2113
2114 Self::transfer(
2116 &self.origin,
2117 &frame.account_id,
2118 &beneficiary,
2119 <Contracts<T>>::evm_balance(&contract_address),
2120 Preservation::Preserve,
2121 &mut frame.frame_meter,
2122 self.exec_config,
2123 )?;
2124
2125 let account_id = frame.account_id.clone();
2127 self.top_frame_mut().contracts_to_be_destroyed.insert(
2128 account_id,
2129 TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: true },
2130 );
2131 Ok(CodeRemoved::Yes)
2132 }
2133
2134 fn own_code_hash(&mut self) -> &H256 {
2135 &self.top_frame_mut().contract_info().code_hash
2136 }
2137
2138 fn immutable_data_len(&mut self) -> u32 {
2139 let frame = self.top_frame_mut();
2140 if frame.code_address == T::AddressMapper::to_address(&frame.account_id) {
2141 frame.contract_info().immutable_data_len()
2142 } else {
2143 limits::IMMUTABLE_BYTES
2144 }
2145 }
2146
2147 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
2148 if self.top_frame().entry_point == ExportedFunction::Constructor {
2149 return Err(Error::<T>::InvalidImmutableAccess.into());
2150 }
2151
2152 let address = self.top_frame().code_address;
2155 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
2156 }
2157
2158 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
2159 let frame = self.top_frame_mut();
2160 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
2161 return Err(Error::<T>::InvalidImmutableAccess.into());
2162 }
2163 frame.contract_info().set_immutable_data_len(data.len() as u32);
2164 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
2165 Ok(())
2166 }
2167}
2168
2169impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
2170where
2171 T: Config,
2172 E: Executable<T>,
2173{
2174 fn instantiate(
2175 &mut self,
2176 call_resources: &CallResources<T>,
2177 mut code: Code,
2178 value: U256,
2179 input_data: Vec<u8>,
2180 salt: Option<&[u8; 32]>,
2181 ) -> Result<H160, ExecError> {
2182 *self.last_frame_output_mut() = Default::default();
2185
2186 let sender = self.top_frame().account_id.clone();
2187 let executable = {
2188 let executable = match &mut code {
2189 Code::Upload(initcode) => {
2190 if !T::AllowEVMBytecode::get() {
2191 return Err(<Error<T>>::CodeRejected.into());
2192 }
2193 ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
2194 let initcode = crate::tracing::if_tracing(|_| initcode.clone())
2195 .unwrap_or_else(|| mem::take(initcode));
2196 E::from_evm_init_code(initcode, sender.clone())?
2197 },
2198 Code::Existing(hash) => {
2199 let executable = E::from_storage(*hash, self.frame_meter_mut())?;
2200 ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
2201 executable
2202 },
2203 };
2204 self.push_frame(
2205 FrameArgs::Instantiate {
2206 sender,
2207 executable,
2208 salt,
2209 input_data: input_data.as_ref(),
2210 },
2211 value,
2212 call_resources,
2213 self.is_read_only(),
2214 &input_data,
2215 )?
2216 };
2217 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
2218
2219 let account_id = self.top_frame().account_id.clone();
2221 self.top_frame_mut().contracts_created.insert(account_id);
2222
2223 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
2224 if_tracing(|t| t.instantiate_code(&code, salt));
2225 self.run(executable, input_data).map(|_| address)
2226 }
2227}
2228
2229impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
2230where
2231 T: Config,
2232 E: Executable<T>,
2233{
2234 type T = T;
2235
2236 fn call(
2237 &mut self,
2238 call_resources: &CallResources<T>,
2239 dest_addr: &H160,
2240 value: U256,
2241 input_data: Vec<u8>,
2242 allows_reentry: ReentrancyProtection,
2243 read_only: bool,
2244 ) -> Result<(), ExecError> {
2245 *self.last_frame_output_mut() = Default::default();
2248
2249 if allows_reentry == ReentrancyProtection::Strict {
2254 self.top_frame_mut().allows_reentry = false;
2255 }
2256
2257 let try_call = || {
2258 let is_read_only = read_only || self.is_read_only();
2260
2261 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2263 T::AddressMapper::to_fallback_account_id(dest_addr)
2264 } else {
2265 T::AddressMapper::to_account_id(dest_addr)
2266 };
2267
2268 if !self.allows_reentry(&dest) {
2269 return Err(<Error<T>>::ReentranceDenied.into());
2270 }
2271
2272 if allows_reentry == ReentrancyProtection::AllowNext {
2273 self.top_frame_mut().allows_reentry = false;
2274 }
2275
2276 let cached_info = self
2284 .frames()
2285 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2286 .and_then(|f| match &f.contract_info {
2287 CachedContract::Cached(contract) => {
2288 let mut contract_with_pending = contract.clone();
2289 f.frame_meter.apply_pending_storage_changes(&mut contract_with_pending);
2290 Some(contract_with_pending)
2291 },
2292 _ => None,
2293 });
2294
2295 if let Some(executable) = self.push_frame(
2296 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2297 value,
2298 call_resources,
2299 is_read_only,
2300 &input_data,
2301 )? {
2302 self.run(executable, input_data)
2303 } else {
2304 if_tracing(|t| {
2305 t.enter_child_span(
2306 T::AddressMapper::to_address(self.account_id()),
2307 T::AddressMapper::to_address(&dest),
2308 None,
2309 false,
2310 is_read_only,
2311 value,
2312 &input_data,
2313 Default::default(),
2314 );
2315 });
2316
2317 let snapshot = if_tracing(|_| top_frame!(self).frame_meter.snapshot());
2318
2319 let result = if let Some(mock_answer) =
2320 self.exec_config.mock_handler.as_ref().and_then(|handler| {
2321 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2322 }) {
2323 *self.last_frame_output_mut() = mock_answer.clone();
2324 Ok(mock_answer)
2325 } else if is_read_only && value.is_zero() {
2326 Ok(Default::default())
2327 } else if is_read_only {
2328 Err(Error::<T>::StateChangeDenied.into())
2329 } else {
2330 let account_id = self.account_id().clone();
2331 let frame = top_frame_mut!(self);
2332 Self::transfer_from_origin(
2333 &self.origin,
2334 &Origin::from_account_id(account_id),
2335 &dest,
2336 value,
2337 &mut frame.frame_meter,
2338 self.exec_config,
2339 )
2340 };
2341
2342 if_tracing(|t| {
2343 let snapshot = snapshot.as_ref().expect(
2344 "snapshot is taken inside if_tracing above; tracing state cannot \
2345 change mid-call, so it is Some whenever this closure runs; qed",
2346 );
2347 let (gas_used, weight_delta) =
2348 top_frame!(self).frame_meter.delta_since(snapshot);
2349 match result {
2350 Ok(ref output) => t.exit_child_span(&output, gas_used, weight_delta),
2351 Err(e) => {
2352 t.exit_child_span_with_error(e.error.into(), gas_used, weight_delta)
2353 },
2354 }
2355 });
2356
2357 result.map(|_| ())
2358 }
2359 };
2360
2361 let result = try_call();
2363
2364 self.top_frame_mut().allows_reentry = true;
2366
2367 result
2368 }
2369
2370 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2371 self.with_transient_storage(|transient_storage| {
2372 transient_storage.read(self.account_id(), key)
2373 })
2374 }
2375
2376 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2377 self.with_transient_storage(|transient_storage| {
2378 transient_storage.read(self.account_id(), key).map(|value| value.len() as _)
2379 })
2380 }
2381
2382 fn set_transient_storage(
2383 &mut self,
2384 key: &Key,
2385 value: Option<Vec<u8>>,
2386 take_old: bool,
2387 ) -> Result<WriteOutcome, DispatchError> {
2388 let account_id = self.account_id().clone();
2389 self.with_transient_storage_mut(|transient_storage| {
2390 transient_storage.write(&account_id, key, value, take_old)
2391 })
2392 }
2393
2394 fn account_id(&self) -> &T::AccountId {
2395 &self.top_frame().account_id
2396 }
2397
2398 fn caller(&self) -> Origin<T> {
2399 if let Some(Ok(mock_caller)) = self
2400 .exec_config
2401 .mock_handler
2402 .as_ref()
2403 .and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2404 .map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2405 {
2406 return mock_caller;
2407 }
2408
2409 if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
2410 caller.clone()
2411 } else {
2412 self.frames()
2413 .nth(1)
2414 .map(|f| Origin::from_account_id(f.account_id.clone()))
2415 .unwrap_or(self.origin.clone())
2416 }
2417 }
2418
2419 fn caller_of_caller(&self) -> Origin<T> {
2420 let caller_of_caller_frame = match self.frames().nth(2) {
2422 None => return self.origin.clone(),
2423 Some(frame) => frame,
2424 };
2425 if let Some(DelegateInfo { caller, .. }) = &caller_of_caller_frame.delegate {
2426 caller.clone()
2427 } else {
2428 Origin::from_account_id(caller_of_caller_frame.account_id.clone())
2429 }
2430 }
2431
2432 fn origin(&self) -> &Origin<T> {
2433 if let Some(mock_origin) = self
2434 .exec_config
2435 .mock_handler
2436 .as_ref()
2437 .and_then(|mock_handler| mock_handler.mock_origin())
2438 {
2439 return mock_origin;
2440 }
2441
2442 &self.origin
2443 }
2444
2445 fn to_account_id(&self, address: &H160) -> T::AccountId {
2446 T::AddressMapper::to_account_id(address)
2447 }
2448
2449 fn code_hash(&self, address: &H160) -> H256 {
2450 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2451 self.exec_config
2452 .mock_handler
2453 .as_ref()
2454 .and_then(|handler| handler.mocked_code(*address))
2455 }) {
2456 return sp_io::hashing::keccak_256(code).into();
2457 }
2458
2459 if let Some(target) = <AccountInfo<T>>::get_delegation_target(address) {
2463 let indicator = <AccountInfo<T>>::delegation_indicator(&target);
2464 return sp_io::hashing::keccak_256(&indicator).into();
2465 }
2466
2467 <AccountInfo<T>>::load_contract(&address)
2468 .map(|contract| contract.code_hash)
2469 .unwrap_or_else(|| {
2470 if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) {
2471 return EMPTY_CODE_HASH;
2472 }
2473 H256::zero()
2474 })
2475 }
2476
2477 fn code_size(&self, address: &H160) -> u64 {
2478 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2479 self.exec_config
2480 .mock_handler
2481 .as_ref()
2482 .and_then(|handler| handler.mocked_code(*address))
2483 }) {
2484 return code.len() as u64;
2485 }
2486
2487 if <AccountInfo<T>>::is_delegated(address) {
2496 return 23;
2497 }
2498
2499 <AccountInfo<T>>::load_contract(&address)
2500 .and_then(|contract| CodeInfoOf::<T>::get(contract.code_hash))
2501 .map(|info| info.code_len())
2502 .unwrap_or_default()
2503 }
2504
2505 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2506 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2507 self.origin == caller
2508 }
2509
2510 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2511 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2513 }
2514
2515 fn origin_is_root(&self) -> bool {
2516 self.origin == Origin::Root
2517 }
2518
2519 fn balance(&self) -> U256 {
2520 self.account_balance(&self.top_frame().account_id)
2521 }
2522
2523 fn balance_of(&self, address: &H160) -> U256 {
2524 let balance =
2525 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2526 if_tracing(|tracer| {
2527 tracer.balance_read(address, balance);
2528 });
2529 balance
2530 }
2531
2532 fn value_transferred(&self) -> U256 {
2533 self.top_frame().value_transferred.into()
2534 }
2535
2536 fn now(&self) -> U256 {
2537 (self.timestamp / 1000u32.into()).into()
2538 }
2539
2540 fn minimum_balance(&self) -> U256 {
2541 let min = T::Currency::minimum_balance();
2542 crate::Pallet::<T>::convert_native_to_evm(min)
2543 }
2544
2545 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2546 let contract = T::AddressMapper::to_address(self.account_id());
2547 if_tracing(|tracer| {
2548 let log_index = frame_system::Pallet::<Self::T>::event_count();
2549 tracer.log_event(contract, &topics, &data, log_index);
2550 });
2551
2552 block_storage::capture_ethereum_log(&contract, &data, &topics);
2554
2555 Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2556 }
2557
2558 fn block_number(&self) -> U256 {
2559 self.block_number.into()
2560 }
2561
2562 fn block_hash(&self, block_number: U256) -> Option<H256> {
2563 self.block_hash(block_number)
2564 }
2565
2566 fn block_author(&self) -> H160 {
2567 Contracts::<Self::T>::block_author()
2568 }
2569
2570 fn gas_limit(&self) -> u64 {
2571 <Contracts<T>>::evm_block_gas_limit().saturated_into()
2572 }
2573
2574 fn chain_id(&self) -> u64 {
2575 <T as Config>::ChainId::get()
2576 }
2577
2578 fn gas_meter(&self) -> &FrameMeter<Self::T> {
2579 &self.top_frame().frame_meter
2580 }
2581
2582 #[inline]
2583 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2584 &mut self.top_frame_mut().frame_meter
2585 }
2586
2587 fn frame_meter(&self) -> &FrameMeter<Self::T> {
2588 &self.top_frame().frame_meter
2589 }
2590
2591 #[inline]
2592 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2593 &mut self.top_frame_mut().frame_meter
2594 }
2595
2596 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2597 secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2598 }
2599
2600 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2601 sp_io::crypto::sr25519_verify(
2602 &SR25519Signature::from(*signature),
2603 message,
2604 &SR25519Public::from(*pub_key),
2605 )
2606 }
2607
2608 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError> {
2609 Ok(ECDSAPublic::from(*pk)
2610 .to_eth_address()
2611 .or_else(|()| Err(Error::<T>::EcdsaRecoveryFailed))?)
2612 }
2613
2614 #[cfg(any(test, feature = "runtime-benchmarks"))]
2615 fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2616 self.top_frame_mut().contract_info()
2617 }
2618
2619 #[cfg(any(feature = "runtime-benchmarks", test))]
2620 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2621 &mut self.transient_storage
2622 }
2623
2624 fn is_read_only(&self) -> bool {
2625 self.top_frame().read_only
2626 }
2627
2628 fn is_delegate_call(&self) -> bool {
2629 self.top_frame().delegate.is_some()
2630 }
2631
2632 fn last_frame_output(&self) -> &ExecReturnValue {
2633 &self.top_frame().last_frame_output
2634 }
2635
2636 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2637 &mut self.top_frame_mut().last_frame_output
2638 }
2639
2640 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2641 let len = buf.len();
2642 if len == 0 {
2643 return;
2644 }
2645
2646 let code = if let Some(code) =
2647 <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2648 self.exec_config
2649 .mock_handler
2650 .as_ref()
2651 .and_then(|handler| handler.mocked_code(*address))
2652 }) {
2653 code.to_vec()
2654 } else if let Some(target) = <AccountInfo<T>>::get_delegation_target(address) {
2655 <AccountInfo<T>>::delegation_indicator(&target).to_vec()
2664 } else {
2665 let code_hash = self.code_hash(address);
2666 crate::PristineCode::<T>::get(&code_hash).unwrap_or_default()
2667 };
2668
2669 let copy_len = len.min(code.len().saturating_sub(code_offset));
2670 if copy_len > 0 {
2671 buf[..copy_len].copy_from_slice(&code[code_offset..code_offset + copy_len]);
2672 }
2673 buf[copy_len..].fill(0);
2674 }
2675
2676 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2677 ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2678 let parent = self.frames_mut().nth(1).ok_or_else(|| Error::<T>::ContractNotFound)?;
2679 ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2680 ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2681
2682 let contract_address = T::AddressMapper::to_address(&parent.account_id);
2683
2684 ensure!(
2686 !AccountInfo::<T>::is_delegated(&contract_address),
2687 Error::<T>::CannotTerminateDelegatedAccount,
2688 );
2689
2690 let info = parent.contract_info();
2691 let trie_id = info.trie_id.clone();
2692 let code_hash = info.code_hash;
2693 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2694
2695 let parent_account_id = parent.account_id.clone();
2696
2697 Self::transfer(
2699 &self.origin,
2700 &parent_account_id,
2701 &beneficiary,
2702 <Contracts<T>>::evm_balance(&contract_address),
2703 Preservation::Preserve,
2704 &mut top_frame_mut!(self).frame_meter,
2705 &self.exec_config,
2706 )?;
2707
2708 let args = TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: false };
2710 self.top_frame_mut().contracts_to_be_destroyed.insert(parent_account_id, args);
2711
2712 Ok(())
2713 }
2714
2715 fn effective_gas_price(&self) -> U256 {
2716 self.exec_config
2717 .effective_gas_price
2718 .unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2719 }
2720
2721 fn gas_left(&self) -> u64 {
2722 let frame = self.top_frame();
2723
2724 frame.frame_meter.eth_gas_left().unwrap_or_default().saturated_into::<u64>()
2725 }
2726
2727 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2728 assert!(self.has_contract_info());
2729 self.top_frame_mut().contract_info().read(key)
2730 }
2731
2732 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2733 assert!(self.has_contract_info());
2734 self.top_frame_mut().contract_info().size(key.into())
2735 }
2736
2737 fn set_storage(
2738 &mut self,
2739 key: &Key,
2740 value: Option<Vec<u8>>,
2741 take_old: bool,
2742 ) -> Result<WriteOutcome, DispatchError> {
2743 assert!(self.has_contract_info());
2744 let frame = self.top_frame_mut();
2745 frame.contract_info.get(&frame.account_id).write(
2746 key.into(),
2747 value,
2748 Some(&mut frame.frame_meter),
2749 take_old,
2750 )
2751 }
2752
2753 fn touch_storage_access(&mut self, key: &Key, op: StorageOp) -> Warmth {
2754 let address = self.address();
2755 self.access_list.touch(AccessEntry { address, slot: key.into() }, op)
2756 }
2757
2758 fn peek_storage_access(&self, key: &Key) -> Warmth {
2759 let address = self.address();
2760 self.access_list.peek(&AccessEntry { address, slot: key.into() })
2761 }
2762
2763 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult {
2764 assert!(self.has_contract_info());
2765 self.top_frame_mut().frame_meter.record_contract_storage_changes(diff)
2766 }
2767}
2768
2769pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2771 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2772}
2773
2774#[cfg(feature = "runtime-benchmarks")]
2775pub fn bench_do_terminate<T: Config>(
2776 transaction_meter: &mut TransactionMeter<T>,
2777 exec_config: &ExecConfig<T>,
2778 contract_account: &T::AccountId,
2779 origin: &Origin<T>,
2780 beneficiary: T::AccountId,
2781 trie_id: TrieId,
2782 code_hash: H256,
2783 only_if_same_tx: bool,
2784) -> Result<(), DispatchError> {
2785 Stack::<T, crate::ContractBlob<T>>::do_terminate(
2786 transaction_meter,
2787 exec_config,
2788 contract_account,
2789 origin,
2790 &TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx },
2791 )
2792}
2793
2794mod sealing {
2795 use super::*;
2796
2797 pub trait Sealed {}
2798 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2799
2800 #[cfg(test)]
2801 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2802}