Skip to content

Commit 3cba3a8

Browse files
committed
something working
Signed-off-by: Alexandru Gheorghe <[email protected]>
1 parent 648cc16 commit 3cba3a8

File tree

9 files changed

+179
-57
lines changed

9 files changed

+179
-57
lines changed

substrate/frame/revive/src/call_builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub struct CallSetup<T: Config> {
5656
value: BalanceOf<T>,
5757
data: Vec<u8>,
5858
transient_storage_size: u32,
59-
exec_config: ExecConfig,
59+
exec_config: ExecConfig<T>,
6060
}
6161

6262
impl<T> Default for CallSetup<T>

substrate/frame/revive/src/exec.rs

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ pub struct Stack<'a, T: Config, E> {
544544
/// Transient storage used to store data, which is kept for the duration of a transaction.
545545
transient_storage: TransientStorage<T>,
546546
/// Global behavior determined by the creater of this stack.
547-
exec_config: &'a ExecConfig,
547+
exec_config: &'a ExecConfig<T>,
548548
/// No executable is held by the struct but influences its behaviour.
549549
_phantom: PhantomData<E>,
550550
}
@@ -579,7 +579,7 @@ struct Frame<T: Config> {
579579

580580
/// This structure is used to represent the arguments in a delegate call frame in order to
581581
/// distinguish who delegated the call and where it was delegated to.
582-
struct DelegateInfo<T: Config> {
582+
pub struct DelegateInfo<T: Config> {
583583
/// The caller of the contract.
584584
pub caller: Origin<T>,
585585
/// The address of the contract the call was delegated to.
@@ -794,7 +794,7 @@ where
794794
storage_meter: &mut storage::meter::Meter<T>,
795795
value: U256,
796796
input_data: Vec<u8>,
797-
exec_config: &ExecConfig,
797+
exec_config: &ExecConfig<T>,
798798
) -> ExecResult {
799799
let dest = T::AddressMapper::to_account_id(&dest);
800800
if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
@@ -804,6 +804,7 @@ where
804804
storage_meter,
805805
value,
806806
exec_config,
807+
&input_data,
807808
)? {
808809
stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
809810
} else {
@@ -819,14 +820,25 @@ where
819820
);
820821
});
821822

822-
let result = Self::transfer_from_origin(
823-
&origin,
824-
&origin,
825-
&dest,
826-
value,
827-
storage_meter,
828-
exec_config,
829-
);
823+
let result = if let Some(mock_answer) =
824+
exec_config.mock_handler.as_ref().and_then(|handler| {
825+
handler.mock_call(
826+
T::AddressMapper::to_address(&dest),
827+
input_data.clone(),
828+
value,
829+
)
830+
}) {
831+
Ok(mock_answer)
832+
} else {
833+
Self::transfer_from_origin(
834+
&origin,
835+
&origin,
836+
&dest,
837+
value,
838+
storage_meter,
839+
exec_config,
840+
)
841+
};
830842

