1use crate::{
19 address::{self, AddressMapper},
20 evm::{block_storage, transfer_with_dust},
21 limits,
22 metering::{ChargedAmount, Diff, FrameMeter, ResourceMeter, State, Token, TransactionMeter},
23 precompiles::{All as AllPrecompiles, Instance as PrecompileInstance, Precompiles},
24 primitives::{ExecConfig, ExecReturnValue, StorageDeposit},
25 runtime_decl_for_revive_api::{Decode, Encode, RuntimeDebugNoBound, TypeInfo},
26 storage::{AccountIdOrAddress, WriteOutcome},
27 tracing::if_tracing,
28 transient_storage::TransientStorage,
29 AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf,
30 CodeRemoved, Config, ContractInfo, Error, Event, HoldReason, ImmutableData, ImmutableDataOf,
31 Pallet as Contracts, RuntimeCosts, TrieId, LOG_TARGET,
32};
33use alloc::{
34 collections::{BTreeMap, BTreeSet},
35 vec::Vec,
36};
37use core::{cmp, fmt::Debug, marker::PhantomData, mem, ops::ControlFlow};
38use frame_support::{
39 crypto::ecdsa::ECDSAExt,
40 dispatch::DispatchResult,
41 ensure,
42 storage::{with_transaction, TransactionOutcome},
43 traits::{
44 fungible::{Inspect, Mutate},
45 tokens::Preservation,
46 Time,
47 },
48 weights::Weight,
49 Blake2_128Concat, BoundedVec, DebugNoBound, StorageHasher,
50};
51use frame_system::{
52 pallet_prelude::{BlockNumberFor, OriginFor},
53 Pallet as System, RawOrigin,
54};
55use sp_core::{
56 ecdsa::Public as ECDSAPublic,
57 sr25519::{Public as SR25519Public, Signature as SR25519Signature},
58 ConstU32, Get, H160, H256, U256,
59};
60use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
61use sp_runtime::{
62 traits::{BadOrigin, Saturating, TrailingZeroInput},
63 DispatchError, SaturatedConversion,
64};
65
66#[cfg(test)]
67mod tests;
68
69#[cfg(test)]
70pub mod mock_ext;
71
72pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
73pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
74pub type ExecResult = Result<ExecReturnValue, ExecError>;
75
76type VarSizedKey = BoundedVec<u8, ConstU32<{ limits::STORAGE_KEY_BYTES }>>;
78
79const 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";
80
81pub const EMPTY_CODE_HASH: H256 =
83 H256(sp_core::hex2array!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
84
85#[derive(Debug)]
87pub enum Key {
88 Fix([u8; 32]),
90 Var(VarSizedKey),
92}
93
94impl Key {
95 pub fn unhashed(&self) -> &[u8] {
97 match self {
98 Key::Fix(v) => v.as_ref(),
99 Key::Var(v) => v.as_ref(),
100 }
101 }
102
103 pub fn hash(&self) -> Vec<u8> {
105 match self {
106 Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
107 Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
108 }
109 }
110
111 pub fn from_fixed(v: [u8; 32]) -> Self {
112 Self::Fix(v)
113 }
114
115 pub fn try_from_var(v: Vec<u8>) -> Result<Self, ()> {
116 VarSizedKey::try_from(v).map(Self::Var).map_err(|_| ())
117 }
118}
119
120#[derive(Copy, Clone, PartialEq, Debug)]
126pub enum ReentrancyProtection {
127 AllowReentry,
129 Strict,
132 AllowNext,
140}
141
142#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
148pub enum ErrorOrigin {
149 Caller,
154 Callee,
156}
157
158#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
160pub struct ExecError {
161 pub error: DispatchError,
163 pub origin: ErrorOrigin,
165}
166
167impl<T: Into<DispatchError>> From<T> for ExecError {
168 fn from(error: T) -> Self {
169 Self { error: error.into(), origin: ErrorOrigin::Caller }
170 }
171}
172
173#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebugNoBound)]
175pub enum Origin<T: Config> {
176 Root,
177 Signed(T::AccountId),
178}
179
180impl<T: Config> Origin<T> {
181 pub fn from_account_id(account_id: T::AccountId) -> Self {
183 Origin::Signed(account_id)
184 }
185
186 pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
188 match o.into() {
189 Ok(RawOrigin::Root) => Ok(Self::Root),
190 Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
191 _ => Err(BadOrigin.into()),
192 }
193 }
194
195 pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
197 match self {
198 Origin::Signed(id) => Ok(id),
199 Origin::Root => Err(DispatchError::RootNotAllowed),
200 }
201 }
202
203 fn ensure_mapped(&self) -> DispatchResult {
208 match self {
209 Self::Root => Ok(()),
210 Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()),
211 Self::Signed(_) => Err(<Error<T>>::AccountUnmapped.into()),
212 }
213 }
214}
215
216#[derive(DebugNoBound)]
219pub enum CallResources<T: Config> {
220 NoLimits,
222 WeightDeposit { weight: Weight, deposit_limit: BalanceOf<T> },
224 Ethereum { gas: BalanceOf<T>, add_stipend: bool },
226}
227
228impl<T: Config> CallResources<T> {
229 pub fn from_weight_and_deposit(weight: Weight, deposit_limit: U256) -> Self {
231 Self::WeightDeposit {
232 weight,
233 deposit_limit: deposit_limit.saturated_into::<BalanceOf<T>>(),
234 }
235 }
236
237 pub fn from_ethereum_gas(gas: U256, add_stipend: bool) -> Self {
239 Self::Ethereum { gas: gas.saturated_into::<BalanceOf<T>>(), add_stipend }
240 }
241}
242
243impl<T: Config> Default for CallResources<T> {
244 fn default() -> Self {
245 Self::WeightDeposit { weight: Default::default(), deposit_limit: Default::default() }
246 }
247}
248
249struct TerminateArgs<T: Config> {
251 beneficiary: T::AccountId,
253 trie_id: TrieId,
255 code_hash: H256,
257 only_if_same_tx: bool,
259}
260
261pub trait Ext: PrecompileWithInfoExt {
263 fn delegate_call(
267 &mut self,
268 call_resources: &CallResources<Self::T>,
269 address: H160,
270 input_data: Vec<u8>,
271 ) -> Result<(), ExecError>;
272
273 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError>;
280
281 #[allow(dead_code)]
283 fn own_code_hash(&mut self) -> &H256;
284
285 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 account_id(&self) -> &AccountIdOf<Self::T>;
406
407 fn address(&self) -> H160 {
409 <Self::T as Config>::AddressMapper::to_address(self.account_id())
410 }
411
412 fn balance(&self) -> U256;
416
417 fn balance_of(&self, address: &H160) -> U256;
421
422 fn value_transferred(&self) -> U256;
424
425 fn now(&self) -> U256;
427
428 fn minimum_balance(&self) -> U256;
430
431 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
435
436 fn block_number(&self) -> U256;
438
439 fn block_hash(&self, block_number: U256) -> Option<H256>;
442
443 fn block_author(&self) -> H160;
445
446 fn gas_limit(&self) -> u64;
448
449 fn chain_id(&self) -> u64;
451
452 #[deprecated(note = "Renamed to `frame_meter`; this alias will be removed in future versions")]
454 fn gas_meter(&self) -> &FrameMeter<Self::T>;
455
456 #[deprecated(
458 note = "Renamed to `frame_meter_mut`; this alias will be removed in future versions"
459 )]
460 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
461
462 fn frame_meter(&self) -> &FrameMeter<Self::T>;
464
465 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
467
468 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
470
471 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
473
474 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError>;
476
477 #[cfg(any(test, feature = "runtime-benchmarks"))]
479 fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
480
481 #[cfg(any(feature = "runtime-benchmarks", test))]
485 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
486
487 fn is_read_only(&self) -> bool;
489
490 fn is_delegate_call(&self) -> bool;
492
493 fn last_frame_output(&self) -> &ExecReturnValue;
495
496 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
498
499 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize);
507
508 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError>;
517
518 fn effective_gas_price(&self) -> U256;
520
521 fn gas_left(&self) -> u64;
523
524 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
529
530 fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
535
536 fn set_storage(
539 &mut self,
540 key: &Key,
541 value: Option<Vec<u8>>,
542 take_old: bool,
543 ) -> Result<WriteOutcome, DispatchError>;
544
545 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult;
547}
548
549#[derive(
551 Copy,
552 Clone,
553 PartialEq,
554 Eq,
555 sp_core::RuntimeDebug,
556 codec::Decode,
557 codec::Encode,
558 codec::MaxEncodedLen,
559 scale_info::TypeInfo,
560)]
561pub enum ExportedFunction {
562 Constructor,
564 Call,
566}
567
568pub trait Executable<T: Config>: Sized {
573 fn from_storage<S: State>(
578 code_hash: H256,
579 meter: &mut ResourceMeter<T, S>,
580 ) -> Result<Self, DispatchError>;
581
582 fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
584
585 fn execute<E: Ext<T = T>>(
595 self,
596 ext: &mut E,
597 function: ExportedFunction,
598 input_data: Vec<u8>,
599 ) -> ExecResult;
600
601 fn code_info(&self) -> &CodeInfo<T>;
603
604 fn code(&self) -> &[u8];
606
607 fn code_hash(&self) -> &H256;
609}
610
611pub struct Stack<'a, T: Config, E> {
617 origin: Origin<T>,
626 transaction_meter: &'a mut TransactionMeter<T>,
628 timestamp: MomentOf<T>,
630 block_number: BlockNumberFor<T>,
632 frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
635 first_frame: Frame<T>,
637 transient_storage: TransientStorage<T>,
639 exec_config: &'a ExecConfig<T>,
641 _phantom: PhantomData<E>,
643}
644
645struct Frame<T: Config> {
650 account_id: T::AccountId,
652 contract_info: CachedContract<T>,
654 value_transferred: U256,
656 entry_point: ExportedFunction,
658 frame_meter: FrameMeter<T>,
660 allows_reentry: bool,
662 read_only: bool,
664 delegate: Option<DelegateInfo<T>>,
667 last_frame_output: ExecReturnValue,
669 contracts_created: BTreeSet<T::AccountId>,
671 contracts_to_be_destroyed: BTreeMap<T::AccountId, TerminateArgs<T>>,
673}
674
675#[derive(Clone, RuntimeDebugNoBound)]
678pub struct DelegateInfo<T: Config> {
679 pub caller: Origin<T>,
681 pub callee: H160,
683}
684
685enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
687 Executable(E),
689 Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
691}
692
693impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
694 fn as_executable(&self) -> Option<&E> {
695 if let Self::Executable(executable) = self {
696 Some(executable)
697 } else {
698 None
699 }
700 }
701
702 fn is_pvm(&self) -> bool {
703 match self {
704 Self::Executable(e) => e.code_info().is_pvm(),
705 _ => false,
706 }
707 }
708
709 fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
710 if let Self::Precompile { instance, .. } = self {
711 Some(instance)
712 } else {
713 None
714 }
715 }
716
717 #[cfg(any(feature = "runtime-benchmarks", test))]
718 fn into_executable(self) -> Option<E> {
719 if let Self::Executable(executable) = self {
720 Some(executable)
721 } else {
722 None
723 }
724 }
725}
726
727enum FrameArgs<'a, T: Config, E> {
731 Call {
732 dest: T::AccountId,
734 cached_info: Option<ContractInfo<T>>,
736 delegated_call: Option<DelegateInfo<T>>,
740 },
741 Instantiate {
742 sender: T::AccountId,
744 executable: E,
746 salt: Option<&'a [u8; 32]>,
748 input_data: &'a [u8],
750 },
751}
752
753enum CachedContract<T: Config> {
755 Cached(ContractInfo<T>),
757 Invalidated,
761 None,
763}
764
765impl<T: Config> Frame<T> {
766 fn contract_info(&mut self) -> &mut ContractInfo<T> {
768 self.contract_info.get(&self.account_id)
769 }
770}
771
772macro_rules! get_cached_or_panic_after_load {
776 ($c:expr) => {{
777 if let CachedContract::Cached(contract) = $c {
778 contract
779 } else {
780 panic!(
781 "It is impossible to remove a contract that is on the call stack;\
782 See implementations of terminate;\
783 Therefore fetching a contract will never fail while using an account id
784 that is currently active on the call stack;\
785 qed"
786 );
787 }
788 }};
789}
790
791macro_rules! top_frame {
796 ($stack:expr) => {
797 $stack.frames.last().unwrap_or(&$stack.first_frame)
798 };
799}
800
801macro_rules! top_frame_mut {
806 ($stack:expr) => {
807 $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
808 };
809}
810
811impl<T: Config> CachedContract<T> {
812 fn into_contract(self) -> Option<ContractInfo<T>> {
814 if let CachedContract::Cached(contract) = self {
815 Some(contract)
816 } else {
817 None
818 }
819 }
820
821 fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
823 if let CachedContract::Cached(contract) = self {
824 Some(contract)
825 } else {
826 None
827 }
828 }
829
830 fn load(&mut self, account_id: &T::AccountId) {
832 if let CachedContract::Invalidated = self {
833 if let Some(contract) =
834 AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
835 {
836 *self = CachedContract::Cached(contract);
837 }
838 }
839 }
840
841 fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
843 self.load(account_id);
844 get_cached_or_panic_after_load!(self)
845 }
846
847 fn invalidate(&mut self) {
849 if matches!(self, CachedContract::Cached(_)) {
850 *self = CachedContract::Invalidated;
851 }
852 }
853}
854
855impl<'a, T, E> Stack<'a, T, E>
856where
857 T: Config,
858 E: Executable<T>,
859{
860 pub fn run_call(
866 origin: Origin<T>,
867 dest: H160,
868 transaction_meter: &'a mut TransactionMeter<T>,
869 value: U256,
870 input_data: Vec<u8>,
871 exec_config: &ExecConfig<T>,
872 ) -> ExecResult {
873 let dest = T::AddressMapper::to_account_id(&dest);
874 if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
875 FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
876 origin.clone(),
877 transaction_meter,
878 value,
879 exec_config,
880 &input_data,
881 )? {
882 stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
883 } else {
884 if_tracing(|t| {
885 t.enter_child_span(
886 origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
887 T::AddressMapper::to_address(&dest),
888 None,
889 false,
890 value,
891 &input_data,
892 Default::default(),
893 );
894 });
895
896 let result = if let Some(mock_answer) =
897 exec_config.mock_handler.as_ref().and_then(|handler| {
898 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
899 }) {
900 Ok(mock_answer)
901 } else {
902 Self::transfer_from_origin(
903 &origin,
904 &origin,
905 &dest,
906 value,
907 transaction_meter,
908 exec_config,
909 )
910 };
911
912 if_tracing(|t| match result {
913 Ok(ref output) => t.exit_child_span(&output, Default::default()),
914 Err(e) => t.exit_child_span_with_error(e.error.into(), Default::default()),
915 });
916
917 log::trace!(target: LOG_TARGET, "call finished with: {result:?}");
918
919 result
920 }
921 }
922
923 pub fn run_instantiate(
929 origin: T::AccountId,
930 executable: E,
931 transaction_meter: &'a mut TransactionMeter<T>,
932 value: U256,
933 input_data: Vec<u8>,
934 salt: Option<&[u8; 32]>,
935 exec_config: &ExecConfig<T>,
936 ) -> Result<(H160, ExecReturnValue), ExecError> {
937 let deployer = T::AddressMapper::to_address(&origin);
938 let (mut stack, executable) = Stack::<'_, T, E>::new(
939 FrameArgs::Instantiate {
940 sender: origin.clone(),
941 executable,
942 salt,
943 input_data: input_data.as_ref(),
944 },
945 Origin::from_account_id(origin),
946 transaction_meter,
947 value,
948 exec_config,
949 &input_data,
950 )?
951 .expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
952 let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
953 let result = stack
954 .run(executable, input_data)
955 .map(|_| (address, stack.first_frame.last_frame_output));
956 if let Ok((contract, ref output)) = result {
957 if !output.did_revert() {
958 Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract });
959 }
960 }
961 log::trace!(target: LOG_TARGET, "instantiate finished with: {result:?}");
962 result
963 }
964
965 #[cfg(any(feature = "runtime-benchmarks", test))]
966 pub fn bench_new_call(
967 dest: H160,
968 origin: Origin<T>,
969 transaction_meter: &'a mut TransactionMeter<T>,
970 value: BalanceOf<T>,
971 exec_config: &'a ExecConfig<T>,
972 ) -> (Self, E) {
973 let call = Self::new(
974 FrameArgs::Call {
975 dest: T::AddressMapper::to_account_id(&dest),
976 cached_info: None,
977 delegated_call: None,
978 },
979 origin,
980 transaction_meter,
981 value.into(),
982 exec_config,
983 &Default::default(),
984 )
985 .unwrap()
986 .unwrap();
987 (call.0, call.1.into_executable().unwrap())
988 }
989
990 fn new(
995 args: FrameArgs<T, E>,
996 origin: Origin<T>,
997 transaction_meter: &'a mut TransactionMeter<T>,
998 value: U256,
999 exec_config: &'a ExecConfig<T>,
1000 input_data: &Vec<u8>,
1001 ) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1002 origin.ensure_mapped()?;
1003 let Some((first_frame, executable)) = Self::new_frame(
1004 args,
1005 value,
1006 transaction_meter,
1007 &CallResources::NoLimits,
1008 false,
1009 true,
1010 input_data,
1011 exec_config,
1012 )?
1013 else {
1014 return Ok(None);
1015 };
1016
1017 let mut timestamp = T::Time::now();
1018 let mut block_number = <frame_system::Pallet<T>>::block_number();
1019 if let Some(timestamp_override) =
1021 exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override)
1022 {
1023 block_number = block_number.saturating_add(1u32.into());
1024 let delta = 1000u32.into();
1026 timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override);
1027 }
1028
1029 let stack = Self {
1030 origin,
1031 transaction_meter,
1032 timestamp,
1033 block_number,
1034 first_frame,
1035 frames: Default::default(),
1036 transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
1037 exec_config,
1038 _phantom: Default::default(),
1039 };
1040 Ok(Some((stack, executable)))
1041 }
1042
1043 fn new_frame<S: State>(
1048 frame_args: FrameArgs<T, E>,
1049 value_transferred: U256,
1050 meter: &mut ResourceMeter<T, S>,
1051 call_resources: &CallResources<T>,
1052 read_only: bool,
1053 origin_is_caller: bool,
1054 input_data: &[u8],
1055 exec_config: &ExecConfig<T>,
1056 ) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1057 let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
1058 FrameArgs::Call { dest, cached_info, delegated_call } => {
1059 let address = T::AddressMapper::to_address(&dest);
1060 let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
1061
1062 let mut contract = match (cached_info, &precompile) {
1065 (Some(info), _) => CachedContract::Cached(info),
1066 (None, None) =>
1067 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
1068 CachedContract::Cached(info)
1069 } else {
1070 return Ok(None);
1071 },
1072 (None, Some(precompile)) if precompile.has_contract_info() => {
1073 log::trace!(target: LOG_TARGET, "found precompile for address {address:?}");
1074 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
1075 CachedContract::Cached(info)
1076 } else {
1077 let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
1078 CachedContract::Cached(info)
1079 }
1080 },
1081 (None, Some(_)) => CachedContract::None,
1082 };
1083
1084 let delegated_call = delegated_call.or_else(|| {
1085 exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1086 mock_handler.mock_delegated_caller(address, input_data)
1087 })
1088 });
1089 let executable = if let Some(delegated_call) = &delegated_call {
1091 if let Some(precompile) =
1092 <AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
1093 {
1094 ExecutableOrPrecompile::Precompile {
1095 instance: precompile,
1096 _phantom: Default::default(),
1097 }
1098 } else {
1099 let Some(info) = AccountInfo::<T>::load_contract(&delegated_call.callee)
1100 else {
1101 return Ok(None);
1102 };
1103 let executable = E::from_storage(info.code_hash, meter)?;
1104 ExecutableOrPrecompile::Executable(executable)
1105 }
1106 } else {
1107 if let Some(precompile) = precompile {
1108 ExecutableOrPrecompile::Precompile {
1109 instance: precompile,
1110 _phantom: Default::default(),
1111 }
1112 } else {
1113 let executable = E::from_storage(
1114 contract
1115 .as_contract()
1116 .expect("When not a precompile the contract was loaded above; qed")
1117 .code_hash,
1118 meter,
1119 )?;
1120 ExecutableOrPrecompile::Executable(executable)
1121 }
1122 };
1123
1124 (dest, contract, executable, delegated_call, ExportedFunction::Call)
1125 },
1126 FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1127 let deployer = T::AddressMapper::to_address(&sender);
1128 let account_nonce = <System<T>>::account_nonce(&sender);
1129 let address = if let Some(salt) = salt {
1130 address::create2(&deployer, executable.code(), input_data, salt)
1131 } else {
1132 use sp_runtime::Saturating;
1133 address::create1(
1134 &deployer,
1135 if origin_is_caller {
1138 account_nonce.saturating_sub(1u32.into()).saturated_into()
1139 } else {
1140 account_nonce.saturated_into()
1141 },
1142 )
1143 };
1144 let contract = ContractInfo::new(
1145 &address,
1146 <System<T>>::account_nonce(&sender),
1147 *executable.code_hash(),
1148 )?;
1149 (
1150 T::AddressMapper::to_fallback_account_id(&address),
1151 CachedContract::Cached(contract),
1152 ExecutableOrPrecompile::Executable(executable),
1153 None,
1154 ExportedFunction::Constructor,
1155 )
1156 },
1157 };
1158
1159 let frame = Frame {
1160 delegate,
1161 value_transferred,
1162 contract_info,
1163 account_id,
1164 entry_point,
1165 frame_meter: meter.new_nested(call_resources)?,
1166 allows_reentry: true,
1167 read_only,
1168 last_frame_output: Default::default(),
1169 contracts_created: Default::default(),
1170 contracts_to_be_destroyed: Default::default(),
1171 };
1172
1173 Ok(Some((frame, executable)))
1174 }
1175
1176 fn push_frame(
1178 &mut self,
1179 frame_args: FrameArgs<T, E>,
1180 value_transferred: U256,
1181 call_resources: &CallResources<T>,
1182 read_only: bool,
1183 input_data: &[u8],
1184 ) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1185 if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1186 return Err(Error::<T>::MaxCallDepthReached.into());
1187 }
1188
1189 let frame = self.top_frame();
1194 if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1195 (&frame.contract_info, frame.entry_point)
1196 {
1197 AccountInfo::<T>::insert_contract(
1198 &T::AddressMapper::to_address(&frame.account_id),
1199 contract.clone(),
1200 );
1201 }
1202
1203 let frame = top_frame_mut!(self);
1204 let meter = &mut frame.frame_meter;
1205 if let Some((frame, executable)) = Self::new_frame(
1206 frame_args,
1207 value_transferred,
1208 meter,
1209 call_resources,
1210 read_only,
1211 false,
1212 input_data,
1213 self.exec_config,
1214 )? {
1215 self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1216 Ok(Some(executable))
1217 } else {
1218 Ok(None)
1219 }
1220 }
1221
1222 fn run(
1226 &mut self,
1227 executable: ExecutableOrPrecompile<T, E, Self>,
1228 input_data: Vec<u8>,
1229 ) -> Result<(), ExecError> {
1230 let frame = self.top_frame();
1231 let entry_point = frame.entry_point;
1232 let is_pvm = executable.is_pvm();
1233
1234 if_tracing(|tracer| {
1235 tracer.enter_child_span(
1236 self.caller().account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
1237 T::AddressMapper::to_address(&frame.account_id),
1238 frame.delegate.as_ref().map(|delegate| delegate.callee),
1239 frame.read_only,
1240 frame.value_transferred,
1241 &input_data,
1242 frame.frame_meter.eth_gas_left().unwrap_or_default().into(),
1243 );
1244 });
1245 let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1246 handler.mock_call(
1247 frame
1248 .delegate
1249 .as_ref()
1250 .map(|delegate| delegate.callee)
1251 .unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1252 &input_data,
1253 frame.value_transferred,
1254 )
1255 });
1256 let frames_len = self.frames.len();
1260 if let Some(caller_frame) = match frames_len {
1261 0 => None,
1262 1 => Some(&mut self.first_frame.last_frame_output),
1263 _ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1264 } {
1265 *caller_frame = Default::default();
1266 }
1267
1268 self.transient_storage.start_transaction();
1269 let is_first_frame = self.frames.is_empty();
1270
1271 let do_transaction = || -> ExecResult {
1272 let caller = self.caller();
1273 let bump_nonce = self.exec_config.bump_nonce;
1274 let frame = top_frame_mut!(self);
1275 let account_id = &frame.account_id.clone();
1276
1277 if u32::try_from(input_data.len())
1278 .map(|len| len > limits::CALLDATA_BYTES)
1279 .unwrap_or(true)
1280 {
1281 Err(<Error<T>>::CallDataTooLarge)?;
1282 }
1283
1284 if entry_point == ExportedFunction::Constructor {
1287 let origin = &self.origin.account_id()?;
1290
1291 if !frame_system::Pallet::<T>::account_exists(&account_id) {
1292 let ed = <Contracts<T>>::min_balance();
1293 frame.frame_meter.charge_deposit(&StorageDeposit::Charge(ed))?;
1294 <Contracts<T>>::charge_deposit(None, origin, account_id, ed, self.exec_config)?;
1295 }
1296
1297 <System<T>>::inc_consumers(account_id)?;
1302
1303 <System<T>>::inc_account_nonce(account_id);
1305
1306 if bump_nonce || !is_first_frame {
1307 <System<T>>::inc_account_nonce(caller.account_id()?);
1310 }
1311 if is_pvm {
1313 <CodeInfo<T>>::increment_refcount(
1314 *executable
1315 .as_executable()
1316 .expect("Precompiles cannot be instantiated; qed")
1317 .code_hash(),
1318 )?;
1319 }
1320 }
1321
1322 if frame.delegate.is_none() {
1326 Self::transfer_from_origin(
1327 &self.origin,
1328 &caller,
1329 account_id,
1330 frame.value_transferred,
1331 &mut frame.frame_meter,
1332 self.exec_config,
1333 )?;
1334 }
1335
1336 if let Some(precompile) = executable.as_precompile() {
1343 if precompile.has_contract_info() &&
1344 frame.delegate.is_none() &&
1345 !<System<T>>::account_exists(account_id)
1346 {
1347 T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1350 <System<T>>::inc_consumers(account_id)?;
1352 }
1353 }
1354
1355 let mut code_deposit = executable
1356 .as_executable()
1357 .map(|exec| exec.code_info().deposit())
1358 .unwrap_or_default();
1359
1360 let mut output = match executable {
1361 ExecutableOrPrecompile::Executable(executable) =>
1362 executable.execute(self, entry_point, input_data),
1363 ExecutableOrPrecompile::Precompile { instance, .. } =>
1364 instance.call(input_data, self),
1365 }
1366 .and_then(|output| {
1367 if u32::try_from(output.data.len())
1368 .map(|len| len > limits::CALLDATA_BYTES)
1369 .unwrap_or(true)
1370 {
1371 Err(<Error<T>>::ReturnDataTooLarge)?;
1372 }
1373 Ok(output)
1374 })
1375 .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1376
1377 if output.did_revert() {
1379 return Ok(output);
1380 }
1381
1382 let frame = if entry_point == ExportedFunction::Constructor {
1385 let origin = self.origin.account_id()?.clone();
1386 let frame = top_frame_mut!(self);
1387 if !is_pvm {
1390 let data = if crate::tracing::if_tracing(|_| {}).is_none() &&
1394 self.exec_config.is_dry_run.is_none()
1395 {
1396 core::mem::replace(&mut output.data, Default::default())
1397 } else {
1398 output.data.clone()
1399 };
1400
1401 let mut module = crate::ContractBlob::<T>::from_evm_runtime_code(data, origin)?;
1402 module.store_code(&self.exec_config, &mut frame.frame_meter)?;
1403 code_deposit = module.code_info().deposit();
1404
1405 let contract_info = frame.contract_info();
1406 contract_info.code_hash = *module.code_hash();
1407 <CodeInfo<T>>::increment_refcount(contract_info.code_hash)?;
1408 }
1409
1410 let deposit = frame.contract_info().update_base_deposit(code_deposit);
1411 frame.frame_meter.charge_contract_deposit_and_transfer(
1412 frame.account_id.clone(),
1413 StorageDeposit::Charge(deposit),
1414 )?;
1415 frame
1416 } else {
1417 self.top_frame_mut()
1418 };
1419
1420 let contract = frame.contract_info.as_contract();
1424 frame
1425 .frame_meter
1426 .finalize(contract)
1427 .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1428
1429 Ok(output)
1430 };
1431
1432 let transaction_outcome =
1439 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1440 let output = if let Some(mock_answer) = mock_answer {
1441 Ok(mock_answer)
1442 } else {
1443 do_transaction()
1444 };
1445 match &output {
1446 Ok(result) if !result.did_revert() =>
1447 TransactionOutcome::Commit(Ok((true, output))),
1448 _ => TransactionOutcome::Rollback(Ok((false, output))),
1449 }
1450 });
1451
1452 let (success, output) = match transaction_outcome {
1453 Ok((success, output)) => {
1455 if_tracing(|tracer| {
1456 let frame_meter = &top_frame!(self).frame_meter;
1457
1458 let gas_consumed = if is_first_frame {
1461 frame_meter.total_consumed_gas().into()
1462 } else {
1463 frame_meter.eth_gas_consumed().into()
1464 };
1465
1466 match &output {
1467 Ok(output) => tracer.exit_child_span(&output, gas_consumed),
1468 Err(e) => tracer.exit_child_span_with_error(e.error.into(), gas_consumed),
1469 }
1470 });
1471
1472 (success, output)
1473 },
1474 Err(error) => {
1477 if_tracing(|tracer| {
1478 let frame_meter = &top_frame!(self).frame_meter;
1479
1480 let gas_consumed = if is_first_frame {
1483 frame_meter.total_consumed_gas().into()
1484 } else {
1485 frame_meter.eth_gas_consumed().into()
1486 };
1487
1488 tracer.exit_child_span_with_error(error.into(), gas_consumed);
1489 });
1490
1491 (false, Err(error.into()))
1492 },
1493 };
1494
1495 if success {
1496 self.transient_storage.commit_transaction();
1497 } else {
1498 self.transient_storage.rollback_transaction();
1499 }
1500 log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1501
1502 self.pop_frame(success);
1503 output.map(|output| {
1504 self.top_frame_mut().last_frame_output = output;
1505 })
1506 }
1507
1508 fn pop_frame(&mut self, persist: bool) {
1513 let frame = self.frames.pop();
1517
1518 if let Some(mut frame) = frame {
1521 let account_id = &frame.account_id;
1522 let prev = top_frame_mut!(self);
1523
1524 if !persist {
1526 prev.frame_meter.absorb_weight_meter_only(frame.frame_meter);
1527 return;
1528 }
1529
1530 frame.contract_info.load(account_id);
1535 let mut contract = frame.contract_info.into_contract();
1536 prev.frame_meter
1537 .absorb_all_meters(frame.frame_meter, account_id, contract.as_mut());
1538
1539 prev.contracts_created.extend(frame.contracts_created);
1541 prev.contracts_to_be_destroyed.extend(frame.contracts_to_be_destroyed);
1542
1543 if let Some(contract) = contract {
1544 if prev.account_id == *account_id {
1549 prev.contract_info = CachedContract::Cached(contract);
1550 return;
1551 }
1552
1553 AccountInfo::<T>::insert_contract(
1559 &T::AddressMapper::to_address(account_id),
1560 contract,
1561 );
1562 if let Some(f) = self.frames_mut().skip(1).find(|f| f.account_id == *account_id) {
1563 f.contract_info.invalidate();
1564 }
1565 }
1566 } else {
1567 if !persist {
1568 self.transaction_meter
1569 .absorb_weight_meter_only(mem::take(&mut self.first_frame.frame_meter));
1570 return;
1571 }
1572
1573 let mut contract = self.first_frame.contract_info.as_contract();
1574 self.transaction_meter.absorb_all_meters(
1575 mem::take(&mut self.first_frame.frame_meter),
1576 &self.first_frame.account_id,
1577 contract.as_deref_mut(),
1578 );
1579
1580 if let Some(contract) = contract {
1581 AccountInfo::<T>::insert_contract(
1582 &T::AddressMapper::to_address(&self.first_frame.account_id),
1583 contract.clone(),
1584 );
1585 }
1586 let contracts_created = mem::take(&mut self.first_frame.contracts_created);
1588 let contracts_to_destroy = mem::take(&mut self.first_frame.contracts_to_be_destroyed);
1589 for (contract_account, args) in contracts_to_destroy {
1590 if args.only_if_same_tx && !contracts_created.contains(&contract_account) {
1591 continue;
1592 }
1593 Self::do_terminate(
1594 &mut self.transaction_meter,
1595 self.exec_config,
1596 &contract_account,
1597 &self.origin,
1598 &args,
1599 )
1600 .ok();
1601 }
1602 }
1603 }
1604
1605 fn transfer<S: State>(
1618 origin: &Origin<T>,
1619 from: &T::AccountId,
1620 to: &T::AccountId,
1621 value: U256,
1622 preservation: Preservation,
1623 meter: &mut ResourceMeter<T, S>,
1624 exec_config: &ExecConfig<T>,
1625 ) -> DispatchResult {
1626 let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1627 .map_err(|_| Error::<T>::BalanceConversionFailed)?;
1628 if value.is_zero() {
1629 return Ok(());
1630 }
1631
1632 if <System<T>>::account_exists(to) {
1633 return transfer_with_dust::<T>(from, to, value, preservation)
1634 }
1635
1636 let origin = origin.account_id()?;
1637 let ed = <T as Config>::Currency::minimum_balance();
1638 with_transaction(|| -> TransactionOutcome<DispatchResult> {
1639 match meter
1640 .charge_deposit(&StorageDeposit::Charge(ed))
1641 .and_then(|_| <Contracts<T>>::charge_deposit(None, origin, to, ed, exec_config))
1642 .and_then(|_| transfer_with_dust::<T>(from, to, value, preservation))
1643 {
1644 Ok(_) => TransactionOutcome::Commit(Ok(())),
1645 Err(err) => TransactionOutcome::Rollback(Err(err)),
1646 }
1647 })
1648 }
1649
1650 fn transfer_from_origin<S: State>(
1652 origin: &Origin<T>,
1653 from: &Origin<T>,
1654 to: &T::AccountId,
1655 value: U256,
1656 meter: &mut ResourceMeter<T, S>,
1657 exec_config: &ExecConfig<T>,
1658 ) -> ExecResult {
1659 let from = match from {
1662 Origin::Signed(caller) => caller,
1663 Origin::Root if value.is_zero() => return Ok(Default::default()),
1664 Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1665 };
1666 Self::transfer(origin, from, to, value, Preservation::Preserve, meter, exec_config)
1667 .map(|_| Default::default())
1668 .map_err(Into::into)
1669 }
1670
1671 fn do_terminate(
1673 transaction_meter: &mut TransactionMeter<T>,
1674 exec_config: &ExecConfig<T>,
1675 contract_account: &T::AccountId,
1676 origin: &Origin<T>,
1677 args: &TerminateArgs<T>,
1678 ) -> Result<(), DispatchError> {
1679 use frame_support::traits::fungible::InspectHold;
1680
1681 let contract_address = T::AddressMapper::to_address(contract_account);
1682
1683 let mut delete_contract = |trie_id: &TrieId, code_hash: &H256| {
1684 let refund = T::Currency::balance_on_hold(
1686 &HoldReason::StorageDepositReserve.into(),
1687 &contract_account,
1688 );
1689 <Contracts<T>>::refund_deposit(
1690 HoldReason::StorageDepositReserve,
1691 contract_account,
1692 origin.account_id()?,
1693 refund,
1694 Some(exec_config),
1695 )?;
1696
1697 System::<T>::dec_consumers(&contract_account);
1699
1700 Self::transfer(
1702 origin,
1703 contract_account,
1704 origin.account_id()?,
1705 Contracts::<T>::convert_native_to_evm(T::Currency::minimum_balance()),
1706 Preservation::Expendable,
1707 transaction_meter,
1708 exec_config,
1709 )?;
1710
1711 let balance = <Contracts<T>>::convert_native_to_evm(<AccountInfo<T>>::total_balance(
1715 contract_address.into(),
1716 ));
1717 Self::transfer(
1718 origin,
1719 contract_account,
1720 &args.beneficiary,
1721 balance,
1722 Preservation::Expendable,
1723 transaction_meter,
1724 exec_config,
1725 )?;
1726
1727 let _code_removed = <CodeInfo<T>>::decrement_refcount(*code_hash)?;
1729
1730 ContractInfo::<T>::queue_trie_for_deletion(trie_id.clone());
1732 AccountInfoOf::<T>::remove(contract_address);
1733 ImmutableDataOf::<T>::remove(contract_address);
1734
1735 transaction_meter.terminate(contract_account.clone(), refund);
1738
1739 Ok(())
1740 };
1741
1742 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1746 match delete_contract(&args.trie_id, &args.code_hash) {
1747 Ok(()) => {
1748 log::trace!(target: LOG_TARGET, "Terminated {contract_address:?}");
1750 TransactionOutcome::Commit(Ok(()))
1751 },
1752 Err(e) => {
1753 log::debug!(target: LOG_TARGET, "Contract at {contract_address:?} failed to terminate: {e:?}");
1754 TransactionOutcome::Rollback(Err(e))
1755 },
1756 }
1757 })
1758 }
1759
1760 fn top_frame(&self) -> &Frame<T> {
1762 top_frame!(self)
1763 }
1764
1765 fn top_frame_mut(&mut self) -> &mut Frame<T> {
1767 top_frame_mut!(self)
1768 }
1769
1770 fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1774 core::iter::once(&self.first_frame).chain(&self.frames).rev()
1775 }
1776
1777 fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1779 core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1780 }
1781
1782 fn allows_reentry(&self, id: &T::AccountId) -> bool {
1784 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1785 }
1786
1787 fn account_balance(&self, who: &T::AccountId) -> U256 {
1789 let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
1790 crate::Pallet::<T>::convert_native_to_evm(balance)
1791 }
1792
1793 #[cfg(feature = "runtime-benchmarks")]
1796 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
1797 self.top_frame_mut().entry_point = export;
1798 }
1799
1800 #[cfg(feature = "runtime-benchmarks")]
1801 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
1802 self.block_number = block_number;
1803 }
1804
1805 fn block_hash(&self, block_number: U256) -> Option<H256> {
1806 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
1807 return None;
1808 };
1809 if block_number >= self.block_number {
1810 return None;
1811 }
1812 if block_number < self.block_number.saturating_sub(256u32.into()) {
1813 return None;
1814 }
1815
1816 match crate::Pallet::<T>::eth_block_hash_from_number(block_number.into()) {
1820 Some(hash) => Some(hash),
1821 None => {
1822 use codec::Decode;
1823 let block_hash = System::<T>::block_hash(&block_number);
1824 Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
1825 },
1826 }
1827 }
1828
1829 fn has_contract_info(&self) -> bool {
1832 let address = self.address();
1833 let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
1834 if let Some(precompile) = precompile {
1835 return precompile.has_contract_info();
1836 }
1837 true
1838 }
1839}
1840
1841impl<'a, T, E> Ext for Stack<'a, T, E>
1842where
1843 T: Config,
1844 E: Executable<T>,
1845{
1846 fn delegate_call(
1847 &mut self,
1848 call_resources: &CallResources<T>,
1849 address: H160,
1850 input_data: Vec<u8>,
1851 ) -> Result<(), ExecError> {
1852 *self.last_frame_output_mut() = Default::default();
1855
1856 let top_frame = self.top_frame_mut();
1857 let contract_info = top_frame.contract_info().clone();
1858 let account_id = top_frame.account_id.clone();
1859 let value = top_frame.value_transferred;
1860 if let Some(executable) = self.push_frame(
1861 FrameArgs::Call {
1862 dest: account_id,
1863 cached_info: Some(contract_info),
1864 delegated_call: Some(DelegateInfo {
1865 caller: self.caller().clone(),
1866 callee: address,
1867 }),
1868 },
1869 value,
1870 call_resources,
1871 self.is_read_only(),
1872 &input_data,
1873 )? {
1874 self.run(executable, input_data)
1875 } else {
1876 Ok(())
1878 }
1879 }
1880
1881 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
1882 if_tracing(|tracer| {
1883 let addr = T::AddressMapper::to_address(self.account_id());
1884 tracer.terminate(
1885 addr,
1886 *beneficiary,
1887 self.top_frame().frame_meter.eth_gas_left().unwrap_or_default().into(),
1888 crate::Pallet::<T>::evm_balance(&addr),
1889 );
1890 });
1891 let frame = top_frame_mut!(self);
1892 let info = frame.contract_info();
1893 let trie_id = info.trie_id.clone();
1894 let code_hash = info.code_hash;
1895 let contract_address = T::AddressMapper::to_address(&frame.account_id);
1896 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
1897
1898 Self::transfer(
1900 &self.origin,
1901 &frame.account_id,
1902 &beneficiary,
1903 <Contracts<T>>::evm_balance(&contract_address),
1904 Preservation::Preserve,
1905 &mut frame.frame_meter,
1906 self.exec_config,
1907 )?;
1908
1909 let account_id = frame.account_id.clone();
1911 self.top_frame_mut().contracts_to_be_destroyed.insert(
1912 account_id,
1913 TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: true },
1914 );
1915 Ok(CodeRemoved::Yes)
1916 }
1917
1918 fn own_code_hash(&mut self) -> &H256 {
1919 &self.top_frame_mut().contract_info().code_hash
1920 }
1921
1922 fn immutable_data_len(&mut self) -> u32 {
1923 self.top_frame_mut().contract_info().immutable_data_len()
1924 }
1925
1926 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
1927 if self.top_frame().entry_point == ExportedFunction::Constructor {
1928 return Err(Error::<T>::InvalidImmutableAccess.into());
1929 }
1930
1931 let address = self
1933 .top_frame()
1934 .delegate
1935 .as_ref()
1936 .map(|d| d.callee)
1937 .unwrap_or(T::AddressMapper::to_address(self.account_id()));
1938 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
1939 }
1940
1941 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
1942 let frame = self.top_frame_mut();
1943 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
1944 return Err(Error::<T>::InvalidImmutableAccess.into());
1945 }
1946 frame.contract_info().set_immutable_data_len(data.len() as u32);
1947 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
1948 Ok(())
1949 }
1950}
1951
1952impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
1953where
1954 T: Config,
1955 E: Executable<T>,
1956{
1957 fn instantiate(
1958 &mut self,
1959 call_resources: &CallResources<T>,
1960 mut code: Code,
1961 value: U256,
1962 input_data: Vec<u8>,
1963 salt: Option<&[u8; 32]>,
1964 ) -> Result<H160, ExecError> {
1965 *self.last_frame_output_mut() = Default::default();
1968
1969 let sender = self.top_frame().account_id.clone();
1970 let executable = {
1971 let executable = match &mut code {
1972 Code::Upload(initcode) => {
1973 if !T::AllowEVMBytecode::get() {
1974 return Err(<Error<T>>::CodeRejected.into());
1975 }
1976 ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
1977 let initcode = crate::tracing::if_tracing(|_| initcode.clone())
1978 .unwrap_or_else(|| mem::take(initcode));
1979 E::from_evm_init_code(initcode, sender.clone())?
1980 },
1981 Code::Existing(hash) => {
1982 let executable = E::from_storage(*hash, self.frame_meter_mut())?;
1983 ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
1984 executable
1985 },
1986 };
1987 self.push_frame(
1988 FrameArgs::Instantiate {
1989 sender,
1990 executable,
1991 salt,
1992 input_data: input_data.as_ref(),
1993 },
1994 value,
1995 call_resources,
1996 self.is_read_only(),
1997 &input_data,
1998 )?
1999 };
2000 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
2001
2002 let account_id = self.top_frame().account_id.clone();
2004 self.top_frame_mut().contracts_created.insert(account_id);
2005
2006 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
2007 if_tracing(|t| t.instantiate_code(&code, salt));
2008 self.run(executable, input_data).map(|_| address)
2009 }
2010}
2011
2012impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
2013where
2014 T: Config,
2015 E: Executable<T>,
2016{
2017 type T = T;
2018
2019 fn call(
2020 &mut self,
2021 call_resources: &CallResources<T>,
2022 dest_addr: &H160,
2023 value: U256,
2024 input_data: Vec<u8>,
2025 allows_reentry: ReentrancyProtection,
2026 read_only: bool,
2027 ) -> Result<(), ExecError> {
2028 if allows_reentry == ReentrancyProtection::Strict {
2033 self.top_frame_mut().allows_reentry = false;
2034 }
2035
2036 *self.last_frame_output_mut() = Default::default();
2039
2040 let try_call = || {
2041 let is_read_only = read_only || self.is_read_only();
2043
2044 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2046 T::AddressMapper::to_fallback_account_id(dest_addr)
2047 } else {
2048 T::AddressMapper::to_account_id(dest_addr)
2049 };
2050
2051 if !self.allows_reentry(&dest) {
2052 return Err(<Error<T>>::ReentranceDenied.into());
2053 }
2054
2055 if allows_reentry == ReentrancyProtection::AllowNext {
2056 self.top_frame_mut().allows_reentry = false;
2057 }
2058
2059 let cached_info = self
2063 .frames()
2064 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2065 .and_then(|f| match &f.contract_info {
2066 CachedContract::Cached(contract) => Some(contract.clone()),
2067 _ => None,
2068 });
2069
2070 if let Some(executable) = self.push_frame(
2071 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2072 value,
2073 call_resources,
2074 is_read_only,
2075 &input_data,
2076 )? {
2077 self.run(executable, input_data)
2078 } else {
2079 if_tracing(|t| {
2080 t.enter_child_span(
2081 T::AddressMapper::to_address(self.account_id()),
2082 T::AddressMapper::to_address(&dest),
2083 None,
2084 is_read_only,
2085 value,
2086 &input_data,
2087 Default::default(),
2088 );
2089 });
2090 let result = if let Some(mock_answer) =
2091 self.exec_config.mock_handler.as_ref().and_then(|handler| {
2092 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2093 }) {
2094 *self.last_frame_output_mut() = mock_answer.clone();
2095 Ok(mock_answer)
2096 } else if is_read_only && value.is_zero() {
2097 Ok(Default::default())
2098 } else if is_read_only {
2099 Err(Error::<T>::StateChangeDenied.into())
2100 } else {
2101 let account_id = self.account_id().clone();
2102 let frame = top_frame_mut!(self);
2103 Self::transfer_from_origin(
2104 &self.origin,
2105 &Origin::from_account_id(account_id),
2106 &dest,
2107 value,
2108 &mut frame.frame_meter,
2109 self.exec_config,
2110 )
2111 };
2112
2113 if_tracing(|t| match result {
2114 Ok(ref output) => t.exit_child_span(&output, Default::default()),
2115 Err(e) => t.exit_child_span_with_error(e.error.into(), Default::default()),
2116 });
2117
2118 result.map(|_| ())
2119 }
2120 };
2121
2122 let result = try_call();
2124
2125 self.top_frame_mut().allows_reentry = true;
2127
2128 result
2129 }
2130
2131 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2132 self.transient_storage.read(self.account_id(), key)
2133 }
2134
2135 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2136 self.transient_storage
2137 .read(self.account_id(), key)
2138 .map(|value| value.len() as _)
2139 }
2140
2141 fn set_transient_storage(
2142 &mut self,
2143 key: &Key,
2144 value: Option<Vec<u8>>,
2145 take_old: bool,
2146 ) -> Result<WriteOutcome, DispatchError> {
2147 let account_id = self.account_id().clone();
2148 self.transient_storage.write(&account_id, key, value, take_old)
2149 }
2150
2151 fn account_id(&self) -> &T::AccountId {
2152 &self.top_frame().account_id
2153 }
2154
2155 fn caller(&self) -> Origin<T> {
2156 if let Some(Ok(mock_caller)) = self
2157 .exec_config
2158 .mock_handler
2159 .as_ref()
2160 .and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2161 .map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2162 {
2163 return mock_caller;
2164 }
2165
2166 if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
2167 caller.clone()
2168 } else {
2169 self.frames()
2170 .nth(1)
2171 .map(|f| Origin::from_account_id(f.account_id.clone()))
2172 .unwrap_or(self.origin.clone())
2173 }
2174 }
2175
2176 fn caller_of_caller(&self) -> Origin<T> {
2177 let caller_of_caller_frame = match self.frames().nth(2) {
2179 None => return self.origin.clone(),
2180 Some(frame) => frame,
2181 };
2182 if let Some(DelegateInfo { caller, .. }) = &caller_of_caller_frame.delegate {
2183 caller.clone()
2184 } else {
2185 Origin::from_account_id(caller_of_caller_frame.account_id.clone())
2186 }
2187 }
2188
2189 fn origin(&self) -> &Origin<T> {
2190 if let Some(mock_origin) = self
2191 .exec_config
2192 .mock_handler
2193 .as_ref()
2194 .and_then(|mock_handler| mock_handler.mock_origin())
2195 {
2196 return mock_origin;
2197 }
2198
2199 &self.origin
2200 }
2201
2202 fn to_account_id(&self, address: &H160) -> T::AccountId {
2203 T::AddressMapper::to_account_id(address)
2204 }
2205
2206 fn code_hash(&self, address: &H160) -> H256 {
2207 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()) {
2208 return sp_io::hashing::keccak_256(code).into()
2209 }
2210
2211 <AccountInfo<T>>::load_contract(&address)
2212 .map(|contract| contract.code_hash)
2213 .unwrap_or_else(|| {
2214 if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) {
2215 return EMPTY_CODE_HASH;
2216 }
2217 H256::zero()
2218 })
2219 }
2220
2221 fn code_size(&self, address: &H160) -> u64 {
2222 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()) {
2223 return code.len() as u64
2224 }
2225
2226 <AccountInfo<T>>::load_contract(&address)
2227 .and_then(|contract| CodeInfoOf::<T>::get(contract.code_hash))
2228 .map(|info| info.code_len())
2229 .unwrap_or_default()
2230 }
2231
2232 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2233 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2234 self.origin == caller
2235 }
2236
2237 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2238 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2240 }
2241
2242 fn balance(&self) -> U256 {
2243 self.account_balance(&self.top_frame().account_id)
2244 }
2245
2246 fn balance_of(&self, address: &H160) -> U256 {
2247 let balance =
2248 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2249 if_tracing(|tracer| {
2250 tracer.balance_read(address, balance);
2251 });
2252 balance
2253 }
2254
2255 fn value_transferred(&self) -> U256 {
2256 self.top_frame().value_transferred.into()
2257 }
2258
2259 fn now(&self) -> U256 {
2260 (self.timestamp / 1000u32.into()).into()
2261 }
2262
2263 fn minimum_balance(&self) -> U256 {
2264 let min = T::Currency::minimum_balance();
2265 crate::Pallet::<T>::convert_native_to_evm(min)
2266 }
2267
2268 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2269 let contract = T::AddressMapper::to_address(self.account_id());
2270 if_tracing(|tracer| {
2271 tracer.log_event(contract, &topics, &data);
2272 });
2273
2274 block_storage::capture_ethereum_log(&contract, &data, &topics);
2276
2277 Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2278 }
2279
2280 fn block_number(&self) -> U256 {
2281 self.block_number.into()
2282 }
2283
2284 fn block_hash(&self, block_number: U256) -> Option<H256> {
2285 self.block_hash(block_number)
2286 }
2287
2288 fn block_author(&self) -> H160 {
2289 Contracts::<Self::T>::block_author()
2290 }
2291
2292 fn gas_limit(&self) -> u64 {
2293 <Contracts<T>>::evm_block_gas_limit().saturated_into()
2294 }
2295
2296 fn chain_id(&self) -> u64 {
2297 <T as Config>::ChainId::get()
2298 }
2299
2300 fn gas_meter(&self) -> &FrameMeter<Self::T> {
2301 &self.top_frame().frame_meter
2302 }
2303
2304 #[inline]
2305 fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2306 &mut self.top_frame_mut().frame_meter
2307 }
2308
2309 fn frame_meter(&self) -> &FrameMeter<Self::T> {
2310 &self.top_frame().frame_meter
2311 }
2312
2313 #[inline]
2314 fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2315 &mut self.top_frame_mut().frame_meter
2316 }
2317
2318 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2319 secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2320 }
2321
2322 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2323 sp_io::crypto::sr25519_verify(
2324 &SR25519Signature::from(*signature),
2325 message,
2326 &SR25519Public::from(*pub_key),
2327 )
2328 }
2329
2330 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError> {
2331 Ok(ECDSAPublic::from(*pk)
2332 .to_eth_address()
2333 .or_else(|()| Err(Error::<T>::EcdsaRecoveryFailed))?)
2334 }
2335
2336 #[cfg(any(test, feature = "runtime-benchmarks"))]
2337 fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2338 self.top_frame_mut().contract_info()
2339 }
2340
2341 #[cfg(any(feature = "runtime-benchmarks", test))]
2342 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2343 &mut self.transient_storage
2344 }
2345
2346 fn is_read_only(&self) -> bool {
2347 self.top_frame().read_only
2348 }
2349
2350 fn is_delegate_call(&self) -> bool {
2351 self.top_frame().delegate.is_some()
2352 }
2353
2354 fn last_frame_output(&self) -> &ExecReturnValue {
2355 &self.top_frame().last_frame_output
2356 }
2357
2358 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2359 &mut self.top_frame_mut().last_frame_output
2360 }
2361
2362 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2363 let len = buf.len();
2364 if len == 0 {
2365 return;
2366 }
2367
2368 let code_hash = self.code_hash(address);
2369 let code = crate::PristineCode::<T>::get(&code_hash).unwrap_or_default();
2370
2371 let len = len.min(code.len().saturating_sub(code_offset));
2372 if len > 0 {
2373 buf[..len].copy_from_slice(&code[code_offset..code_offset + len]);
2374 }
2375
2376 buf[len..].fill(0);
2377 }
2378
2379 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2380 ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2381 let parent = self.frames_mut().nth(1).ok_or_else(|| Error::<T>::ContractNotFound)?;
2382 ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2383 ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2384
2385 let info = parent.contract_info();
2386 let trie_id = info.trie_id.clone();
2387 let code_hash = info.code_hash;
2388 let contract_address = T::AddressMapper::to_address(&parent.account_id);
2389 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2390
2391 let parent_account_id = parent.account_id.clone();
2392
2393 Self::transfer(
2395 &self.origin,
2396 &parent_account_id,
2397 &beneficiary,
2398 <Contracts<T>>::evm_balance(&contract_address),
2399 Preservation::Preserve,
2400 &mut top_frame_mut!(self).frame_meter,
2401 &self.exec_config,
2402 )?;
2403
2404 let args = TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: false };
2406 self.top_frame_mut().contracts_to_be_destroyed.insert(parent_account_id, args);
2407
2408 Ok(())
2409 }
2410
2411 fn effective_gas_price(&self) -> U256 {
2412 self.exec_config
2413 .effective_gas_price
2414 .unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2415 }
2416
2417 fn gas_left(&self) -> u64 {
2418 let frame = self.top_frame();
2419
2420 frame.frame_meter.eth_gas_left().unwrap_or_default().saturated_into::<u64>()
2421 }
2422
2423 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2424 assert!(self.has_contract_info());
2425 self.top_frame_mut().contract_info().read(key)
2426 }
2427
2428 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2429 assert!(self.has_contract_info());
2430 self.top_frame_mut().contract_info().size(key.into())
2431 }
2432
2433 fn set_storage(
2434 &mut self,
2435 key: &Key,
2436 value: Option<Vec<u8>>,
2437 take_old: bool,
2438 ) -> Result<WriteOutcome, DispatchError> {
2439 assert!(self.has_contract_info());
2440 let frame = self.top_frame_mut();
2441 frame.contract_info.get(&frame.account_id).write(
2442 key.into(),
2443 value,
2444 Some(&mut frame.frame_meter),
2445 take_old,
2446 )
2447 }
2448
2449 fn charge_storage(&mut self, diff: &Diff) -> DispatchResult {
2450 assert!(self.has_contract_info());
2451 self.top_frame_mut().frame_meter.record_contract_storage_changes(diff)
2452 }
2453}
2454
2455pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2457 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2458}
2459
2460#[cfg(feature = "runtime-benchmarks")]
2461pub fn bench_do_terminate<T: Config>(
2462 transaction_meter: &mut TransactionMeter<T>,
2463 exec_config: &ExecConfig<T>,
2464 contract_account: &T::AccountId,
2465 origin: &Origin<T>,
2466 beneficiary: T::AccountId,
2467 trie_id: TrieId,
2468 code_hash: H256,
2469 only_if_same_tx: bool,
2470) -> Result<(), DispatchError> {
2471 Stack::<T, crate::ContractBlob<T>>::do_terminate(
2472 transaction_meter,
2473 exec_config,
2474 contract_account,
2475 origin,
2476 &TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx },
2477 )
2478}
2479
2480mod sealing {
2481 use super::*;
2482
2483 pub trait Sealed {}
2484 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2485
2486 #[cfg(test)]
2487 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2488}