1use crate::{
19 address::{self, AddressMapper},
20 gas::GasMeter,
21 limits,
22 precompiles::{All as AllPrecompiles, Instance as PrecompileInstance, Precompiles},
23 primitives::{BumpNonce, ExecReturnValue, StorageDeposit},
24 runtime_decl_for_revive_api::{Decode, Encode, RuntimeDebugNoBound, TypeInfo},
25 storage::{self, meter::Diff, AccountIdOrAddress, WriteOutcome},
26 tracing::if_tracing,
27 transient_storage::TransientStorage,
28 AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf,
29 CodeRemoved, Config, ContractInfo, Error, Event, ImmutableData, ImmutableDataOf,
30 Pallet as Contracts, RuntimeCosts, LOG_TARGET,
31};
32use alloc::vec::Vec;
33use core::{fmt::Debug, marker::PhantomData, mem};
34use frame_support::{
35 crypto::ecdsa::ECDSAExt,
36 dispatch::DispatchResult,
37 storage::{with_transaction, TransactionOutcome},
38 traits::{
39 fungible::{Inspect, Mutate},
40 tokens::{Fortitude, Precision, Preservation},
41 Time,
42 },
43 weights::Weight,
44 Blake2_128Concat, BoundedVec, StorageHasher,
45};
46use frame_system::{
47 pallet_prelude::{BlockNumberFor, OriginFor},
48 Pallet as System, RawOrigin,
49};
50use sp_core::{
51 ecdsa::Public as ECDSAPublic,
52 sr25519::{Public as SR25519Public, Signature as SR25519Signature},
53 ConstU32, Get, H160, H256, U256,
54};
55use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
56use sp_runtime::{
57 traits::{BadOrigin, Bounded, Convert, Saturating, Zero},
58 DispatchError, SaturatedConversion,
59};
60
61#[cfg(test)]
62mod tests;
63
64#[cfg(test)]
65pub mod mock_ext;
66
67pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
68pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
69pub type ExecResult = Result<ExecReturnValue, ExecError>;
70
71type VarSizedKey = BoundedVec<u8, ConstU32<{ limits::STORAGE_KEY_BYTES }>>;
73
74const 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";
75
76pub const EMPTY_CODE_HASH: H256 =
78 H256(sp_core::hex2array!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
79
80#[derive(Debug)]
82pub enum Key {
83 Fix([u8; 32]),
85 Var(VarSizedKey),
87}
88
89impl Key {
90 pub fn unhashed(&self) -> &[u8] {
92 match self {
93 Key::Fix(v) => v.as_ref(),
94 Key::Var(v) => v.as_ref(),
95 }
96 }
97
98 pub fn hash(&self) -> Vec<u8> {
100 match self {
101 Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
102 Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
103 }
104 }
105
106 pub fn from_fixed(v: [u8; 32]) -> Self {
107 Self::Fix(v)
108 }
109
110 pub fn try_from_var(v: Vec<u8>) -> Result<Self, ()> {
111 VarSizedKey::try_from(v).map(Self::Var).map_err(|_| ())
112 }
113}
114
115#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
121pub enum ErrorOrigin {
122 Caller,
127 Callee,
129}
130
131#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
133pub struct ExecError {
134 pub error: DispatchError,
136 pub origin: ErrorOrigin,
138}
139
140impl<T: Into<DispatchError>> From<T> for ExecError {
141 fn from(error: T) -> Self {
142 Self { error: error.into(), origin: ErrorOrigin::Caller }
143 }
144}
145
146#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebugNoBound)]
148pub enum Origin<T: Config> {
149 Root,
150 Signed(T::AccountId),
151}
152
153impl<T: Config> Origin<T> {
154 pub fn from_account_id(account_id: T::AccountId) -> Self {
156 Origin::Signed(account_id)
157 }
158
159 pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
161 match o.into() {
162 Ok(RawOrigin::Root) => Ok(Self::Root),
163 Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
164 _ => Err(BadOrigin.into()),
165 }
166 }
167
168 pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
170 match self {
171 Origin::Signed(id) => Ok(id),
172 Origin::Root => Err(DispatchError::RootNotAllowed),
173 }
174 }
175
176 fn ensure_mapped(&self) -> DispatchResult {
181 match self {
182 Self::Root => Ok(()),
183 Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()),
184 Self::Signed(_) => Err(<Error<T>>::AccountUnmapped.into()),
185 }
186 }
187}
188pub trait Ext: PrecompileWithInfoExt {
190 fn delegate_call(
194 &mut self,
195 gas_limit: Weight,
196 deposit_limit: U256,
197 address: H160,
198 input_data: Vec<u8>,
199 ) -> Result<(), ExecError>;
200
201 fn terminate(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError>;
209
210 #[allow(dead_code)]
212 fn own_code_hash(&mut self) -> &H256;
213
214 fn set_code_hash(&mut self, hash: H256) -> Result<CodeRemoved, DispatchError>;
217
218 fn immutable_data_len(&mut self) -> u32;
223
224 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError>;
228
229 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError>;
235}
236
237pub trait PrecompileWithInfoExt: PrecompileExt {
239 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
244
245 fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
250
251 fn set_storage(
254 &mut self,
255 key: &Key,
256 value: Option<Vec<u8>>,
257 take_old: bool,
258 ) -> Result<WriteOutcome, DispatchError>;
259
260 fn charge_storage(&mut self, diff: &Diff);
262
263 fn instantiate(
269 &mut self,
270 gas_limit: Weight,
271 deposit_limit: U256,
272 code: Code,
273 value: U256,
274 input_data: Vec<u8>,
275 salt: Option<&[u8; 32]>,
276 ) -> Result<H160, ExecError>;
277}
278
279pub trait PrecompileExt: sealing::Sealed {
281 type T: Config;
282
283 fn charge(&mut self, weight: Weight) -> Result<crate::gas::ChargedAmount, DispatchError> {
285 self.gas_meter_mut().charge(RuntimeCosts::Precompile(weight))
286 }
287
288 fn adjust_gas(&mut self, charged: crate::gas::ChargedAmount, actual_weight: Weight) {
289 self.gas_meter_mut()
290 .adjust_gas(charged, RuntimeCosts::Precompile(actual_weight));
291 }
292
293 fn call(
295 &mut self,
296 gas_limit: Weight,
297 deposit_limit: U256,
298 to: &H160,
299 value: U256,
300 input_data: Vec<u8>,
301 allows_reentry: bool,
302 read_only: bool,
303 ) -> Result<(), ExecError>;
304
305 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>>;
310
311 fn get_transient_storage_size(&self, key: &Key) -> Option<u32>;
316
317 fn set_transient_storage(
320 &mut self,
321 key: &Key,
322 value: Option<Vec<u8>>,
323 take_old: bool,
324 ) -> Result<WriteOutcome, DispatchError>;
325
326 fn caller(&self) -> Origin<Self::T>;
328
329 fn caller_of_caller(&self) -> Origin<Self::T>;
331
332 fn origin(&self) -> &Origin<Self::T>;
334
335 fn to_account_id(&self, address: &H160) -> AccountIdOf<Self::T>;
337
338 fn code_hash(&self, address: &H160) -> H256;
341
342 fn code_size(&self, address: &H160) -> u64;
344
345 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool;
347
348 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool;
350
351 fn account_id(&self) -> &AccountIdOf<Self::T>;
353
354 fn address(&self) -> H160 {
356 <Self::T as Config>::AddressMapper::to_address(self.account_id())
357 }
358
359 fn balance(&self) -> U256;
363
364 fn balance_of(&self, address: &H160) -> U256;
368
369 fn value_transferred(&self) -> U256;
371
372 fn now(&self) -> U256;
374
375 fn minimum_balance(&self) -> U256;
377
378 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
382
383 fn block_number(&self) -> U256;
385
386 fn block_hash(&self, block_number: U256) -> Option<H256>;
389
390 fn block_author(&self) -> Option<H160>;
392
393 fn gas_limit(&self) -> u64;
395
396 fn chain_id(&self) -> u64;
398
399 fn max_value_size(&self) -> u32;
401
402 fn get_weight_price(&self, weight: Weight) -> U256;
404
405 fn gas_meter(&self) -> &GasMeter<Self::T>;
407
408 fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T>;
410
411 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
413
414 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
416
417 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()>;
419
420 #[cfg(any(test, feature = "runtime-benchmarks"))]
422 fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
423
424 #[cfg(any(feature = "runtime-benchmarks", test))]
428 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
429
430 fn is_read_only(&self) -> bool;
432
433 fn last_frame_output(&self) -> &ExecReturnValue;
435
436 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
438
439 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize);
447}
448
449#[derive(
451 Copy,
452 Clone,
453 PartialEq,
454 Eq,
455 sp_core::RuntimeDebug,
456 codec::Decode,
457 codec::Encode,
458 codec::MaxEncodedLen,
459 scale_info::TypeInfo,
460)]
461pub enum ExportedFunction {
462 Constructor,
464 Call,
466}
467
468pub trait Executable<T: Config>: Sized {
473 fn from_storage(code_hash: H256, gas_meter: &mut GasMeter<T>) -> Result<Self, DispatchError>;
478
479 fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
481
482 fn execute<E: Ext<T = T>>(
492 self,
493 ext: &mut E,
494 function: ExportedFunction,
495 input_data: Vec<u8>,
496 ) -> ExecResult;
497
498 fn code_info(&self) -> &CodeInfo<T>;
500
501 fn code(&self) -> &[u8];
503
504 fn code_hash(&self) -> &H256;
506}
507
508pub struct Stack<'a, T: Config, E> {
514 origin: Origin<T>,
523 gas_meter: &'a mut GasMeter<T>,
525 storage_meter: &'a mut storage::meter::Meter<T>,
527 timestamp: MomentOf<T>,
529 block_number: BlockNumberFor<T>,
531 frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
534 first_frame: Frame<T>,
536 transient_storage: TransientStorage<T>,
538 skip_transfer: bool,
541 _phantom: PhantomData<E>,
543}
544
545struct Frame<T: Config> {
550 account_id: T::AccountId,
552 contract_info: CachedContract<T>,
554 value_transferred: U256,
556 entry_point: ExportedFunction,
558 nested_gas: GasMeter<T>,
560 nested_storage: storage::meter::NestedMeter<T>,
562 allows_reentry: bool,
564 read_only: bool,
566 delegate: Option<DelegateInfo<T>>,
569 last_frame_output: ExecReturnValue,
571}
572
573struct DelegateInfo<T: Config> {
576 pub caller: Origin<T>,
578 pub callee: H160,
580}
581
582enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
584 Executable(E),
586 Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
588}
589
590impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
591 fn as_executable(&self) -> Option<&E> {
592 if let Self::Executable(executable) = self {
593 Some(executable)
594 } else {
595 None
596 }
597 }
598
599 fn is_pvm(&self) -> bool {
600 match self {
601 Self::Executable(e) => e.code_info().is_pvm(),
602 _ => false,
603 }
604 }
605
606 fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
607 if let Self::Precompile { instance, .. } = self {
608 Some(instance)
609 } else {
610 None
611 }
612 }
613
614 #[cfg(any(feature = "runtime-benchmarks", test))]
615 fn into_executable(self) -> Option<E> {
616 if let Self::Executable(executable) = self {
617 Some(executable)
618 } else {
619 None
620 }
621 }
622}
623
624enum FrameArgs<'a, T: Config, E> {
628 Call {
629 dest: T::AccountId,
631 cached_info: Option<ContractInfo<T>>,
633 delegated_call: Option<DelegateInfo<T>>,
637 },
638 Instantiate {
639 sender: T::AccountId,
641 executable: E,
643 salt: Option<&'a [u8; 32]>,
645 input_data: &'a [u8],
647 },
648}
649
650enum CachedContract<T: Config> {
652 Cached(ContractInfo<T>),
654 Invalidated,
658 Terminated,
663 None,
665}
666
667impl<T: Config> Frame<T> {
668 fn contract_info(&mut self) -> &mut ContractInfo<T> {
670 self.contract_info.get(&self.account_id)
671 }
672
673 fn terminate(&mut self) -> ContractInfo<T> {
680 self.contract_info.terminate(&self.account_id)
681 }
682}
683
684macro_rules! get_cached_or_panic_after_load {
688 ($c:expr) => {{
689 if let CachedContract::Cached(contract) = $c {
690 contract
691 } else {
692 panic!(
693 "It is impossible to remove a contract that is on the call stack;\
694 See implementations of terminate;\
695 Therefore fetching a contract will never fail while using an account id
696 that is currently active on the call stack;\
697 qed"
698 );
699 }
700 }};
701}
702
703macro_rules! top_frame {
708 ($stack:expr) => {
709 $stack.frames.last().unwrap_or(&$stack.first_frame)
710 };
711}
712
713macro_rules! top_frame_mut {
718 ($stack:expr) => {
719 $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
720 };
721}
722
723impl<T: Config> CachedContract<T> {
724 fn into_contract(self) -> Option<ContractInfo<T>> {
726 if let CachedContract::Cached(contract) = self {
727 Some(contract)
728 } else {
729 None
730 }
731 }
732
733 fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
735 if let CachedContract::Cached(contract) = self {
736 Some(contract)
737 } else {
738 None
739 }
740 }
741
742 fn load(&mut self, account_id: &T::AccountId) {
744 if let CachedContract::Invalidated = self {
745 if let Some(contract) =
746 AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
747 {
748 *self = CachedContract::Cached(contract);
749 }
750 }
751 }
752
753 fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
755 self.load(account_id);
756 get_cached_or_panic_after_load!(self)
757 }
758
759 fn terminate(&mut self, account_id: &T::AccountId) -> ContractInfo<T> {
761 self.load(account_id);
762 get_cached_or_panic_after_load!(mem::replace(self, Self::Terminated))
763 }
764
765 fn invalidate(&mut self) {
767 if matches!(self, CachedContract::Cached(_)) {
768 *self = CachedContract::Invalidated;
769 }
770 }
771}
772
773impl<'a, T, E> Stack<'a, T, E>
774where
775 T: Config,
776 BalanceOf<T>: Into<U256> + TryFrom<U256>,
777 MomentOf<T>: Into<U256>,
778 E: Executable<T>,
779 T::Hash: frame_support::traits::IsType<H256>,
780{
781 pub fn run_call(
787 origin: Origin<T>,
788 dest: H160,
789 gas_meter: &mut GasMeter<T>,
790 storage_meter: &mut storage::meter::Meter<T>,
791 value: U256,
792 input_data: Vec<u8>,
793 skip_transfer: bool,
794 ) -> ExecResult {
795 let dest = T::AddressMapper::to_account_id(&dest);
796 if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
797 FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
798 origin.clone(),
799 gas_meter,
800 storage_meter,
801 value,
802 skip_transfer,
803 )? {
804 stack
805 .run(executable, input_data, BumpNonce::Yes)
806 .map(|_| stack.first_frame.last_frame_output)
807 } else {
808 if_tracing(|t| {
809 t.enter_child_span(
810 origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
811 T::AddressMapper::to_address(&dest),
812 false,
813 false,
814 value,
815 &input_data,
816 Weight::zero(),
817 );
818 });
819
820 let result = Self::transfer_from_origin(&origin, &origin, &dest, value, storage_meter);
821
822 if_tracing(|t| match result {
823 Ok(ref output) => t.exit_child_span(&output, Weight::zero()),
824 Err(e) => t.exit_child_span_with_error(e.error.into(), Weight::zero()),
825 });
826
827 result
828 }
829 }
830
831 pub fn run_instantiate(
837 origin: T::AccountId,
838 executable: E,
839 gas_meter: &mut GasMeter<T>,
840 storage_meter: &mut storage::meter::Meter<T>,
841 value: U256,
842 input_data: Vec<u8>,
843 salt: Option<&[u8; 32]>,
844 skip_transfer: bool,
845 bump_nonce: BumpNonce,
846 ) -> Result<(H160, ExecReturnValue), ExecError> {
847 let deployer = T::AddressMapper::to_address(&origin);
848 let (mut stack, executable) = Stack::<'_, T, E>::new(
849 FrameArgs::Instantiate {
850 sender: origin.clone(),
851 executable,
852 salt,
853 input_data: input_data.as_ref(),
854 },
855 Origin::from_account_id(origin),
856 gas_meter,
857 storage_meter,
858 value,
859 skip_transfer,
860 )?
861 .expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
862 let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
863 let result = stack
864 .run(executable, input_data, bump_nonce)
865 .map(|_| (address, stack.first_frame.last_frame_output));
866 if let Ok((contract, ref output)) = result {
867 if !output.did_revert() {
868 Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract });
869 }
870 }
871 result
872 }
873
874 #[cfg(any(feature = "runtime-benchmarks", test))]
875 pub fn bench_new_call(
876 dest: H160,
877 origin: Origin<T>,
878 gas_meter: &'a mut GasMeter<T>,
879 storage_meter: &'a mut storage::meter::Meter<T>,
880 value: BalanceOf<T>,
881 ) -> (Self, E) {
882 let call = Self::new(
883 FrameArgs::Call {
884 dest: T::AddressMapper::to_account_id(&dest),
885 cached_info: None,
886 delegated_call: None,
887 },
888 origin,
889 gas_meter,
890 storage_meter,
891 value.into(),
892 false,
893 )
894 .unwrap()
895 .unwrap();
896 (call.0, call.1.into_executable().unwrap())
897 }
898
899 fn new(
904 args: FrameArgs<T, E>,
905 origin: Origin<T>,
906 gas_meter: &'a mut GasMeter<T>,
907 storage_meter: &'a mut storage::meter::Meter<T>,
908 value: U256,
909 skip_transfer: bool,
910 ) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
911 origin.ensure_mapped()?;
912 let Some((first_frame, executable)) = Self::new_frame(
913 args,
914 value,
915 gas_meter,
916 Weight::max_value(),
917 storage_meter,
918 BalanceOf::<T>::max_value(),
919 false,
920 true,
921 )?
922 else {
923 return Ok(None);
924 };
925
926 let stack = Self {
927 origin,
928 gas_meter,
929 storage_meter,
930 timestamp: T::Time::now(),
931 block_number: <frame_system::Pallet<T>>::block_number(),
932 first_frame,
933 frames: Default::default(),
934 transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
935 skip_transfer,
936 _phantom: Default::default(),
937 };
938
939 Ok(Some((stack, executable)))
940 }
941
942 fn new_frame<S: storage::meter::State + Default + Debug>(
947 frame_args: FrameArgs<T, E>,
948 value_transferred: U256,
949 gas_meter: &mut GasMeter<T>,
950 gas_limit: Weight,
951 storage_meter: &mut storage::meter::GenericMeter<T, S>,
952 deposit_limit: BalanceOf<T>,
953 read_only: bool,
954 origin_is_caller: bool,
955 ) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
956 let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
957 FrameArgs::Call { dest, cached_info, delegated_call } => {
958 let address = T::AddressMapper::to_address(&dest);
959 let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
960
961 let mut contract = match (cached_info, &precompile) {
964 (Some(info), _) => CachedContract::Cached(info),
965 (None, None) =>
966 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
967 CachedContract::Cached(info)
968 } else {
969 return Ok(None);
970 },
971 (None, Some(precompile)) if precompile.has_contract_info() => {
972 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
973 CachedContract::Cached(info)
974 } else {
975 let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
976 CachedContract::Cached(info)
977 }
978 },
979 (None, Some(_)) => CachedContract::None,
980 };
981
982 let executable = if let Some(delegated_call) = &delegated_call {
984 if let Some(precompile) =
985 <AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
986 {
987 ExecutableOrPrecompile::Precompile {
988 instance: precompile,
989 _phantom: Default::default(),
990 }
991 } else {
992 let Some(info) = AccountInfo::<T>::load_contract(&delegated_call.callee)
993 else {
994 return Ok(None);
995 };
996 let executable = E::from_storage(info.code_hash, gas_meter)?;
997 ExecutableOrPrecompile::Executable(executable)
998 }
999 } else {
1000 if let Some(precompile) = precompile {
1001 ExecutableOrPrecompile::Precompile {
1002 instance: precompile,
1003 _phantom: Default::default(),
1004 }
1005 } else {
1006 let executable = E::from_storage(
1007 contract
1008 .as_contract()
1009 .expect("When not a precompile the contract was loaded above; qed")
1010 .code_hash,
1011 gas_meter,
1012 )?;
1013 ExecutableOrPrecompile::Executable(executable)
1014 }
1015 };
1016
1017 (dest, contract, executable, delegated_call, ExportedFunction::Call)
1018 },
1019 FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1020 let deployer = T::AddressMapper::to_address(&sender);
1021 let account_nonce = <System<T>>::account_nonce(&sender);
1022 let address = if let Some(salt) = salt {
1023 address::create2(&deployer, executable.code(), input_data, salt)
1024 } else {
1025 use sp_runtime::Saturating;
1026 address::create1(
1027 &deployer,
1028 if origin_is_caller {
1031 account_nonce.saturating_sub(1u32.into()).saturated_into()
1032 } else {
1033 account_nonce.saturated_into()
1034 },
1035 )
1036 };
1037 let contract = ContractInfo::new(
1038 &address,
1039 <System<T>>::account_nonce(&sender),
1040 *executable.code_hash(),
1041 )?;
1042 (
1043 T::AddressMapper::to_fallback_account_id(&address),
1044 CachedContract::Cached(contract),
1045 ExecutableOrPrecompile::Executable(executable),
1046 None,
1047 ExportedFunction::Constructor,
1048 )
1049 },
1050 };
1051
1052 let frame = Frame {
1053 delegate,
1054 value_transferred,
1055 contract_info,
1056 account_id,
1057 entry_point,
1058 nested_gas: gas_meter.nested(gas_limit),
1059 nested_storage: storage_meter.nested(deposit_limit),
1060 allows_reentry: true,
1061 read_only,
1062 last_frame_output: Default::default(),
1063 };
1064
1065 Ok(Some((frame, executable)))
1066 }
1067
1068 fn push_frame(
1070 &mut self,
1071 frame_args: FrameArgs<T, E>,
1072 value_transferred: U256,
1073 gas_limit: Weight,
1074 deposit_limit: BalanceOf<T>,
1075 read_only: bool,
1076 ) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1077 if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1078 return Err(Error::<T>::MaxCallDepthReached.into());
1079 }
1080
1081 let frame = self.top_frame();
1086 if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1087 (&frame.contract_info, frame.entry_point)
1088 {
1089 AccountInfo::<T>::insert_contract(
1090 &T::AddressMapper::to_address(&frame.account_id),
1091 contract.clone(),
1092 );
1093 }
1094
1095 let frame = top_frame_mut!(self);
1096 let nested_gas = &mut frame.nested_gas;
1097 let nested_storage = &mut frame.nested_storage;
1098 if let Some((frame, executable)) = Self::new_frame(
1099 frame_args,
1100 value_transferred,
1101 nested_gas,
1102 gas_limit,
1103 nested_storage,
1104 deposit_limit,
1105 read_only,
1106 false,
1107 )? {
1108 self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1109 Ok(Some(executable))
1110 } else {
1111 Ok(None)
1112 }
1113 }
1114
1115 fn run(
1119 &mut self,
1120 executable: ExecutableOrPrecompile<T, E, Self>,
1121 input_data: Vec<u8>,
1122 bump_nonce: BumpNonce,
1123 ) -> Result<(), ExecError> {
1124 let frame = self.top_frame();
1125 let entry_point = frame.entry_point;
1126 let is_pvm = executable.is_pvm();
1127
1128 if_tracing(|tracer| {
1129 tracer.enter_child_span(
1130 self.caller().account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
1131 T::AddressMapper::to_address(&frame.account_id),
1132 frame.delegate.is_some(),
1133 frame.read_only,
1134 frame.value_transferred,
1135 &input_data,
1136 frame.nested_gas.gas_left(),
1137 );
1138 });
1139
1140 let frames_len = self.frames.len();
1144 if let Some(caller_frame) = match frames_len {
1145 0 => None,
1146 1 => Some(&mut self.first_frame.last_frame_output),
1147 _ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1148 } {
1149 *caller_frame = Default::default();
1150 }
1151
1152 self.transient_storage.start_transaction();
1153
1154 let do_transaction = || -> ExecResult {
1155 let caller = self.caller();
1156 let skip_transfer = self.skip_transfer;
1157 let frame = top_frame_mut!(self);
1158 let account_id = &frame.account_id.clone();
1159
1160 if u32::try_from(input_data.len())
1161 .map(|len| len > limits::CALLDATA_BYTES)
1162 .unwrap_or(true)
1163 {
1164 Err(<Error<T>>::CallDataTooLarge)?;
1165 }
1166
1167 if entry_point == ExportedFunction::Constructor {
1170 let origin = &self.origin.account_id()?;
1173
1174 let ed = <Contracts<T>>::min_balance();
1175 frame.nested_storage.record_charge(&StorageDeposit::Charge(ed))?;
1176 if self.skip_transfer {
1177 T::Currency::set_balance(account_id, ed);
1178 } else {
1179 T::Currency::transfer(origin, account_id, ed, Preservation::Preserve)
1180 .map_err(|_| <Error<T>>::StorageDepositNotEnoughFunds)?;
1181 }
1182
1183 <System<T>>::inc_consumers(account_id)?;
1188
1189 <System<T>>::inc_account_nonce(account_id);
1191
1192 if matches!(bump_nonce, BumpNonce::Yes) {
1193 <System<T>>::inc_account_nonce(caller.account_id()?);
1196 }
1197 if is_pvm {
1199 <CodeInfo<T>>::increment_refcount(
1200 *executable
1201 .as_executable()
1202 .expect("Precompiles cannot be instantiated; qed")
1203 .code_hash(),
1204 )?;
1205 }
1206 }
1207
1208 if frame.delegate.is_none() {
1212 Self::transfer_from_origin(
1213 &self.origin,
1214 &caller,
1215 account_id,
1216 frame.value_transferred,
1217 &mut frame.nested_storage,
1218 )?;
1219 }
1220
1221 if let Some(precompile) = executable.as_precompile() {
1228 if precompile.has_contract_info() &&
1229 frame.delegate.is_none() &&
1230 !<System<T>>::account_exists(account_id)
1231 {
1232 T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1235 <System<T>>::inc_consumers(account_id)?;
1237 }
1238 }
1239
1240 let mut code_deposit = executable
1241 .as_executable()
1242 .map(|exec| exec.code_info().deposit())
1243 .unwrap_or_default();
1244
1245 let mut output = match executable {
1246 ExecutableOrPrecompile::Executable(executable) =>
1247 executable.execute(self, entry_point, input_data),
1248 ExecutableOrPrecompile::Precompile { instance, .. } =>
1249 instance.call(input_data, self),
1250 }
1251 .and_then(|output| {
1252 if u32::try_from(output.data.len())
1253 .map(|len| len > limits::CALLDATA_BYTES)
1254 .unwrap_or(true)
1255 {
1256 Err(<Error<T>>::ReturnDataTooLarge)?;
1257 }
1258 Ok(output)
1259 })
1260 .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1261
1262 if output.did_revert() {
1264 return Ok(output);
1265 }
1266
1267 let frame = if entry_point == ExportedFunction::Constructor {
1270 let origin = self.origin.account_id()?.clone();
1271 let frame = self.top_frame_mut();
1272 let contract_info = frame.contract_info();
1273 if !is_pvm {
1276 let data = if crate::tracing::if_tracing(|_| {}).is_none() {
1278 core::mem::replace(&mut output.data, Default::default())
1279 } else {
1280 output.data.clone()
1281 };
1282
1283 let mut module = crate::ContractBlob::<T>::from_evm_runtime_code(data, origin)?;
1284 module.store_code(skip_transfer)?;
1285 code_deposit = module.code_info().deposit();
1286 contract_info.code_hash = *module.code_hash();
1287
1288 <CodeInfo<T>>::increment_refcount(contract_info.code_hash)?;
1289 }
1290
1291 let deposit = contract_info.update_base_deposit(code_deposit);
1292 frame
1293 .nested_storage
1294 .charge_deposit(frame.account_id.clone(), StorageDeposit::Charge(deposit));
1295 frame
1296 } else {
1297 self.top_frame_mut()
1298 };
1299
1300 let contract = frame.contract_info.as_contract();
1304 frame
1305 .nested_storage
1306 .enforce_limit(contract)
1307 .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1308
1309 Ok(output)
1310 };
1311
1312 let transaction_outcome =
1319 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1320 let output = do_transaction();
1321 match &output {
1322 Ok(result) if !result.did_revert() =>
1323 TransactionOutcome::Commit(Ok((true, output))),
1324 _ => TransactionOutcome::Rollback(Ok((false, output))),
1325 }
1326 });
1327
1328 let (success, output) = match transaction_outcome {
1329 Ok((success, output)) => {
1331 if_tracing(|tracer| {
1332 let gas_consumed = top_frame!(self).nested_gas.gas_consumed();
1333 match &output {
1334 Ok(output) => tracer.exit_child_span(&output, gas_consumed),
1335 Err(e) => tracer.exit_child_span_with_error(e.error.into(), gas_consumed),
1336 }
1337 });
1338
1339 (success, output)
1340 },
1341 Err(error) => {
1344 if_tracing(|tracer| {
1345 let gas_consumed = top_frame!(self).nested_gas.gas_consumed();
1346 tracer.exit_child_span_with_error(error.into(), gas_consumed);
1347 });
1348
1349 (false, Err(error.into()))
1350 },
1351 };
1352
1353 if success {
1354 self.transient_storage.commit_transaction();
1355 } else {
1356 self.transient_storage.rollback_transaction();
1357 }
1358
1359 log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1360
1361 self.pop_frame(success);
1362 output.map(|output| {
1363 self.top_frame_mut().last_frame_output = output;
1364 })
1365 }
1366
1367 fn pop_frame(&mut self, persist: bool) {
1372 let frame = self.frames.pop();
1376
1377 if let Some(mut frame) = frame {
1380 let account_id = &frame.account_id;
1381 let prev = top_frame_mut!(self);
1382
1383 prev.nested_gas.absorb_nested(frame.nested_gas);
1384
1385 if !persist {
1387 return;
1388 }
1389
1390 frame.contract_info.load(account_id);
1395 let mut contract = frame.contract_info.into_contract();
1396 prev.nested_storage.absorb(frame.nested_storage, account_id, contract.as_mut());
1397
1398 if let Some(contract) = contract {
1400 if prev.account_id == *account_id {
1405 prev.contract_info = CachedContract::Cached(contract);
1406 return;
1407 }
1408
1409 AccountInfo::<T>::insert_contract(
1415 &T::AddressMapper::to_address(account_id),
1416 contract,
1417 );
1418 if let Some(f) = self.frames_mut().skip(1).find(|f| f.account_id == *account_id) {
1419 f.contract_info.invalidate();
1420 }
1421 }
1422 } else {
1423 self.gas_meter.absorb_nested(mem::take(&mut self.first_frame.nested_gas));
1425 if !persist {
1426 return;
1427 }
1428 let mut contract = self.first_frame.contract_info.as_contract();
1429 self.storage_meter.absorb(
1430 mem::take(&mut self.first_frame.nested_storage),
1431 &self.first_frame.account_id,
1432 contract.as_deref_mut(),
1433 );
1434 if let Some(contract) = contract {
1435 AccountInfo::<T>::insert_contract(
1436 &T::AddressMapper::to_address(&self.first_frame.account_id),
1437 contract.clone(),
1438 );
1439 }
1440 }
1441 }
1442
1443 fn transfer<S: storage::meter::State + Default + Debug>(
1456 origin: &Origin<T>,
1457 from: &T::AccountId,
1458 to: &T::AccountId,
1459 value: U256,
1460 storage_meter: &mut storage::meter::GenericMeter<T, S>,
1461 ) -> DispatchResult {
1462 fn transfer_with_dust<T: Config>(
1463 from: &AccountIdOf<T>,
1464 to: &AccountIdOf<T>,
1465 value: BalanceWithDust<BalanceOf<T>>,
1466 ) -> DispatchResult {
1467 let (value, dust) = value.deconstruct();
1468
1469 fn transfer_balance<T: Config>(
1470 from: &AccountIdOf<T>,
1471 to: &AccountIdOf<T>,
1472 value: BalanceOf<T>,
1473 ) -> DispatchResult {
1474 T::Currency::transfer(from, to, value, Preservation::Preserve)
1475 .map_err(|err| {
1476 log::debug!(target: crate::LOG_TARGET, "Transfer failed: from {from:?} to {to:?} (value: ${value:?}). Err: {err:?}");
1477 Error::<T>::TransferFailed
1478 })?;
1479 Ok(())
1480 }
1481
1482 fn transfer_dust<T: Config>(
1483 from: &mut AccountInfo<T>,
1484 to: &mut AccountInfo<T>,
1485 dust: u32,
1486 ) -> DispatchResult {
1487 from.dust =
1488 from.dust.checked_sub(dust).ok_or_else(|| Error::<T>::TransferFailed)?;
1489 to.dust = to.dust.checked_add(dust).ok_or_else(|| Error::<T>::TransferFailed)?;
1490 Ok(())
1491 }
1492
1493 if dust.is_zero() {
1494 return transfer_balance::<T>(from, to, value)
1495 }
1496
1497 let from_addr = <T::AddressMapper as AddressMapper<T>>::to_address(from);
1498 let mut from_info = AccountInfoOf::<T>::get(&from_addr).unwrap_or_default();
1499
1500 let to_addr = <T::AddressMapper as AddressMapper<T>>::to_address(to);
1501 let mut to_info = AccountInfoOf::<T>::get(&to_addr).unwrap_or_default();
1502
1503 let plank = T::NativeToEthRatio::get();
1504
1505 if from_info.dust < dust {
1506 T::Currency::burn_from(
1507 from,
1508 1u32.into(),
1509 Preservation::Preserve,
1510 Precision::Exact,
1511 Fortitude::Polite,
1512 )
1513 .map_err(|err| {
1514 log::debug!(target: crate::LOG_TARGET, "Burning 1 plank from {from:?} failed. Err: {err:?}");
1515 Error::<T>::TransferFailed
1516 })?;
1517
1518 from_info.dust =
1519 from_info.dust.checked_add(plank).ok_or_else(|| Error::<T>::TransferFailed)?;
1520 }
1521
1522 transfer_balance::<T>(from, to, value)?;
1523 transfer_dust::<T>(&mut from_info, &mut to_info, dust)?;
1524
1525 if to_info.dust >= plank {
1526 T::Currency::mint_into(to, 1u32.into())?;
1527 to_info.dust =
1528 to_info.dust.checked_sub(plank).ok_or_else(|| Error::<T>::TransferFailed)?;
1529 }
1530
1531 AccountInfoOf::<T>::set(&from_addr, Some(from_info));
1532 AccountInfoOf::<T>::set(&to_addr, Some(to_info));
1533
1534 Ok(())
1535 }
1536
1537 let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1538 .map_err(|_| <Error<T>>::BalanceConversionFailed)?;
1539 if value.is_zero() {
1540 return Ok(());
1541 }
1542
1543 if <System<T>>::account_exists(to) {
1544 return transfer_with_dust::<T>(from, to, value)
1545 }
1546
1547 let origin = origin.account_id()?;
1548 let ed = <T as Config>::Currency::minimum_balance();
1549 with_transaction(|| -> TransactionOutcome<DispatchResult> {
1550 match storage_meter
1551 .record_charge(&StorageDeposit::Charge(ed))
1552 .and_then(|_| {
1553 T::Currency::transfer(origin, to, ed, Preservation::Preserve)
1554 .map_err(|_| Error::<T>::StorageDepositNotEnoughFunds.into())
1555 })
1556 .and_then(|_| transfer_with_dust::<T>(from, to, value))
1557 {
1558 Ok(_) => TransactionOutcome::Commit(Ok(())),
1559 Err(err) => TransactionOutcome::Rollback(Err(err)),
1560 }
1561 })
1562 }
1563
1564 fn transfer_from_origin<S: storage::meter::State + Default + Debug>(
1566 origin: &Origin<T>,
1567 from: &Origin<T>,
1568 to: &T::AccountId,
1569 value: U256,
1570 storage_meter: &mut storage::meter::GenericMeter<T, S>,
1571 ) -> ExecResult {
1572 let from = match from {
1575 Origin::Signed(caller) => caller,
1576 Origin::Root if value.is_zero() => return Ok(Default::default()),
1577 Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1578 };
1579 Self::transfer(origin, from, to, value, storage_meter)
1580 .map(|_| Default::default())
1581 .map_err(Into::into)
1582 }
1583
1584 fn top_frame(&self) -> &Frame<T> {
1586 top_frame!(self)
1587 }
1588
1589 fn top_frame_mut(&mut self) -> &mut Frame<T> {
1591 top_frame_mut!(self)
1592 }
1593
1594 fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1598 core::iter::once(&self.first_frame).chain(&self.frames).rev()
1599 }
1600
1601 fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1603 core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1604 }
1605
1606 fn is_recursive(&self) -> bool {
1608 let account_id = &self.top_frame().account_id;
1609 self.frames().skip(1).any(|f| &f.account_id == account_id)
1610 }
1611
1612 fn allows_reentry(&self, id: &T::AccountId) -> bool {
1614 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1615 }
1616
1617 fn account_balance(&self, who: &T::AccountId) -> U256 {
1619 let balance = AccountInfo::<T>::balance(AccountIdOrAddress::AccountId(who.clone()));
1620 crate::Pallet::<T>::convert_native_to_evm(balance)
1621 }
1622
1623 #[cfg(feature = "runtime-benchmarks")]
1626 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
1627 self.top_frame_mut().entry_point = export;
1628 }
1629
1630 #[cfg(feature = "runtime-benchmarks")]
1631 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
1632 self.block_number = block_number;
1633 }
1634
1635 fn block_hash(&self, block_number: U256) -> Option<H256> {
1636 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
1637 return None;
1638 };
1639 if block_number >= self.block_number {
1640 return None;
1641 }
1642 if block_number < self.block_number.saturating_sub(256u32.into()) {
1643 return None;
1644 }
1645 Some(System::<T>::block_hash(&block_number).into())
1646 }
1647}
1648
1649impl<'a, T, E> Ext for Stack<'a, T, E>
1650where
1651 T: Config,
1652 E: Executable<T>,
1653 BalanceOf<T>: Into<U256> + TryFrom<U256>,
1654 MomentOf<T>: Into<U256>,
1655 T::Hash: frame_support::traits::IsType<H256>,
1656{
1657 fn delegate_call(
1658 &mut self,
1659 gas_limit: Weight,
1660 deposit_limit: U256,
1661 address: H160,
1662 input_data: Vec<u8>,
1663 ) -> Result<(), ExecError> {
1664 *self.last_frame_output_mut() = Default::default();
1667
1668 let top_frame = self.top_frame_mut();
1669 let contract_info = top_frame.contract_info().clone();
1670 let account_id = top_frame.account_id.clone();
1671 let value = top_frame.value_transferred;
1672 if let Some(executable) = self.push_frame(
1673 FrameArgs::Call {
1674 dest: account_id,
1675 cached_info: Some(contract_info),
1676 delegated_call: Some(DelegateInfo {
1677 caller: self.caller().clone(),
1678 callee: address,
1679 }),
1680 },
1681 value,
1682 gas_limit,
1683 deposit_limit.saturated_into::<BalanceOf<T>>(),
1684 self.is_read_only(),
1685 )? {
1686 self.run(executable, input_data, BumpNonce::Yes)
1687 } else {
1688 Ok(())
1690 }
1691 }
1692
1693 fn terminate(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
1694 if self.is_recursive() {
1695 return Err(Error::<T>::TerminatedWhileReentrant.into());
1696 }
1697 let frame = self.top_frame_mut();
1698 if frame.entry_point == ExportedFunction::Constructor {
1699 return Err(Error::<T>::TerminatedInConstructor.into());
1700 }
1701 let info = frame.terminate();
1702 let beneficiary_account = T::AddressMapper::to_account_id(beneficiary);
1703 frame.nested_storage.terminate(&info, beneficiary_account);
1704
1705 info.queue_trie_for_deletion();
1706 let account_address = T::AddressMapper::to_address(&frame.account_id);
1707 AccountInfoOf::<T>::remove(&account_address);
1708 ImmutableDataOf::<T>::remove(&account_address);
1709 let removed = <CodeInfo<T>>::decrement_refcount(info.code_hash)?;
1710
1711 Ok(removed)
1712 }
1713
1714 fn own_code_hash(&mut self) -> &H256 {
1715 &self.top_frame_mut().contract_info().code_hash
1716 }
1717
1718 fn set_code_hash(&mut self, hash: H256) -> Result<CodeRemoved, DispatchError> {
1734 let frame = top_frame_mut!(self);
1735
1736 let info = frame.contract_info();
1737
1738 let prev_hash = info.code_hash;
1739 info.code_hash = hash;
1740
1741 let code_info = CodeInfoOf::<T>::get(hash).ok_or(Error::<T>::CodeNotFound)?;
1742
1743 let old_base_deposit = info.storage_base_deposit();
1744 let new_base_deposit = info.update_base_deposit(code_info.deposit());
1745 let deposit = StorageDeposit::Charge(new_base_deposit)
1746 .saturating_sub(&StorageDeposit::Charge(old_base_deposit));
1747
1748 frame.nested_storage.charge_deposit(frame.account_id.clone(), deposit);
1749
1750 <CodeInfo<T>>::increment_refcount(hash)?;
1751 let removed = <CodeInfo<T>>::decrement_refcount(prev_hash)?;
1752 Ok(removed)
1753 }
1754
1755 fn immutable_data_len(&mut self) -> u32 {
1756 self.top_frame_mut().contract_info().immutable_data_len()
1757 }
1758
1759 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
1760 if self.top_frame().entry_point == ExportedFunction::Constructor {
1761 return Err(Error::<T>::InvalidImmutableAccess.into());
1762 }
1763
1764 let address = self
1766 .top_frame()
1767 .delegate
1768 .as_ref()
1769 .map(|d| d.callee)
1770 .unwrap_or(T::AddressMapper::to_address(self.account_id()));
1771 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
1772 }
1773
1774 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
1775 let frame = self.top_frame_mut();
1776 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
1777 return Err(Error::<T>::InvalidImmutableAccess.into());
1778 }
1779 frame.contract_info().set_immutable_data_len(data.len() as u32);
1780 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
1781 Ok(())
1782 }
1783}
1784
1785impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
1786where
1787 T: Config,
1788 E: Executable<T>,
1789 BalanceOf<T>: Into<U256> + TryFrom<U256>,
1790 MomentOf<T>: Into<U256>,
1791 T::Hash: frame_support::traits::IsType<H256>,
1792{
1793 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
1794 self.top_frame_mut().contract_info().read(key)
1795 }
1796
1797 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
1798 self.top_frame_mut().contract_info().size(key.into())
1799 }
1800
1801 fn set_storage(
1802 &mut self,
1803 key: &Key,
1804 value: Option<Vec<u8>>,
1805 take_old: bool,
1806 ) -> Result<WriteOutcome, DispatchError> {
1807 let frame = self.top_frame_mut();
1808 frame.contract_info.get(&frame.account_id).write(
1809 key.into(),
1810 value,
1811 Some(&mut frame.nested_storage),
1812 take_old,
1813 )
1814 }
1815
1816 fn charge_storage(&mut self, diff: &Diff) {
1817 self.top_frame_mut().nested_storage.charge(diff)
1818 }
1819
1820 fn instantiate(
1821 &mut self,
1822 gas_limit: Weight,
1823 deposit_limit: U256,
1824 code: Code,
1825 value: U256,
1826 input_data: Vec<u8>,
1827 salt: Option<&[u8; 32]>,
1828 ) -> Result<H160, ExecError> {
1829 *self.last_frame_output_mut() = Default::default();
1832
1833 let sender = self.top_frame().account_id.clone();
1834 let executable = {
1835 let executable = match &code {
1836 Code::Upload(bytecode) => {
1837 if !T::AllowEVMBytecode::get() {
1838 return Err(<Error<T>>::CodeRejected.into());
1839 }
1840 E::from_evm_init_code(bytecode.clone(), sender.clone())?
1841 },
1842 Code::Existing(hash) => E::from_storage(*hash, self.gas_meter_mut())?,
1843 };
1844 self.push_frame(
1845 FrameArgs::Instantiate {
1846 sender,
1847 executable,
1848 salt,
1849 input_data: input_data.as_ref(),
1850 },
1851 value,
1852 gas_limit,
1853 deposit_limit.saturated_into::<BalanceOf<T>>(),
1854 self.is_read_only(),
1855 )?
1856 };
1857 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
1858 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
1859 if_tracing(|t| t.instantiate_code(&code, salt));
1860 self.run(executable, input_data, BumpNonce::Yes).map(|_| address)
1861 }
1862}
1863
1864impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
1865where
1866 T: Config,
1867 E: Executable<T>,
1868 BalanceOf<T>: Into<U256> + TryFrom<U256>,
1869 MomentOf<T>: Into<U256>,
1870 T::Hash: frame_support::traits::IsType<H256>,
1871{
1872 type T = T;
1873
1874 fn call(
1875 &mut self,
1876 gas_limit: Weight,
1877 deposit_limit: U256,
1878 dest_addr: &H160,
1879 value: U256,
1880 input_data: Vec<u8>,
1881 allows_reentry: bool,
1882 read_only: bool,
1883 ) -> Result<(), ExecError> {
1884 self.top_frame_mut().allows_reentry = allows_reentry;
1888
1889 *self.last_frame_output_mut() = Default::default();
1892
1893 let try_call = || {
1894 let is_read_only = read_only || self.is_read_only();
1896
1897 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
1899 T::AddressMapper::to_fallback_account_id(dest_addr)
1900 } else {
1901 T::AddressMapper::to_account_id(dest_addr)
1902 };
1903
1904 if !self.allows_reentry(&dest) {
1905 return Err(<Error<T>>::ReentranceDenied.into());
1906 }
1907
1908 let cached_info = self
1912 .frames()
1913 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
1914 .and_then(|f| match &f.contract_info {
1915 CachedContract::Cached(contract) => Some(contract.clone()),
1916 _ => None,
1917 });
1918
1919 if let Some(executable) = self.push_frame(
1920 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
1921 value,
1922 gas_limit,
1923 deposit_limit.saturated_into::<BalanceOf<T>>(),
1924 is_read_only,
1925 )? {
1926 self.run(executable, input_data, BumpNonce::Yes)
1927 } else {
1928 if_tracing(|t| {
1929 t.enter_child_span(
1930 T::AddressMapper::to_address(self.account_id()),
1931 T::AddressMapper::to_address(&dest),
1932 false,
1933 is_read_only,
1934 value,
1935 &input_data,
1936 Weight::zero(),
1937 );
1938 });
1939
1940 let result = if is_read_only && value.is_zero() {
1941 Ok(Default::default())
1942 } else if is_read_only {
1943 Err(Error::<T>::StateChangeDenied.into())
1944 } else {
1945 let account_id = self.account_id().clone();
1946 let frame = top_frame_mut!(self);
1947 Self::transfer_from_origin(
1948 &self.origin,
1949 &Origin::from_account_id(account_id),
1950 &dest,
1951 value,
1952 &mut frame.nested_storage,
1953 )
1954 };
1955
1956 if_tracing(|t| match result {
1957 Ok(ref output) => t.exit_child_span(&output, Weight::zero()),
1958 Err(e) => t.exit_child_span_with_error(e.error.into(), Weight::zero()),
1959 });
1960
1961 result.map(|_| ())
1962 }
1963 };
1964
1965 let result = try_call();
1967
1968 self.top_frame_mut().allows_reentry = true;
1970
1971 result
1972 }
1973
1974 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
1975 self.transient_storage.read(self.account_id(), key)
1976 }
1977
1978 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
1979 self.transient_storage
1980 .read(self.account_id(), key)
1981 .map(|value| value.len() as _)
1982 }
1983
1984 fn set_transient_storage(
1985 &mut self,
1986 key: &Key,
1987 value: Option<Vec<u8>>,
1988 take_old: bool,
1989 ) -> Result<WriteOutcome, DispatchError> {
1990 let account_id = self.account_id().clone();
1991 self.transient_storage.write(&account_id, key, value, take_old)
1992 }
1993
1994 fn account_id(&self) -> &T::AccountId {
1995 &self.top_frame().account_id
1996 }
1997
1998 fn caller(&self) -> Origin<T> {
1999 if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
2000 caller.clone()
2001 } else {
2002 self.frames()
2003 .nth(1)
2004 .map(|f| Origin::from_account_id(f.account_id.clone()))
2005 .unwrap_or(self.origin.clone())
2006 }
2007 }
2008
2009 fn caller_of_caller(&self) -> Origin<T> {
2010 let caller_of_caller_frame = match self.frames().nth(2) {
2012 None => return self.origin.clone(),
2013 Some(frame) => frame,
2014 };
2015 if let Some(DelegateInfo { caller, .. }) = &caller_of_caller_frame.delegate {
2016 caller.clone()
2017 } else {
2018 Origin::from_account_id(caller_of_caller_frame.account_id.clone())
2019 }
2020 }
2021
2022 fn origin(&self) -> &Origin<T> {
2023 &self.origin
2024 }
2025
2026 fn to_account_id(&self, address: &H160) -> T::AccountId {
2027 T::AddressMapper::to_account_id(address)
2028 }
2029
2030 fn code_hash(&self, address: &H160) -> H256 {
2031 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()) {
2032 return sp_io::hashing::keccak_256(code).into()
2033 }
2034
2035 <AccountInfo<T>>::load_contract(&address)
2036 .map(|contract| contract.code_hash)
2037 .unwrap_or_else(|| {
2038 if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) {
2039 return EMPTY_CODE_HASH;
2040 }
2041 H256::zero()
2042 })
2043 }
2044
2045 fn code_size(&self, address: &H160) -> u64 {
2046 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()) {
2047 return code.len() as u64
2048 }
2049
2050 <AccountInfo<T>>::load_contract(&address)
2051 .and_then(|contract| CodeInfoOf::<T>::get(contract.code_hash))
2052 .map(|info| info.code_len())
2053 .unwrap_or_default()
2054 }
2055
2056 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2057 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2058 self.origin == caller
2059 }
2060
2061 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2062 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2064 }
2065
2066 fn balance(&self) -> U256 {
2067 self.account_balance(&self.top_frame().account_id)
2068 }
2069
2070 fn balance_of(&self, address: &H160) -> U256 {
2071 let balance =
2072 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2073 if_tracing(|tracer| {
2074 tracer.balance_read(address, balance);
2075 });
2076 balance
2077 }
2078
2079 fn value_transferred(&self) -> U256 {
2080 self.top_frame().value_transferred.into()
2081 }
2082
2083 fn now(&self) -> U256 {
2084 (self.timestamp / 1000u32.into()).into()
2085 }
2086
2087 fn minimum_balance(&self) -> U256 {
2088 let min = T::Currency::minimum_balance();
2089 crate::Pallet::<T>::convert_native_to_evm(min)
2090 }
2091
2092 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2093 let contract = T::AddressMapper::to_address(self.account_id());
2094 if_tracing(|tracer| {
2095 tracer.log_event(contract, &topics, &data);
2096 });
2097 Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2098 }
2099
2100 fn block_number(&self) -> U256 {
2101 self.block_number.into()
2102 }
2103
2104 fn block_hash(&self, block_number: U256) -> Option<H256> {
2105 self.block_hash(block_number)
2106 }
2107
2108 fn block_author(&self) -> Option<H160> {
2109 Contracts::<Self::T>::block_author()
2110 }
2111
2112 fn gas_limit(&self) -> u64 {
2113 <T as frame_system::Config>::BlockWeights::get().max_block.ref_time()
2114 }
2115
2116 fn chain_id(&self) -> u64 {
2117 <T as Config>::ChainId::get()
2118 }
2119
2120 fn max_value_size(&self) -> u32 {
2121 limits::PAYLOAD_BYTES
2122 }
2123
2124 fn get_weight_price(&self, weight: Weight) -> U256 {
2125 T::WeightPrice::convert(weight).into()
2126 }
2127
2128 fn gas_meter(&self) -> &GasMeter<Self::T> {
2129 &self.top_frame().nested_gas
2130 }
2131
2132 fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T> {
2133 &mut self.top_frame_mut().nested_gas
2134 }
2135
2136 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2137 secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2138 }
2139
2140 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2141 sp_io::crypto::sr25519_verify(
2142 &SR25519Signature::from(*signature),
2143 message,
2144 &SR25519Public::from(*pub_key),
2145 )
2146 }
2147
2148 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()> {
2149 ECDSAPublic::from(*pk).to_eth_address()
2150 }
2151
2152 #[cfg(any(test, feature = "runtime-benchmarks"))]
2153 fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2154 self.top_frame_mut().contract_info()
2155 }
2156
2157 #[cfg(any(feature = "runtime-benchmarks", test))]
2158 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2159 &mut self.transient_storage
2160 }
2161
2162 fn is_read_only(&self) -> bool {
2163 self.top_frame().read_only
2164 }
2165
2166 fn last_frame_output(&self) -> &ExecReturnValue {
2167 &self.top_frame().last_frame_output
2168 }
2169
2170 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2171 &mut self.top_frame_mut().last_frame_output
2172 }
2173
2174 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2175 let len = buf.len();
2176 if len == 0 {
2177 return;
2178 }
2179
2180 let code_hash = self.code_hash(address);
2181 let code = crate::PristineCode::<T>::get(&code_hash).unwrap_or_default();
2182
2183 let len = len.min(code.len().saturating_sub(code_offset));
2184 if len > 0 {
2185 buf[..len].copy_from_slice(&code[code_offset..code_offset + len]);
2186 }
2187
2188 buf[len..].fill(0);
2189 }
2190}
2191
2192pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool
2194where
2195 BalanceOf<T>: Into<U256> + TryFrom<U256>,
2196 MomentOf<T>: Into<U256>,
2197 T::Hash: frame_support::traits::IsType<H256>,
2198{
2199 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2200}
2201
2202mod sealing {
2203 use super::*;
2204
2205 pub trait Sealed {}
2206 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2207
2208 #[cfg(test)]
2209 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2210}