831843
if_tracing(|t| match result {
832844
Ok(ref output) => t.exit_child_span(&output, Weight::zero()),
@@ -852,7 +864,7 @@ where
852864
value: U256,
853865
input_data: Vec<u8>,
854866
salt: Option<&[u8; 32]>,
855-
exec_config: &ExecConfig,
867+
exec_config: &ExecConfig<T>,
856868
) -> Result<(H160, ExecReturnValue), ExecError> {
857869
let deployer = T::AddressMapper::to_address(&origin);
858870
let (mut stack, executable) = Stack::<'_, T, E>::new(
@@ -867,6 +879,7 @@ where
867879
storage_meter,
868880
value,
869881
exec_config,
882+
&input_data,
870883
)?
871884
.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
872885
let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
@@ -889,7 +902,7 @@ where
889902
gas_meter: &'a mut GasMeter<T>,
890903
storage_meter: &'a mut storage::meter::Meter<T>,
891904
value: BalanceOf<T>,
892-
exec_config: &'a ExecConfig,
905+
exec_config: &'a ExecConfig<T>,
893906
) -> (Self, E) {
894907
let call = Self::new(
895908
FrameArgs::Call {
@@ -902,6 +915,7 @@ where
902915
storage_meter,
903916
value.into(),
904917
exec_config,
918+
&Default::default(),
905919
)
906920
.unwrap()
907921
.unwrap();
@@ -918,7 +932,8 @@ where
918932
gas_meter: &'a mut GasMeter<T>,
919933
storage_meter: &'a mut storage::meter::Meter<T>,
920934
value: U256,
921-
exec_config: &'a ExecConfig,
935+
exec_config: &'a ExecConfig<T>,
936+
input_data: &Vec<u8>,
922937
) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
923938
origin.ensure_mapped()?;
924939
let Some((first_frame, executable)) = Self::new_frame(
@@ -930,6 +945,8 @@ where
930945
BalanceOf::<T>::max_value(),
931946
false,
932947
true,
948+
input_data,
949+
exec_config,
933950
)?
934951
else {
935952
return Ok(None);
@@ -964,6 +981,8 @@ where
964981
deposit_limit: BalanceOf<T>,
965982
read_only: bool,
966983
origin_is_caller: bool,
984+
input_data: &Vec<u8>,
985+
exec_config: &ExecConfig<T>,
967986
) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
968987
let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
969988
FrameArgs::Call { dest, cached_info, delegated_call } => {
@@ -991,6 +1010,11 @@ where
9911010
(None, Some(_)) => CachedContract::None,
9921011
};
9931012

1013+
let delegated_call = delegated_call.or_else(|| {
1014+
exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1015+
mock_handler.mock_delegated_caller(address, input_data.clone())
1016+
})
1017+
});
9941018
// in case of delegate the executable is not the one at `address`
9951019
let executable = if let Some(delegated_call) = &delegated_call {
9961020
if let Some(precompile) =
@@ -1085,6 +1109,7 @@ where
10851109
gas_limit: Weight,
10861110
deposit_limit: BalanceOf<T>,
10871111
read_only: bool,
1112+
input_data: &Vec<u8>,
10881113
) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
10891114
if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
10901115
return Err(Error::<T>::MaxCallDepthReached.into());
@@ -1116,6 +1141,8 @@ where
11161141
deposit_limit,
11171142
read_only,
11181143
false,
1144+
input_data,
1145+
self.exec_config,
11191146
)? {
11201147
self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
11211148
Ok(Some(executable))
@@ -1251,11 +1278,23 @@ where
12511278
.map(|exec| exec.code_info().deposit())
12521279
.unwrap_or_default();
12531280

1281+
let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1282+
handler.mock_call(
1283+
frame
1284+
.delegate
1285+
.as_ref()
1286+
.map(|delegate| delegate.callee)
1287+
.unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1288+
input_data.clone(),
1289+
frame.value_transferred,
1290+
)
1291+
});
12541292
let mut output = match executable {
1255-
ExecutableOrPrecompile::Executable(executable) =>
1293+
ExecutableOrPrecompile::Executable(executable) if mock_answer.is_none() =>
12561294
executable.execute(self, entry_point, input_data),
1257-
ExecutableOrPrecompile::Precompile { instance, .. } =>
1295+
ExecutableOrPrecompile::Precompile { instance, .. } if mock_answer.is_none() =>
12581296
instance.call(input_data, self),
1297+
_ => Ok(mock_answer.expect("Checked above; qed")),
12591298
}
12601299
.and_then(|output| {
12611300
if u32::try_from(output.data.len())
@@ -1467,7 +1506,7 @@ where
14671506
to: &T::AccountId,
14681507
value: U256,
14691508
storage_meter: &mut storage::meter::GenericMeter<T, S>,
1470-
exec_config: &ExecConfig,
1509+
exec_config: &ExecConfig<T>,
14711510
) -> DispatchResult {
14721511
fn transfer_with_dust<T: Config>(
14731512
from: &AccountIdOf<T>,
@@ -1579,7 +1618,7 @@ where
15791618
to: &T::AccountId,
15801619
value: U256,
15811620
storage_meter: &mut storage::meter::GenericMeter<T, S>,
1582-
exec_config: &ExecConfig,
1621+
exec_config: &ExecConfig<T>,
15831622
) -> ExecResult {
15841623
// If the from address is root there is no account to transfer from, and therefore we can't
15851624
// take any `value` other than 0.
@@ -1692,6 +1731,7 @@ where
16921731
gas_limit,
16931732
deposit_limit.saturated_into::<BalanceOf<T>>(),
16941733
self.is_read_only(),
1734+
&input_data,
16951735
)? {
16961736
self.run(executable, input_data)
16971737
} else {
@@ -1859,6 +1899,7 @@ where
18591899
gas_limit,
18601900
deposit_limit.saturated_into::<BalanceOf<T>>(),
18611901
self.is_read_only(),
1902+
&input_data,
18621903
)?
18631904
};
18641905
let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
@@ -1926,6 +1967,7 @@ where
19261967
gas_limit,
19271968
deposit_limit.saturated_into::<BalanceOf<T>>(),
19281969
is_read_only,
1970+
&input_data,
19291971
)? {
19301972
self.run(executable, input_data)
19311973
} else {
@@ -2001,6 +2043,16 @@ where
20012043
}
20022044

