1use crate::{
19 address::{self, AddressMapper},
20 evm::{
21 block_storage,
22 fees::{Combinator, InfoT},
23 transfer_with_dust,
24 },
25 gas::GasMeter,
26 limits,
27 precompiles::{All as AllPrecompiles, Instance as PrecompileInstance, Precompiles},
28 primitives::{ExecConfig, ExecReturnValue, StorageDeposit},
29 runtime_decl_for_revive_api::{Decode, Encode, RuntimeDebugNoBound, TypeInfo},
30 storage::{self, meter::Diff, AccountIdOrAddress, WriteOutcome},
31 tracing::if_tracing,
32 transient_storage::TransientStorage,
33 AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf,
34 CodeRemoved, Config, ContractInfo, Error, Event, HoldReason, ImmutableData, ImmutableDataOf,
35 Pezpallet as Contracts, RuntimeCosts, TrieId, LOG_TARGET,
36};
37use alloc::{
38 collections::{BTreeMap, BTreeSet},
39 vec::Vec,
40};
41use core::{cmp, fmt::Debug, marker::PhantomData, mem, ops::ControlFlow};
42use pezframe_support::{
43 crypto::ecdsa::ECDSAExt,
44 dispatch::DispatchResult,
45 ensure,
46 storage::{with_transaction, TransactionOutcome},
47 traits::{
48 fungible::{Inspect, Mutate},
49 tokens::Preservation,
50 Time,
51 },
52 weights::Weight,
53 Blake2_128Concat, BoundedVec, StorageHasher,
54};
55use pezframe_system::{
56 pezpallet_prelude::{BlockNumberFor, OriginFor},
57 Pezpallet as System, RawOrigin,
58};
59use pezsp_core::{
60 ecdsa::Public as ECDSAPublic,
61 sr25519::{Public as SR25519Public, Signature as SR25519Signature},
62 ConstU32, Get, H160, H256, U256,
63};
64use pezsp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
65use pezsp_runtime::{
66 traits::{BadOrigin, Bounded, Saturating, TrailingZeroInput},
67 DispatchError, SaturatedConversion,
68};
69
70#[cfg(test)]
71mod tests;
72
73#[cfg(test)]
74pub mod mock_ext;
75
76pub type AccountIdOf<T> = <T as pezframe_system::Config>::AccountId;
77pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
78pub type ExecResult = Result<ExecReturnValue, ExecError>;
79
80type VarSizedKey = BoundedVec<u8, ConstU32<{ limits::STORAGE_KEY_BYTES }>>;
82
83const 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";
84
85pub const EMPTY_CODE_HASH: H256 = H256(pezsp_core::hex2array!(
87 "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
88));
89
90#[derive(Debug)]
92pub enum Key {
93 Fix([u8; 32]),
95 Var(VarSizedKey),
97}
98
99impl Key {
100 pub fn unhashed(&self) -> &[u8] {
102 match self {
103 Key::Fix(v) => v.as_ref(),
104 Key::Var(v) => v.as_ref(),
105 }
106 }
107
108 pub fn hash(&self) -> Vec<u8> {
110 match self {
111 Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
112 Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
113 }
114 }
115
116 pub fn from_fixed(v: [u8; 32]) -> Self {
117 Self::Fix(v)
118 }
119
120 pub fn try_from_var(v: Vec<u8>) -> Result<Self, ()> {
121 VarSizedKey::try_from(v).map(Self::Var).map_err(|_| ())
122 }
123}
124
125#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
131pub enum ErrorOrigin {
132 Caller,
137 Callee,
139}
140
141#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
143pub struct ExecError {
144 pub error: DispatchError,
146 pub origin: ErrorOrigin,
148}
149
150impl<T: Into<DispatchError>> From<T> for ExecError {
151 fn from(error: T) -> Self {
152 Self { error: error.into(), origin: ErrorOrigin::Caller }
153 }
154}
155
156#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebugNoBound)]
158pub enum Origin<T: Config> {
159 Root,
160 Signed(T::AccountId),
161}
162
163impl<T: Config> Origin<T> {
164 pub fn from_account_id(account_id: T::AccountId) -> Self {
166 Origin::Signed(account_id)
167 }
168
169 pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
171 match o.into() {
172 Ok(RawOrigin::Root) => Ok(Self::Root),
173 Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
174 _ => Err(BadOrigin.into()),
175 }
176 }
177
178 pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
180 match self {
181 Origin::Signed(id) => Ok(id),
182 Origin::Root => Err(DispatchError::RootNotAllowed),
183 }
184 }
185
186 fn ensure_mapped(&self) -> DispatchResult {
191 match self {
192 Self::Root => Ok(()),
193 Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()),
194 Self::Signed(_) => Err(<Error<T>>::AccountUnmapped.into()),
195 }
196 }
197}
198pub trait Ext: PrecompileWithInfoExt {
200 fn delegate_call(
204 &mut self,
205 gas_limit: Weight,
206 deposit_limit: U256,
207 address: H160,
208 input_data: Vec<u8>,
209 ) -> Result<(), ExecError>;
210
211 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError>;
218
219 #[allow(dead_code)]
221 fn own_code_hash(&mut self) -> &H256;
222
223 fn set_code_hash(&mut self, hash: H256) -> Result<CodeRemoved, DispatchError>;
226
227 fn immutable_data_len(&mut self) -> u32;
232
233 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError>;
237
238 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError>;
244}
245
246pub trait PrecompileWithInfoExt: PrecompileExt {
248 fn instantiate(
254 &mut self,
255 gas_limit: Weight,
256 deposit_limit: U256,
257 code: Code,
258 value: U256,
259 input_data: Vec<u8>,
260 salt: Option<&[u8; 32]>,
261 ) -> Result<H160, ExecError>;
262}
263
264pub trait PrecompileExt: sealing::Sealed {
266 type T: Config;
267
268 fn charge(&mut self, weight: Weight) -> Result<crate::gas::ChargedAmount, DispatchError> {
270 self.gas_meter_mut().charge(RuntimeCosts::Precompile(weight))
271 }
272
273 fn adjust_gas(&mut self, charged: crate::gas::ChargedAmount, actual_weight: Weight) {
274 self.gas_meter_mut()
275 .adjust_gas(charged, RuntimeCosts::Precompile(actual_weight));
276 }
277
278 fn charge_or_halt<Tok: crate::gas::Token<Self::T>>(
280 &mut self,
281 token: Tok,
282 ) -> ControlFlow<crate::vm::evm::Halt, crate::gas::ChargedAmount> {
283 self.gas_meter_mut().charge_or_halt(token)
284 }
285
286 fn call(
288 &mut self,
289 gas_limit: Weight,
290 deposit_limit: U256,
291 to: &H160,
292 value: U256,
293 input_data: Vec<u8>,
294 allows_reentry: bool,
295 read_only: bool,
296 ) -> Result<(), ExecError>;
297
298 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>>;
303
304 fn get_transient_storage_size(&self, key: &Key) -> Option<u32>;
309
310 fn set_transient_storage(
313 &mut self,
314 key: &Key,
315 value: Option<Vec<u8>>,
316 take_old: bool,
317 ) -> Result<WriteOutcome, DispatchError>;
318
319 fn caller(&self) -> Origin<Self::T>;
321
322 fn caller_of_caller(&self) -> Origin<Self::T>;
324
325 fn origin(&self) -> &Origin<Self::T>;
327
328 fn to_account_id(&self, address: &H160) -> AccountIdOf<Self::T>;
330
331 fn code_hash(&self, address: &H160) -> H256;
334
335 fn code_size(&self, address: &H160) -> u64;
337
338 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool;
340
341 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool;
343
344 fn account_id(&self) -> &AccountIdOf<Self::T>;
346
347 fn address(&self) -> H160 {
349 <Self::T as Config>::AddressMapper::to_address(self.account_id())
350 }
351
352 fn balance(&self) -> U256;
356
357 fn balance_of(&self, address: &H160) -> U256;
361
362 fn value_transferred(&self) -> U256;
364
365 fn now(&self) -> U256;
367
368 fn minimum_balance(&self) -> U256;
370
371 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
375
376 fn block_number(&self) -> U256;
378
379 fn block_hash(&self, block_number: U256) -> Option<H256>;
382
383 fn block_author(&self) -> H160;
385
386 fn gas_limit(&self) -> u64;
388
389 fn chain_id(&self) -> u64;
391
392 fn gas_meter(&self) -> &GasMeter<Self::T>;
394
395 fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T>;
397
398 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
400
401 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
403
404 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()>;
406
407 #[cfg(any(test, feature = "runtime-benchmarks"))]
409 fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
410
411 #[cfg(any(feature = "runtime-benchmarks", test))]
415 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
416
417 fn is_read_only(&self) -> bool;
419
420 fn is_delegate_call(&self) -> bool;
422
423 fn last_frame_output(&self) -> &ExecReturnValue;
425
426 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
428
429 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize);
437
438 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError>;
447
448 fn effective_gas_price(&self) -> U256;
450
451 fn gas_left(&self) -> u64;
453 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
458
459 fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
464
465 fn set_storage(
468 &mut self,
469 key: &Key,
470 value: Option<Vec<u8>>,
471 take_old: bool,
472 ) -> Result<WriteOutcome, DispatchError>;
473
474 fn charge_storage(&mut self, diff: &Diff);
476}
477
478#[derive(
480 Copy,
481 Clone,
482 PartialEq,
483 Eq,
484 pezsp_core::RuntimeDebug,
485 codec::Decode,
486 codec::Encode,
487 codec::MaxEncodedLen,
488 scale_info::TypeInfo,
489)]
490pub enum ExportedFunction {
491 Constructor,
493 Call,
495}
496
497pub trait Executable<T: Config>: Sized {
502 fn from_storage(code_hash: H256, gas_meter: &mut GasMeter<T>) -> Result<Self, DispatchError>;
507
508 fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
510
511 fn execute<E: Ext<T = T>>(
521 self,
522 ext: &mut E,
523 function: ExportedFunction,
524 input_data: Vec<u8>,
525 ) -> ExecResult;
526
527 fn code_info(&self) -> &CodeInfo<T>;
529
530 fn code(&self) -> &[u8];
532
533 fn code_hash(&self) -> &H256;
535}
536
537pub struct Stack<'a, T: Config, E> {
543 origin: Origin<T>,
552 gas_meter: &'a mut GasMeter<T>,
554 storage_meter: &'a mut storage::meter::Meter<T>,
556 timestamp: MomentOf<T>,
558 block_number: BlockNumberFor<T>,
560 frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
563 first_frame: Frame<T>,
565 transient_storage: TransientStorage<T>,
567 exec_config: &'a ExecConfig<T>,
569 _phantom: PhantomData<E>,
571}
572
573struct Frame<T: Config> {
578 account_id: T::AccountId,
580 contract_info: CachedContract<T>,
582 value_transferred: U256,
584 entry_point: ExportedFunction,
586 nested_gas: GasMeter<T>,
588 nested_storage: storage::meter::NestedMeter<T>,
590 allows_reentry: bool,
592 read_only: bool,
594 delegate: Option<DelegateInfo<T>>,
597 last_frame_output: ExecReturnValue,
599 contracts_created: BTreeSet<T::AccountId>,
601 contracts_to_be_destroyed: BTreeMap<T::AccountId, TerminateArgs<T>>,
603}
604
605#[derive(Clone)]
608pub struct DelegateInfo<T: Config> {
609 pub caller: Origin<T>,
611 pub callee: H160,
613}
614
615enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
617 Executable(E),
619 Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
621}
622
623impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
624 fn as_executable(&self) -> Option<&E> {
625 if let Self::Executable(executable) = self {
626 Some(executable)
627 } else {
628 None
629 }
630 }
631
632 fn is_pvm(&self) -> bool {
633 match self {
634 Self::Executable(e) => e.code_info().is_pvm(),
635 _ => false,
636 }
637 }
638
639 fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
640 if let Self::Precompile { instance, .. } = self {
641 Some(instance)
642 } else {
643 None
644 }
645 }
646
647 #[cfg(any(feature = "runtime-benchmarks", test))]
648 fn into_executable(self) -> Option<E> {
649 if let Self::Executable(executable) = self {
650 Some(executable)
651 } else {
652 None
653 }
654 }
655}
656
657enum FrameArgs<'a, T: Config, E> {
661 Call {
662 dest: T::AccountId,
664 cached_info: Option<ContractInfo<T>>,
666 delegated_call: Option<DelegateInfo<T>>,
670 },
671 Instantiate {
672 sender: T::AccountId,
674 executable: E,
676 salt: Option<&'a [u8; 32]>,
678 input_data: &'a [u8],
680 },
681}
682
683enum CachedContract<T: Config> {
685 Cached(ContractInfo<T>),
687 Invalidated,
691 None,
693}
694
695impl<T: Config> Frame<T> {
696 fn contract_info(&mut self) -> &mut ContractInfo<T> {
698 self.contract_info.get(&self.account_id)
699 }
700}
701
702macro_rules! get_cached_or_panic_after_load {
706 ($c:expr) => {{
707 if let CachedContract::Cached(contract) = $c {
708 contract
709 } else {
710 panic!(
711 "It is impossible to remove a contract that is on the call stack;\
712 See implementations of terminate;\
713 Therefore fetching a contract will never fail while using an account id
714 that is currently active on the call stack;\
715 qed"
716 );
717 }
718 }};
719}
720
721macro_rules! top_frame {
726 ($stack:expr) => {
727 $stack.frames.last().unwrap_or(&$stack.first_frame)
728 };
729}
730
731macro_rules! top_frame_mut {
736 ($stack:expr) => {
737 $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
738 };
739}
740
741impl<T: Config> CachedContract<T> {
742 fn into_contract(self) -> Option<ContractInfo<T>> {
744 if let CachedContract::Cached(contract) = self {
745 Some(contract)
746 } else {
747 None
748 }
749 }
750
751 fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
753 if let CachedContract::Cached(contract) = self {
754 Some(contract)
755 } else {
756 None
757 }
758 }
759
760 fn load(&mut self, account_id: &T::AccountId) {
762 if let CachedContract::Invalidated = self {
763 if let Some(contract) =
764 AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
765 {
766 *self = CachedContract::Cached(contract);
767 }
768 }
769 }
770
771 fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
773 self.load(account_id);
774 get_cached_or_panic_after_load!(self)
775 }
776
777 fn invalidate(&mut self) {
779 if matches!(self, CachedContract::Cached(_)) {
780 *self = CachedContract::Invalidated;
781 }
782 }
783}
784
785impl<'a, T, E> Stack<'a, T, E>
786where
787 T: Config,
788 E: Executable<T>,
789{
790 pub fn run_call(
796 origin: Origin<T>,
797 dest: H160,
798 gas_meter: &mut GasMeter<T>,
799 storage_meter: &mut storage::meter::Meter<T>,
800 value: U256,
801 input_data: Vec<u8>,
802 exec_config: &ExecConfig<T>,
803 ) -> ExecResult {
804 let dest = T::AddressMapper::to_account_id(&dest);
805 if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
806 FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
807 origin.clone(),
808 gas_meter,
809 storage_meter,
810 value,
811 exec_config,
812 &input_data,
813 )? {
814 stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
815 } else {
816 if_tracing(|t| {
817 t.enter_child_span(
818 origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
819 T::AddressMapper::to_address(&dest),
820 false,
821 false,
822 value,
823 &input_data,
824 Weight::zero(),
825 );
826 });
827
828 let result = if let Some(mock_answer) =
829 exec_config.mock_handler.as_ref().and_then(|handler| {
830 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
831 }) {
832 Ok(mock_answer)
833 } else {
834 Self::transfer_from_origin(
835 &origin,
836 &origin,
837 &dest,
838 value,
839 storage_meter,
840 exec_config,
841 )
842 };
843
844 if_tracing(|t| match result {
845 Ok(ref output) => t.exit_child_span(&output, Weight::zero()),
846 Err(e) => t.exit_child_span_with_error(e.error.into(), Weight::zero()),
847 });
848
849 log::trace!(target: LOG_TARGET, "call finished with: {result:?}");
850
851 result
852 }
853 }
854
855 pub fn run_instantiate(
861 origin: T::AccountId,
862 executable: E,
863 gas_meter: &mut GasMeter<T>,
864 storage_meter: &mut storage::meter::Meter<T>,
865 value: U256,
866 input_data: Vec<u8>,
867 salt: Option<&[u8; 32]>,
868 exec_config: &ExecConfig<T>,
869 ) -> Result<(H160, ExecReturnValue), ExecError> {
870 let deployer = T::AddressMapper::to_address(&origin);
871 let (mut stack, executable) = Stack::<'_, T, E>::new(
872 FrameArgs::Instantiate {
873 sender: origin.clone(),
874 executable,
875 salt,
876 input_data: input_data.as_ref(),
877 },
878 Origin::from_account_id(origin),
879 gas_meter,
880 storage_meter,
881 value,
882 exec_config,
883 &input_data,
884 )?
885 .expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
886 let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
887 let result = stack
888 .run(executable, input_data)
889 .map(|_| (address, stack.first_frame.last_frame_output));
890 if let Ok((contract, ref output)) = result {
891 if !output.did_revert() {
892 Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract });
893 }
894 }
895 log::trace!(target: LOG_TARGET, "instantiate finished with: {result:?}");
896 result
897 }
898
899 #[cfg(any(feature = "runtime-benchmarks", test))]
900 pub fn bench_new_call(
901 dest: H160,
902 origin: Origin<T>,
903 gas_meter: &'a mut GasMeter<T>,
904 storage_meter: &'a mut storage::meter::Meter<T>,
905 value: BalanceOf<T>,
906 exec_config: &'a ExecConfig<T>,
907 ) -> (Self, E) {
908 let call = Self::new(
909 FrameArgs::Call {
910 dest: T::AddressMapper::to_account_id(&dest),
911 cached_info: None,
912 delegated_call: None,
913 },
914 origin,
915 gas_meter,
916 storage_meter,
917 value.into(),
918 exec_config,
919 &Default::default(),
920 )
921 .unwrap()
922 .unwrap();
923 (call.0, call.1.into_executable().unwrap())
924 }
925
926 fn new(
931 args: FrameArgs<T, E>,
932 origin: Origin<T>,
933 gas_meter: &'a mut GasMeter<T>,
934 storage_meter: &'a mut storage::meter::Meter<T>,
935 value: U256,
936 exec_config: &'a ExecConfig<T>,
937 input_data: &Vec<u8>,
938 ) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
939 origin.ensure_mapped()?;
940 let Some((first_frame, executable)) = Self::new_frame(
941 args,
942 value,
943 gas_meter,
944 Weight::max_value(),
945 storage_meter,
946 BalanceOf::<T>::max_value(),
947 false,
948 true,
949 input_data,
950 exec_config,
951 )?
952 else {
953 return Ok(None);
954 };
955
956 let mut timestamp = T::Time::now();
957 let mut block_number = <pezframe_system::Pezpallet<T>>::block_number();
958 if let Some(timestamp_override) =
960 exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override)
961 {
962 block_number = block_number.saturating_add(1u32.into());
963 let delta = 1000u32.into();
965 timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override);
966 }
967
968 let stack = Self {
969 origin,
970 gas_meter,
971 storage_meter,
972 timestamp,
973 block_number,
974 first_frame,
975 frames: Default::default(),
976 transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
977 exec_config,
978 _phantom: Default::default(),
979 };
980 Ok(Some((stack, executable)))
981 }
982
983 fn new_frame<S: storage::meter::State + Default + Debug>(
988 frame_args: FrameArgs<T, E>,
989 value_transferred: U256,
990 gas_meter: &mut GasMeter<T>,
991 gas_limit: Weight,
992 storage_meter: &mut storage::meter::GenericMeter<T, S>,
993 deposit_limit: BalanceOf<T>,
994 read_only: bool,
995 origin_is_caller: bool,
996 input_data: &[u8],
997 exec_config: &ExecConfig<T>,
998 ) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
999 let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
1000 FrameArgs::Call { dest, cached_info, delegated_call } => {
1001 let address = T::AddressMapper::to_address(&dest);
1002 let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
1003
1004 let mut contract = match (cached_info, &precompile) {
1007 (Some(info), _) => CachedContract::Cached(info),
1008 (None, None) => {
1009 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
1010 CachedContract::Cached(info)
1011 } else {
1012 return Ok(None);
1013 }
1014 },
1015 (None, Some(precompile)) if precompile.has_contract_info() => {
1016 log::trace!(target: LOG_TARGET, "found precompile for address {address:?}");
1017 if let Some(info) = AccountInfo::<T>::load_contract(&address) {
1018 CachedContract::Cached(info)
1019 } else {
1020 let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
1021 CachedContract::Cached(info)
1022 }
1023 },
1024 (None, Some(_)) => CachedContract::None,
1025 };
1026
1027 let delegated_call = delegated_call.or_else(|| {
1028 exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1029 mock_handler.mock_delegated_caller(address, input_data)
1030 })
1031 });
1032 let executable = if let Some(delegated_call) = &delegated_call {
1034 if let Some(precompile) =
1035 <AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
1036 {
1037 ExecutableOrPrecompile::Precompile {
1038 instance: precompile,
1039 _phantom: Default::default(),
1040 }
1041 } else {
1042 let Some(info) = AccountInfo::<T>::load_contract(&delegated_call.callee)
1043 else {
1044 return Ok(None);
1045 };
1046 let executable = E::from_storage(info.code_hash, gas_meter)?;
1047 ExecutableOrPrecompile::Executable(executable)
1048 }
1049 } else {
1050 if let Some(precompile) = precompile {
1051 ExecutableOrPrecompile::Precompile {
1052 instance: precompile,
1053 _phantom: Default::default(),
1054 }
1055 } else {
1056 let executable = E::from_storage(
1057 contract
1058 .as_contract()
1059 .expect("When not a precompile the contract was loaded above; qed")
1060 .code_hash,
1061 gas_meter,
1062 )?;
1063 ExecutableOrPrecompile::Executable(executable)
1064 }
1065 };
1066
1067 (dest, contract, executable, delegated_call, ExportedFunction::Call)
1068 },
1069 FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1070 let deployer = T::AddressMapper::to_address(&sender);
1071 let account_nonce = <System<T>>::account_nonce(&sender);
1072 let address = if let Some(salt) = salt {
1073 address::create2(&deployer, executable.code(), input_data, salt)
1074 } else {
1075 use pezsp_runtime::Saturating;
1076 address::create1(
1077 &deployer,
1078 if origin_is_caller {
1081 account_nonce.saturating_sub(1u32.into()).saturated_into()
1082 } else {
1083 account_nonce.saturated_into()
1084 },
1085 )
1086 };
1087 let contract = ContractInfo::new(
1088 &address,
1089 <System<T>>::account_nonce(&sender),
1090 *executable.code_hash(),
1091 )?;
1092 (
1093 T::AddressMapper::to_fallback_account_id(&address),
1094 CachedContract::Cached(contract),
1095 ExecutableOrPrecompile::Executable(executable),
1096 None,
1097 ExportedFunction::Constructor,
1098 )
1099 },
1100 };
1101
1102 let frame = Frame {
1103 delegate,
1104 value_transferred,
1105 contract_info,
1106 account_id,
1107 entry_point,
1108 nested_gas: gas_meter.nested(gas_limit),
1109 nested_storage: storage_meter.nested(deposit_limit),
1110 allows_reentry: true,
1111 read_only,
1112 last_frame_output: Default::default(),
1113 contracts_created: Default::default(),
1114 contracts_to_be_destroyed: Default::default(),
1115 };
1116
1117 Ok(Some((frame, executable)))
1118 }
1119
1120 fn push_frame(
1122 &mut self,
1123 frame_args: FrameArgs<T, E>,
1124 value_transferred: U256,
1125 gas_limit: Weight,
1126 deposit_limit: BalanceOf<T>,
1127 read_only: bool,
1128 input_data: &[u8],
1129 ) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1130 if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1131 return Err(Error::<T>::MaxCallDepthReached.into());
1132 }
1133
1134 let frame = self.top_frame();
1139 if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1140 (&frame.contract_info, frame.entry_point)
1141 {
1142 AccountInfo::<T>::insert_contract(
1143 &T::AddressMapper::to_address(&frame.account_id),
1144 contract.clone(),
1145 );
1146 }
1147
1148 let frame = top_frame_mut!(self);
1149 let nested_gas = &mut frame.nested_gas;
1150 let nested_storage = &mut frame.nested_storage;
1151 if let Some((frame, executable)) = Self::new_frame(
1152 frame_args,
1153 value_transferred,
1154 nested_gas,
1155 gas_limit,
1156 nested_storage,
1157 deposit_limit,
1158 read_only,
1159 false,
1160 input_data,
1161 self.exec_config,
1162 )? {
1163 self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1164 Ok(Some(executable))
1165 } else {
1166 Ok(None)
1167 }
1168 }
1169
1170 fn run(
1174 &mut self,
1175 executable: ExecutableOrPrecompile<T, E, Self>,
1176 input_data: Vec<u8>,
1177 ) -> Result<(), ExecError> {
1178 let frame = self.top_frame();
1179 let entry_point = frame.entry_point;
1180 let is_pvm = executable.is_pvm();
1181
1182 if_tracing(|tracer| {
1183 tracer.enter_child_span(
1184 self.caller().account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
1185 T::AddressMapper::to_address(&frame.account_id),
1186 frame.delegate.is_some(),
1187 frame.read_only,
1188 frame.value_transferred,
1189 &input_data,
1190 frame.nested_gas.gas_left(),
1191 );
1192 });
1193 let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1194 handler.mock_call(
1195 frame
1196 .delegate
1197 .as_ref()
1198 .map(|delegate| delegate.callee)
1199 .unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1200 &input_data,
1201 frame.value_transferred,
1202 )
1203 });
1204 let frames_len = self.frames.len();
1208 if let Some(caller_frame) = match frames_len {
1209 0 => None,
1210 1 => Some(&mut self.first_frame.last_frame_output),
1211 _ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1212 } {
1213 *caller_frame = Default::default();
1214 }
1215
1216 self.transient_storage.start_transaction();
1217
1218 let do_transaction = || -> ExecResult {
1219 let caller = self.caller();
1220 let is_first_frame = self.frames.len() == 0;
1221 let bump_nonce = self.exec_config.bump_nonce;
1222 let frame = top_frame_mut!(self);
1223 let account_id = &frame.account_id.clone();
1224
1225 if u32::try_from(input_data.len())
1226 .map(|len| len > limits::CALLDATA_BYTES)
1227 .unwrap_or(true)
1228 {
1229 Err(<Error<T>>::CallDataTooLarge)?;
1230 }
1231
1232 if entry_point == ExportedFunction::Constructor {
1235 let origin = &self.origin.account_id()?;
1238
1239 if !pezframe_system::Pezpallet::<T>::account_exists(&account_id) {
1240 let ed = <Contracts<T>>::min_balance();
1241 frame.nested_storage.record_charge(&StorageDeposit::Charge(ed))?;
1242 <Contracts<T>>::charge_deposit(None, origin, account_id, ed, self.exec_config)?;
1243 }
1244
1245 <System<T>>::inc_consumers(account_id)?;
1250
1251 <System<T>>::inc_account_nonce(account_id);
1253
1254 if bump_nonce || !is_first_frame {
1255 <System<T>>::inc_account_nonce(caller.account_id()?);
1258 }
1259 if is_pvm {
1261 <CodeInfo<T>>::increment_refcount(
1262 *executable
1263 .as_executable()
1264 .expect("Precompiles cannot be instantiated; qed")
1265 .code_hash(),
1266 )?;
1267 }
1268 }
1269
1270 if frame.delegate.is_none() {
1274 Self::transfer_from_origin(
1275 &self.origin,
1276 &caller,
1277 account_id,
1278 frame.value_transferred,
1279 &mut frame.nested_storage,
1280 self.exec_config,
1281 )?;
1282 }
1283
1284 if let Some(precompile) = executable.as_precompile() {
1291 if precompile.has_contract_info()
1292 && frame.delegate.is_none()
1293 && !<System<T>>::account_exists(account_id)
1294 {
1295 T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1298 <System<T>>::inc_consumers(account_id)?;
1300 }
1301 }
1302
1303 let mut code_deposit = executable
1304 .as_executable()
1305 .map(|exec| exec.code_info().deposit())
1306 .unwrap_or_default();
1307
1308 let mut output = match executable {
1309 ExecutableOrPrecompile::Executable(executable) => {
1310 executable.execute(self, entry_point, input_data)
1311 },
1312 ExecutableOrPrecompile::Precompile { instance, .. } => {
1313 instance.call(input_data, self)
1314 },
1315 }
1316 .and_then(|output| {
1317 if u32::try_from(output.data.len())
1318 .map(|len| len > limits::CALLDATA_BYTES)
1319 .unwrap_or(true)
1320 {
1321 Err(<Error<T>>::ReturnDataTooLarge)?;
1322 }
1323 Ok(output)
1324 })
1325 .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1326
1327 if output.did_revert() {
1329 return Ok(output);
1330 }
1331
1332 let frame = if entry_point == ExportedFunction::Constructor {
1335 let origin = self.origin.account_id()?.clone();
1336 let frame = top_frame_mut!(self);
1337 if !is_pvm {
1340 let data = if crate::tracing::if_tracing(|_| {}).is_none()
1344 && self.exec_config.is_dry_run.is_none()
1345 {
1346 core::mem::replace(&mut output.data, Default::default())
1347 } else {
1348 output.data.clone()
1349 };
1350
1351 let mut module = crate::ContractBlob::<T>::from_evm_runtime_code(data, origin)?;
1352 module.store_code(&self.exec_config, Some(&mut frame.nested_storage))?;
1353 code_deposit = module.code_info().deposit();
1354
1355 let contract_info = frame.contract_info();
1356 contract_info.code_hash = *module.code_hash();
1357 <CodeInfo<T>>::increment_refcount(contract_info.code_hash)?;
1358 }
1359
1360 let deposit = frame.contract_info().update_base_deposit(code_deposit);
1361 frame
1362 .nested_storage
1363 .charge_deposit(frame.account_id.clone(), StorageDeposit::Charge(deposit));
1364 frame
1365 } else {
1366 self.top_frame_mut()
1367 };
1368
1369 let contract = frame.contract_info.as_contract();
1373 frame
1374 .nested_storage
1375 .enforce_limit(contract)
1376 .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1377
1378 Ok(output)
1379 };
1380
1381 let transaction_outcome =
1388 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1389 let output = if let Some(mock_answer) = mock_answer {
1390 Ok(mock_answer)
1391 } else {
1392 do_transaction()
1393 };
1394 match &output {
1395 Ok(result) if !result.did_revert() => {
1396 TransactionOutcome::Commit(Ok((true, output)))
1397 },
1398 _ => TransactionOutcome::Rollback(Ok((false, output))),
1399 }
1400 });
1401
1402 let (success, output) = match transaction_outcome {
1403 Ok((success, output)) => {
1405 if_tracing(|tracer| {
1406 let gas_consumed = top_frame!(self).nested_gas.gas_consumed();
1407 match &output {
1408 Ok(output) => tracer.exit_child_span(&output, gas_consumed),
1409 Err(e) => tracer.exit_child_span_with_error(e.error.into(), gas_consumed),
1410 }
1411 });
1412
1413 (success, output)
1414 },
1415 Err(error) => {
1418 if_tracing(|tracer| {
1419 let gas_consumed = top_frame!(self).nested_gas.gas_consumed();
1420 tracer.exit_child_span_with_error(error.into(), gas_consumed);
1421 });
1422
1423 (false, Err(error.into()))
1424 },
1425 };
1426
1427 if success {
1428 self.transient_storage.commit_transaction();
1429 } else {
1430 self.transient_storage.rollback_transaction();
1431 }
1432 log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1433
1434 self.pop_frame(success);
1435 output.map(|output| {
1436 self.top_frame_mut().last_frame_output = output;
1437 })
1438 }
1439
1440 fn pop_frame(&mut self, persist: bool) {
1445 let frame = self.frames.pop();
1449
1450 if let Some(mut frame) = frame {
1453 let account_id = &frame.account_id;
1454 let prev = top_frame_mut!(self);
1455
1456 prev.nested_gas.absorb_nested(frame.nested_gas);
1457
1458 if !persist {
1460 return;
1461 }
1462
1463 frame.contract_info.load(account_id);
1468 let mut contract = frame.contract_info.into_contract();
1469 prev.nested_storage.absorb(frame.nested_storage, account_id, contract.as_mut());
1470
1471 prev.contracts_created.extend(frame.contracts_created);
1473 prev.contracts_to_be_destroyed.extend(frame.contracts_to_be_destroyed);
1474
1475 if let Some(contract) = contract {
1476 if prev.account_id == *account_id {
1481 prev.contract_info = CachedContract::Cached(contract);
1482 return;
1483 }
1484
1485 AccountInfo::<T>::insert_contract(
1491 &T::AddressMapper::to_address(account_id),
1492 contract,
1493 );
1494 if let Some(f) = self.frames_mut().skip(1).find(|f| f.account_id == *account_id) {
1495 f.contract_info.invalidate();
1496 }
1497 }
1498 } else {
1499 self.gas_meter.absorb_nested(mem::take(&mut self.first_frame.nested_gas));
1500 if !persist {
1501 return;
1502 }
1503 let mut contract = self.first_frame.contract_info.as_contract();
1504 self.storage_meter.absorb(
1505 mem::take(&mut self.first_frame.nested_storage),
1506 &self.first_frame.account_id,
1507 contract.as_deref_mut(),
1508 );
1509
1510 if let Some(contract) = contract {
1511 AccountInfo::<T>::insert_contract(
1512 &T::AddressMapper::to_address(&self.first_frame.account_id),
1513 contract.clone(),
1514 );
1515 }
1516 let contracts_created = mem::take(&mut self.first_frame.contracts_created);
1518 let contracts_to_destroy = mem::take(&mut self.first_frame.contracts_to_be_destroyed);
1519 for (contract_account, args) in contracts_to_destroy {
1520 if args.only_if_same_tx && !contracts_created.contains(&contract_account) {
1521 continue;
1522 }
1523 Self::do_terminate(
1524 &mut self.storage_meter,
1525 self.exec_config,
1526 &contract_account,
1527 &self.origin,
1528 &args,
1529 )
1530 .ok();
1531 }
1532 }
1533 }
1534
1535 fn transfer<S: storage::meter::State + Default + Debug>(
1548 origin: &Origin<T>,
1549 from: &T::AccountId,
1550 to: &T::AccountId,
1551 value: U256,
1552 preservation: Preservation,
1553 storage_meter: &mut storage::meter::GenericMeter<T, S>,
1554 exec_config: &ExecConfig<T>,
1555 ) -> DispatchResult {
1556 let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1557 .map_err(|_| Error::<T>::BalanceConversionFailed)?;
1558 if value.is_zero() {
1559 return Ok(());
1560 }
1561
1562 if <System<T>>::account_exists(to) {
1563 return transfer_with_dust::<T>(from, to, value, preservation);
1564 }
1565
1566 let origin = origin.account_id()?;
1567 let ed = <T as Config>::Currency::minimum_balance();
1568 with_transaction(|| -> TransactionOutcome<DispatchResult> {
1569 match storage_meter
1570 .record_charge(&StorageDeposit::Charge(ed))
1571 .and_then(|_| <Contracts<T>>::charge_deposit(None, origin, to, ed, exec_config))
1572 .and_then(|_| transfer_with_dust::<T>(from, to, value, preservation))
1573 {
1574 Ok(_) => TransactionOutcome::Commit(Ok(())),
1575 Err(err) => TransactionOutcome::Rollback(Err(err)),
1576 }
1577 })
1578 }
1579
1580 fn transfer_from_origin<S: storage::meter::State + Default + Debug>(
1582 origin: &Origin<T>,
1583 from: &Origin<T>,
1584 to: &T::AccountId,
1585 value: U256,
1586 storage_meter: &mut storage::meter::GenericMeter<T, S>,
1587 exec_config: &ExecConfig<T>,
1588 ) -> ExecResult {
1589 let from = match from {
1592 Origin::Signed(caller) => caller,
1593 Origin::Root if value.is_zero() => return Ok(Default::default()),
1594 Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1595 };
1596 Self::transfer(origin, from, to, value, Preservation::Preserve, storage_meter, exec_config)
1597 .map(|_| Default::default())
1598 .map_err(Into::into)
1599 }
1600
1601 fn do_terminate(
1603 storage_meter: &mut storage::meter::Meter<T>,
1604 exec_config: &ExecConfig<T>,
1605 contract_account: &T::AccountId,
1606 origin: &Origin<T>,
1607 args: &TerminateArgs<T>,
1608 ) -> Result<(), DispatchError> {
1609 use pezframe_support::traits::fungible::InspectHold;
1610
1611 let contract_address = T::AddressMapper::to_address(contract_account);
1612
1613 let mut delete_contract = |trie_id: &TrieId, code_hash: &H256| {
1614 let refund = T::Currency::balance_on_hold(
1616 &HoldReason::StorageDepositReserve.into(),
1617 &contract_account,
1618 );
1619 <Contracts<T>>::refund_deposit(
1620 HoldReason::StorageDepositReserve,
1621 contract_account,
1622 origin.account_id()?,
1623 refund,
1624 Some(exec_config),
1625 )?;
1626
1627 System::<T>::dec_consumers(&contract_account);
1629
1630 Self::transfer(
1632 origin,
1633 contract_account,
1634 origin.account_id()?,
1635 Contracts::<T>::convert_native_to_evm(T::Currency::minimum_balance()),
1636 Preservation::Expendable,
1637 storage_meter,
1638 exec_config,
1639 )?;
1640
1641 let balance = <Contracts<T>>::convert_native_to_evm(<AccountInfo<T>>::total_balance(
1645 contract_address.into(),
1646 ));
1647 Self::transfer(
1648 origin,
1649 contract_account,
1650 &args.beneficiary,
1651 balance,
1652 Preservation::Expendable,
1653 storage_meter,
1654 exec_config,
1655 )?;
1656
1657 let _code_removed = <CodeInfo<T>>::decrement_refcount(*code_hash)?;
1659
1660 ContractInfo::<T>::queue_trie_for_deletion(trie_id.clone());
1662 AccountInfoOf::<T>::remove(contract_address);
1663 ImmutableDataOf::<T>::remove(contract_address);
1664
1665 storage_meter.terminate(contract_account.clone(), refund);
1668
1669 Ok(())
1670 };
1671
1672 with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1676 match delete_contract(&args.trie_id, &args.code_hash) {
1677 Ok(()) => {
1678 log::trace!(target: LOG_TARGET, "Terminated {contract_address:?}");
1680 TransactionOutcome::Commit(Ok(()))
1681 },
1682 Err(e) => {
1683 log::debug!(target: LOG_TARGET, "Contract at {contract_address:?} failed to terminate: {e:?}");
1684 TransactionOutcome::Rollback(Err(e))
1685 },
1686 }
1687 })
1688 }
1689
1690 fn top_frame(&self) -> &Frame<T> {
1692 top_frame!(self)
1693 }
1694
1695 fn top_frame_mut(&mut self) -> &mut Frame<T> {
1697 top_frame_mut!(self)
1698 }
1699
1700 fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1704 core::iter::once(&self.first_frame).chain(&self.frames).rev()
1705 }
1706
1707 fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1709 core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1710 }
1711
1712 fn allows_reentry(&self, id: &T::AccountId) -> bool {
1714 !self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1715 }
1716
1717 fn account_balance(&self, who: &T::AccountId) -> U256 {
1719 let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
1720 crate::Pezpallet::<T>::convert_native_to_evm(balance)
1721 }
1722
1723 #[cfg(feature = "runtime-benchmarks")]
1726 pub(crate) fn override_export(&mut self, export: ExportedFunction) {
1727 self.top_frame_mut().entry_point = export;
1728 }
1729
1730 #[cfg(feature = "runtime-benchmarks")]
1731 pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
1732 self.block_number = block_number;
1733 }
1734
1735 fn block_hash(&self, block_number: U256) -> Option<H256> {
1736 let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
1737 return None;
1738 };
1739 if block_number >= self.block_number {
1740 return None;
1741 }
1742 if block_number < self.block_number.saturating_sub(256u32.into()) {
1743 return None;
1744 }
1745
1746 match crate::Pezpallet::<T>::eth_block_hash_from_number(block_number.into()) {
1750 Some(hash) => Some(hash),
1751 None => {
1752 use codec::Decode;
1753 let block_hash = System::<T>::block_hash(&block_number);
1754 Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
1755 },
1756 }
1757 }
1758
1759 fn has_contract_info(&self) -> bool {
1762 let address = self.address();
1763 let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
1764 if let Some(precompile) = precompile {
1765 return precompile.has_contract_info();
1766 }
1767 true
1768 }
1769}
1770
1771impl<'a, T, E> Ext for Stack<'a, T, E>
1772where
1773 T: Config,
1774 E: Executable<T>,
1775{
1776 fn delegate_call(
1777 &mut self,
1778 gas_limit: Weight,
1779 deposit_limit: U256,
1780 address: H160,
1781 input_data: Vec<u8>,
1782 ) -> Result<(), ExecError> {
1783 *self.last_frame_output_mut() = Default::default();
1786
1787 let top_frame = self.top_frame_mut();
1788 let contract_info = top_frame.contract_info().clone();
1789 let account_id = top_frame.account_id.clone();
1790 let value = top_frame.value_transferred;
1791 if let Some(executable) = self.push_frame(
1792 FrameArgs::Call {
1793 dest: account_id,
1794 cached_info: Some(contract_info),
1795 delegated_call: Some(DelegateInfo {
1796 caller: self.caller().clone(),
1797 callee: address,
1798 }),
1799 },
1800 value,
1801 gas_limit,
1802 deposit_limit.saturated_into::<BalanceOf<T>>(),
1803 self.is_read_only(),
1804 &input_data,
1805 )? {
1806 self.run(executable, input_data)
1807 } else {
1808 Ok(())
1810 }
1811 }
1812
1813 fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
1814 if_tracing(|tracer| {
1815 let addr = T::AddressMapper::to_address(self.account_id());
1816 tracer.terminate(
1817 addr,
1818 *beneficiary,
1819 self.top_frame().nested_gas.gas_left(),
1820 crate::Pezpallet::<T>::evm_balance(&addr),
1821 );
1822 });
1823 let frame = top_frame_mut!(self);
1824 let info = frame.contract_info();
1825 let trie_id = info.trie_id.clone();
1826 let code_hash = info.code_hash;
1827 let contract_address = T::AddressMapper::to_address(&frame.account_id);
1828 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
1829
1830 Self::transfer(
1832 &self.origin,
1833 &frame.account_id,
1834 &beneficiary,
1835 <Contracts<T>>::evm_balance(&contract_address),
1836 Preservation::Preserve,
1837 &mut frame.nested_storage,
1838 self.exec_config,
1839 )?;
1840
1841 let account_id = frame.account_id.clone();
1843 self.top_frame_mut().contracts_to_be_destroyed.insert(
1844 account_id,
1845 TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: true },
1846 );
1847 Ok(CodeRemoved::Yes)
1848 }
1849
1850 fn own_code_hash(&mut self) -> &H256 {
1851 &self.top_frame_mut().contract_info().code_hash
1852 }
1853
1854 fn set_code_hash(&mut self, hash: H256) -> Result<CodeRemoved, DispatchError> {
1870 let frame = top_frame_mut!(self);
1871
1872 let info = frame.contract_info();
1873
1874 let prev_hash = info.code_hash;
1875 info.code_hash = hash;
1876
1877 let code_info = CodeInfoOf::<T>::get(hash).ok_or(Error::<T>::CodeNotFound)?;
1878
1879 let old_base_deposit = info.storage_base_deposit();
1880 let new_base_deposit = info.update_base_deposit(code_info.deposit());
1881 let deposit = StorageDeposit::Charge(new_base_deposit)
1882 .saturating_sub(&StorageDeposit::Charge(old_base_deposit));
1883
1884 frame.nested_storage.charge_deposit(frame.account_id.clone(), deposit);
1885
1886 <CodeInfo<T>>::increment_refcount(hash)?;
1887 let removed = <CodeInfo<T>>::decrement_refcount(prev_hash)?;
1888 Ok(removed)
1889 }
1890
1891 fn immutable_data_len(&mut self) -> u32 {
1892 self.top_frame_mut().contract_info().immutable_data_len()
1893 }
1894
1895 fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
1896 if self.top_frame().entry_point == ExportedFunction::Constructor {
1897 return Err(Error::<T>::InvalidImmutableAccess.into());
1898 }
1899
1900 let address = self
1902 .top_frame()
1903 .delegate
1904 .as_ref()
1905 .map(|d| d.callee)
1906 .unwrap_or(T::AddressMapper::to_address(self.account_id()));
1907 Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
1908 }
1909
1910 fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
1911 let frame = self.top_frame_mut();
1912 if frame.entry_point == ExportedFunction::Call || data.is_empty() {
1913 return Err(Error::<T>::InvalidImmutableAccess.into());
1914 }
1915 frame.contract_info().set_immutable_data_len(data.len() as u32);
1916 <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
1917 Ok(())
1918 }
1919}
1920
1921impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
1922where
1923 T: Config,
1924 E: Executable<T>,
1925{
1926 fn instantiate(
1927 &mut self,
1928 gas_limit: Weight,
1929 deposit_limit: U256,
1930 mut code: Code,
1931 value: U256,
1932 input_data: Vec<u8>,
1933 salt: Option<&[u8; 32]>,
1934 ) -> Result<H160, ExecError> {
1935 *self.last_frame_output_mut() = Default::default();
1938
1939 let sender = self.top_frame().account_id.clone();
1940 let executable = {
1941 let executable = match &mut code {
1942 Code::Upload(initcode) => {
1943 if !T::AllowEVMBytecode::get() {
1944 return Err(<Error<T>>::CodeRejected.into());
1945 }
1946 ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
1947 let initcode = crate::tracing::if_tracing(|_| initcode.clone())
1948 .unwrap_or_else(|| mem::take(initcode));
1949 E::from_evm_init_code(initcode, sender.clone())?
1950 },
1951 Code::Existing(hash) => {
1952 let executable = E::from_storage(*hash, self.gas_meter_mut())?;
1953 ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
1954 executable
1955 },
1956 };
1957 self.push_frame(
1958 FrameArgs::Instantiate {
1959 sender,
1960 executable,
1961 salt,
1962 input_data: input_data.as_ref(),
1963 },
1964 value,
1965 gas_limit,
1966 deposit_limit.saturated_into::<BalanceOf<T>>(),
1967 self.is_read_only(),
1968 &input_data,
1969 )?
1970 };
1971 let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
1972
1973 let account_id = self.top_frame().account_id.clone();
1975 self.top_frame_mut().contracts_created.insert(account_id);
1976
1977 let address = T::AddressMapper::to_address(&self.top_frame().account_id);
1978 if_tracing(|t| t.instantiate_code(&code, salt));
1979 self.run(executable, input_data).map(|_| address)
1980 }
1981}
1982
1983impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
1984where
1985 T: Config,
1986 E: Executable<T>,
1987{
1988 type T = T;
1989
1990 fn call(
1991 &mut self,
1992 gas_limit: Weight,
1993 deposit_limit: U256,
1994 dest_addr: &H160,
1995 value: U256,
1996 input_data: Vec<u8>,
1997 allows_reentry: bool,
1998 read_only: bool,
1999 ) -> Result<(), ExecError> {
2000 self.top_frame_mut().allows_reentry = allows_reentry;
2004
2005 *self.last_frame_output_mut() = Default::default();
2008
2009 let try_call = || {
2010 let is_read_only = read_only || self.is_read_only();
2012
2013 let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2015 T::AddressMapper::to_fallback_account_id(dest_addr)
2016 } else {
2017 T::AddressMapper::to_account_id(dest_addr)
2018 };
2019
2020 if !self.allows_reentry(&dest) {
2021 return Err(<Error<T>>::ReentranceDenied.into());
2022 }
2023
2024 let cached_info = self
2028 .frames()
2029 .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2030 .and_then(|f| match &f.contract_info {
2031 CachedContract::Cached(contract) => Some(contract.clone()),
2032 _ => None,
2033 });
2034
2035 if let Some(executable) = self.push_frame(
2036 FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2037 value,
2038 gas_limit,
2039 deposit_limit.saturated_into::<BalanceOf<T>>(),
2040 is_read_only,
2041 &input_data,
2042 )? {
2043 self.run(executable, input_data)
2044 } else {
2045 if_tracing(|t| {
2046 t.enter_child_span(
2047 T::AddressMapper::to_address(self.account_id()),
2048 T::AddressMapper::to_address(&dest),
2049 false,
2050 is_read_only,
2051 value,
2052 &input_data,
2053 Weight::zero(),
2054 );
2055 });
2056 let result = if let Some(mock_answer) =
2057 self.exec_config.mock_handler.as_ref().and_then(|handler| {
2058 handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2059 }) {
2060 *self.last_frame_output_mut() = mock_answer.clone();
2061 Ok(mock_answer)
2062 } else if is_read_only && value.is_zero() {
2063 Ok(Default::default())
2064 } else if is_read_only {
2065 Err(Error::<T>::StateChangeDenied.into())
2066 } else {
2067 let account_id = self.account_id().clone();
2068 let frame = top_frame_mut!(self);
2069 Self::transfer_from_origin(
2070 &self.origin,
2071 &Origin::from_account_id(account_id),
2072 &dest,
2073 value,
2074 &mut frame.nested_storage,
2075 self.exec_config,
2076 )
2077 };
2078
2079 if_tracing(|t| match result {
2080 Ok(ref output) => t.exit_child_span(&output, Weight::zero()),
2081 Err(e) => t.exit_child_span_with_error(e.error.into(), Weight::zero()),
2082 });
2083
2084 result.map(|_| ())
2085 }
2086 };
2087
2088 let result = try_call();
2090
2091 self.top_frame_mut().allows_reentry = true;
2093
2094 result
2095 }
2096
2097 fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2098 self.transient_storage.read(self.account_id(), key)
2099 }
2100
2101 fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2102 self.transient_storage
2103 .read(self.account_id(), key)
2104 .map(|value| value.len() as _)
2105 }
2106
2107 fn set_transient_storage(
2108 &mut self,
2109 key: &Key,
2110 value: Option<Vec<u8>>,
2111 take_old: bool,
2112 ) -> Result<WriteOutcome, DispatchError> {
2113 let account_id = self.account_id().clone();
2114 self.transient_storage.write(&account_id, key, value, take_old)
2115 }
2116
2117 fn account_id(&self) -> &T::AccountId {
2118 &self.top_frame().account_id
2119 }
2120
2121 fn caller(&self) -> Origin<T> {
2122 if let Some(Ok(mock_caller)) = self
2123 .exec_config
2124 .mock_handler
2125 .as_ref()
2126 .and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2127 .map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2128 {
2129 return mock_caller;
2130 }
2131
2132 if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
2133 caller.clone()
2134 } else {
2135 self.frames()
2136 .nth(1)
2137 .map(|f| Origin::from_account_id(f.account_id.clone()))
2138 .unwrap_or(self.origin.clone())
2139 }
2140 }
2141
2142 fn caller_of_caller(&self) -> Origin<T> {
2143 let caller_of_caller_frame = match self.frames().nth(2) {
2145 None => return self.origin.clone(),
2146 Some(frame) => frame,
2147 };
2148 if let Some(DelegateInfo { caller, .. }) = &caller_of_caller_frame.delegate {
2149 caller.clone()
2150 } else {
2151 Origin::from_account_id(caller_of_caller_frame.account_id.clone())
2152 }
2153 }
2154
2155 fn origin(&self) -> &Origin<T> {
2156 if let Some(mock_origin) = self
2157 .exec_config
2158 .mock_handler
2159 .as_ref()
2160 .and_then(|mock_handler| mock_handler.mock_origin())
2161 {
2162 return mock_origin;
2163 }
2164
2165 &self.origin
2166 }
2167
2168 fn to_account_id(&self, address: &H160) -> T::AccountId {
2169 T::AddressMapper::to_account_id(address)
2170 }
2171
2172 fn code_hash(&self, address: &H160) -> H256 {
2173 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()) {
2174 return pezsp_io::hashing::keccak_256(code).into();
2175 }
2176
2177 <AccountInfo<T>>::load_contract(&address)
2178 .map(|contract| contract.code_hash)
2179 .unwrap_or_else(|| {
2180 if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) {
2181 return EMPTY_CODE_HASH;
2182 }
2183 H256::zero()
2184 })
2185 }
2186
2187 fn code_size(&self, address: &H160) -> u64 {
2188 if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()) {
2189 return code.len() as u64;
2190 }
2191
2192 <AccountInfo<T>>::load_contract(&address)
2193 .and_then(|contract| CodeInfoOf::<T>::get(contract.code_hash))
2194 .map(|info| info.code_len())
2195 .unwrap_or_default()
2196 }
2197
2198 fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2199 let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2200 self.origin == caller
2201 }
2202
2203 fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2204 self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2206 }
2207
2208 fn balance(&self) -> U256 {
2209 self.account_balance(&self.top_frame().account_id)
2210 }
2211
2212 fn balance_of(&self, address: &H160) -> U256 {
2213 let balance =
2214 self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2215 if_tracing(|tracer| {
2216 tracer.balance_read(address, balance);
2217 });
2218 balance
2219 }
2220
2221 fn value_transferred(&self) -> U256 {
2222 self.top_frame().value_transferred.into()
2223 }
2224
2225 fn now(&self) -> U256 {
2226 (self.timestamp / 1000u32.into()).into()
2227 }
2228
2229 fn minimum_balance(&self) -> U256 {
2230 let min = T::Currency::minimum_balance();
2231 crate::Pezpallet::<T>::convert_native_to_evm(min)
2232 }
2233
2234 fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2235 let contract = T::AddressMapper::to_address(self.account_id());
2236 if_tracing(|tracer| {
2237 tracer.log_event(contract, &topics, &data);
2238 });
2239
2240 block_storage::capture_ethereum_log(&contract, &data, &topics);
2242
2243 Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2244 }
2245
2246 fn block_number(&self) -> U256 {
2247 self.block_number.into()
2248 }
2249
2250 fn block_hash(&self, block_number: U256) -> Option<H256> {
2251 self.block_hash(block_number)
2252 }
2253
2254 fn block_author(&self) -> H160 {
2255 Contracts::<Self::T>::block_author()
2256 }
2257
2258 fn gas_limit(&self) -> u64 {
2259 <Contracts<T>>::evm_block_gas_limit().saturated_into()
2260 }
2261
2262 fn chain_id(&self) -> u64 {
2263 <T as Config>::ChainId::get()
2264 }
2265
2266 fn gas_meter(&self) -> &GasMeter<Self::T> {
2267 &self.top_frame().nested_gas
2268 }
2269
2270 fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T> {
2271 &mut self.top_frame_mut().nested_gas
2272 }
2273
2274 fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2275 secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2276 }
2277
2278 fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2279 pezsp_io::crypto::sr25519_verify(
2280 &SR25519Signature::from(*signature),
2281 message,
2282 &SR25519Public::from(*pub_key),
2283 )
2284 }
2285
2286 fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()> {
2287 ECDSAPublic::from(*pk).to_eth_address()
2288 }
2289
2290 #[cfg(any(test, feature = "runtime-benchmarks"))]
2291 fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2292 self.top_frame_mut().contract_info()
2293 }
2294
2295 #[cfg(any(feature = "runtime-benchmarks", test))]
2296 fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2297 &mut self.transient_storage
2298 }
2299
2300 fn is_read_only(&self) -> bool {
2301 self.top_frame().read_only
2302 }
2303
2304 fn is_delegate_call(&self) -> bool {
2305 self.top_frame().delegate.is_some()
2306 }
2307
2308 fn last_frame_output(&self) -> &ExecReturnValue {
2309 &self.top_frame().last_frame_output
2310 }
2311
2312 fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2313 &mut self.top_frame_mut().last_frame_output
2314 }
2315
2316 fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2317 let len = buf.len();
2318 if len == 0 {
2319 return;
2320 }
2321
2322 let code_hash = self.code_hash(address);
2323 let code = crate::PristineCode::<T>::get(&code_hash).unwrap_or_default();
2324
2325 let len = len.min(code.len().saturating_sub(code_offset));
2326 if len > 0 {
2327 buf[..len].copy_from_slice(&code[code_offset..code_offset + len]);
2328 }
2329
2330 buf[len..].fill(0);
2331 }
2332
2333 fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2334 ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2335 let parent = core::iter::once(&mut self.first_frame)
2336 .chain(&mut self.frames)
2337 .rev()
2338 .nth(1)
2339 .ok_or_else(|| Error::<T>::ContractNotFound)?;
2340 ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2341 ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2342
2343 let info = parent.contract_info();
2344 let trie_id = info.trie_id.clone();
2345 let code_hash = info.code_hash;
2346 let contract_address = T::AddressMapper::to_address(&parent.account_id);
2347 let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2348
2349 Self::transfer(
2351 &self.origin,
2352 &parent.account_id,
2353 &beneficiary,
2354 <Contracts<T>>::evm_balance(&contract_address),
2355 Preservation::Preserve,
2356 &mut parent.nested_storage,
2357 &self.exec_config,
2358 )?;
2359
2360 let args = TerminateArgs { beneficiary, trie_id, code_hash, only_if_same_tx: false };
2362 let account_id = parent.account_id.clone();
2363 self.top_frame_mut().contracts_to_be_destroyed.insert(account_id, args);
2364
2365 Ok(())
2366 }
2367
2368 fn effective_gas_price(&self) -> U256 {
2369 self.exec_config
2370 .effective_gas_price
2371 .unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2372 }
2373
2374 fn gas_left(&self) -> u64 {
2375 let frame = self.top_frame();
2376 if let Some((encoded_len, base_weight)) = self.exec_config.collect_deposit_from_hold {
2377 let weight_fee_consumed = T::FeeInfo::tx_fee_from_weight(
2380 encoded_len,
2381 &frame.nested_gas.gas_consumed().saturating_add(base_weight),
2382 );
2383 let available = T::FeeInfo::remaining_txfee().saturating_sub(weight_fee_consumed);
2384 let deposit_consumed = self
2385 .frames
2386 .iter()
2387 .chain(core::iter::once(&self.first_frame))
2388 .fold(StorageDeposit::default(), |acc, frame| {
2389 acc.saturating_add(&frame.nested_storage.consumed())
2390 });
2391 deposit_consumed.available(&available)
2392 } else {
2393 use pezframe_support::traits::tokens::{Fortitude, Preservation};
2397 let weight_fee_available =
2398 T::FeeInfo::weight_to_fee(&frame.nested_gas.gas_left(), Combinator::Min);
2399 let available_balance = self
2400 .origin
2401 .account_id()
2402 .map(|acc| {
2403 T::Currency::reducible_balance(acc, Preservation::Preserve, Fortitude::Polite)
2404 })
2405 .unwrap_or(BalanceOf::<T>::max_value());
2406 let deposit_available = frame.nested_storage.available().min(available_balance);
2407 weight_fee_available.saturating_add(deposit_available)
2408 }
2409 .saturated_into()
2410 }
2411
2412 fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2413 assert!(self.has_contract_info());
2414 self.top_frame_mut().contract_info().read(key)
2415 }
2416
2417 fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2418 assert!(self.has_contract_info());
2419 self.top_frame_mut().contract_info().size(key.into())
2420 }
2421
2422 fn set_storage(
2423 &mut self,
2424 key: &Key,
2425 value: Option<Vec<u8>>,
2426 take_old: bool,
2427 ) -> Result<WriteOutcome, DispatchError> {
2428 assert!(self.has_contract_info());
2429 let frame = self.top_frame_mut();
2430 frame.contract_info.get(&frame.account_id).write(
2431 key.into(),
2432 value,
2433 Some(&mut frame.nested_storage),
2434 take_old,
2435 )
2436 }
2437
2438 fn charge_storage(&mut self, diff: &Diff) {
2439 assert!(self.has_contract_info());
2440 self.top_frame_mut().nested_storage.charge(diff)
2441 }
2442}
2443
2444pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2446 <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2447}
2448
2449#[cfg(feature = "runtime-benchmarks")]
2450pub fn terminate_contract_for_benchmark<T: Config>(
2451 origin: T::AccountId,
2452 contract: &T::AccountId,
2453 info: &ContractInfo<T>,
2454 beneficiary: T::AccountId,
2455) -> Result<(), DispatchError> {
2456 let mut meter = storage::meter::Meter::<T>::new(BalanceOf::<T>::max_value());
2457 Stack::<T, crate::ContractBlob<T>>::do_terminate(
2458 &mut meter,
2459 &ExecConfig::new_bizinikiwi_tx(),
2460 contract,
2461 &Origin::from_account_id(origin),
2462 &TerminateArgs {
2463 beneficiary,
2464 trie_id: info.trie_id.clone(),
2465 code_hash: info.code_hash,
2466 only_if_same_tx: false,
2467 },
2468 )
2469}
2470
2471struct TerminateArgs<T: Config> {
2473 beneficiary: T::AccountId,
2475 trie_id: TrieId,
2477 code_hash: H256,
2479 only_if_same_tx: bool,
2481}
2482
2483mod sealing {
2484 use super::*;
2485
2486 pub trait Sealed {}
2487 impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2488
2489 #[cfg(test)]
2490 impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2491}