20032045
fn caller(&self) -> Origin<T> {
2046+
if let Some(Ok(mock_caller)) = self
2047+
.exec_config
2048+
.mock_handler
2049+
.as_ref()
2050+
.and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2051+
.map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2052+
{
2053+
return mock_caller;
2054+
}
2055+
20042056
if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
20052057
caller.clone()
20062058
} else {

substrate/frame/revive/src/lib.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,20 @@ mod vm;
3838

3939
pub mod evm;
4040
pub mod migrations;
41+
pub mod mock;
4142
pub mod precompiles;
4243
pub mod test_utils;
4344
pub mod tracing;
4445
pub mod weights;
4546

47+
pub use crate::{
48+
address::{
49+
create1, create2, is_eth_derived, AccountId32Mapper, AddressMapper, TestAccountMapper,
50+
},
51+
exec::{DelegateInfo, Key, MomentOf, Origin as ExecOrigin},
52+
pallet::{genesis, *},
53+
storage::{AccountInfo, ContractInfo},
54+
};
4655
use crate::{
4756
evm::{
4857
create_call, fees::InfoT as FeeInfo, runtime::SetWeightLimit, CallTracer,
@@ -54,9 +63,12 @@ use crate::{
5463
tracing::if_tracing,
5564
vm::{pvm::extract_code_and_data, CodeInfo, ContractBlob, RuntimeCosts},
5665
};
66+
pub use alloc::collections::{BTreeMap, VecDeque};
5767
use alloc::{boxed::Box, format, vec};
68+
pub use codec;
5869
use codec::{Codec, Decode, Encode};
5970
use environmental::*;
71+
pub use frame_support::{self, dispatch::DispatchInfo, weights::Weight};
6072
use frame_support::{
6173
dispatch::{
6274
DispatchErrorWithPostInfo, DispatchResult, DispatchResultWithPostInfo, GetDispatchInfo,
@@ -72,31 +84,20 @@ use frame_support::{
7284
weights::WeightMeter,
7385
BoundedVec, RuntimeDebugNoBound,
7486
};
87+
pub use frame_system::{self, limits::BlockWeights};
7588
use frame_system::{
7689
ensure_signed,
7790
pallet_prelude::{BlockNumberFor, OriginFor},
7891
Pallet as System,
7992
};
93+
pub use primitives::*;
8094
use scale_info::TypeInfo;
95+
pub use sp_core::{H160, H256, U256};
96+
pub use sp_runtime;
8197
use sp_runtime::{
8298
traits::{BadOrigin, Bounded, Convert, Dispatchable, Saturating, UniqueSaturatedInto, Zero},
8399
AccountId32, DispatchError, FixedPointNumber, FixedU128,
84100
};
85-
86-
pub use crate::{
87-
address::{
88-
create1, create2, is_eth_derived, AccountId32Mapper, AddressMapper, TestAccountMapper,
89-
},
90-
exec::{Key, MomentOf, Origin as ExecOrigin},
91-
pallet::{genesis, *},
92-
storage::{AccountInfo, ContractInfo},
93-
};
94-
pub use codec;
95-
pub use frame_support::{self, dispatch::DispatchInfo, weights::Weight};
96-
pub use frame_system::{self, limits::BlockWeights};
97-
pub use primitives::*;
98-
pub use sp_core::{H160, H256, U256};
99-
pub use sp_runtime;
100101
pub use weights::WeightInfo;
101102

102103
#[cfg(doc)]
@@ -107,7 +108,7 @@ type TrieId = BoundedVec<u8, ConstU32<128>>;
107108
type ImmutableData = BoundedVec<u8, ConstU32<{ limits::IMMUTABLE_BYTES }>>;
108109
type CallOf<T> = <T as Config>::RuntimeCall;
109110

110-
/// Used as a sentinel value when reading and writing contract memory.
111+
// Used as a sentinel value when reading and writing contract memory.
111112
///
112113
/// It is usually used to signal `None` to a contract when only a primitive is allowed
113114
/// and we don't want to go through encoding a full Rust type. Using `u32::Max` is a safe
@@ -1275,7 +1276,7 @@ impl<T: Config> Pallet<T> {
12751276
gas_limit: Weight,
12761277
storage_deposit_limit: BalanceOf<T>,
12771278
data: Vec<u8>,
1278-
exec_config: ExecConfig,
1279+
exec_config: ExecConfig<T>,
12791280
) -> ContractResult<ExecReturnValue, BalanceOf<T>> {
12801281
if let Err(contract_result) = Self::ensure_non_contract_if_signed(&origin) {
12811282
return contract_result;
@@ -1334,12 +1335,13 @@ impl<T: Config> Pallet<T> {
13341335
code: Code,
13351336
data: Vec<u8>,
13361337
salt: Option<[u8; 32]>,
1337-
exec_config: ExecConfig,
1338+
exec_config: ExecConfig<T>,
13381339
) -> ContractResult<InstantiateReturnValue, BalanceOf<T>> {
13391340
// Enforce EIP-3607 for top-level signed origins: deny signed contract addresses.
13401341
if let Err(contract_result) = Self::ensure_non_contract_if_signed(&origin) {
13411342
return contract_result;
13421343
}
1344+
13431345
let mut gas_meter = GasMeter::new(gas_limit);
13441346
let mut storage_deposit = Default::default();
13451347
let try_instantiate = || {
@@ -1853,7 +1855,7 @@ impl<T: Config> Pallet<T> {
18531855
origin: T::AccountId,
18541856
code: Vec<u8>,
18551857
storage_deposit_limit: BalanceOf<T>,
1856-
exec_config: &ExecConfig,
1858+
exec_config: &ExecConfig<T>,
18571859
) -> Result<(ContractBlob<T>, BalanceOf<T>), DispatchError> {
18581860
let mut module = ContractBlob::from_pvm_code(code, origin)?;
18591861
let deposit = module.store_code(exec_config, None)?;
@@ -1881,7 +1883,7 @@ impl<T: Config> Pallet<T> {
18811883
}
18821884

18831885
/// Convert a weight to a gas value.
1884-
fn evm_gas_from_weight(weight: Weight) -> U256 {
1886+
pub fn evm_gas_from_weight(weight: Weight) -> U256 {
18851887
T::FeeInfo::weight_to_fee(weight).into()
18861888
}
18871889

@@ -1967,7 +1969,7 @@ impl<T: Config> Pallet<T> {
19671969
from: &T::AccountId,
19681970
to: &T::AccountId,
19691971
amount: BalanceOf<T>,
1970-
exec_config: &ExecConfig,
1972+
exec_config: &ExecConfig<T>,
19711973
) -> DispatchResult {
19721974
use frame_support::traits::tokens::{Fortitude, Precision, Preservation};
19731975
match (exec_config.collect_deposit_from_hold, hold_reason) {
@@ -2012,7 +2014,7 @@ impl<T: Config> Pallet<T> {
20122014
from: &T::AccountId,
20132015
to: &T::AccountId,
20142016
amount: BalanceOf<T>,
2015-
exec_config: &ExecConfig,
2017+
exec_config: &ExecConfig<T>,
20162018
) -> Result<BalanceOf<T>, DispatchError> {
20172019
use frame_support::traits::{
20182020
tokens::{Fortitude, Precision, Preservation, Restriction},

0 commit comments

Comments
 (0)