diff --git a/.github/workflows/tests-evm.yml b/.github/workflows/tests-evm.yml index 5b6886b4ebace..9afb8c0bb30cc 100644 --- a/.github/workflows/tests-evm.yml +++ b/.github/workflows/tests-evm.yml @@ -112,7 +112,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: repository: paritytech/evm-test-suite - ref: 460b2c9aa3a3019d3508bb5a34a2498ea86035ff + ref: 372e9b48d375a63297d6e553a70a89c4e9dfa14e path: evm-test-suite - uses: denoland/setup-deno@v1 diff --git a/Cargo.lock b/Cargo.lock index a24a305de68d2..379b06523c6f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13350,6 +13350,7 @@ dependencies = [ "sp-io", "sp-rpc", "sp-runtime", + "sp-timestamp", "sp-weights", "sqlx", "static_init", diff --git a/prdoc/pr_10191.prdoc b/prdoc/pr_10191.prdoc new file mode 100644 index 0000000000000..65fcae310e423 --- /dev/null +++ b/prdoc/pr_10191.prdoc @@ -0,0 +1,30 @@ +title: 'pallet_revive: Add dry-run timestamp override support' +doc: +- audience: Runtime User + description: |- + # Description + + This PR updates `pallet-revive` to **support overriding the block timestamp during dry-run calls**. + The dry-run execution now uses the following configuration for `eth_estimateGas` and `eth_call` when the block tag is `pending`: + + ```text + block.timestamp = max(rpc_timestamp, latest_block.timestamp + 1) + block.number = latest_block.number + 1 + ``` + + Fixes [#153](https://github.com/paritytech/contract-issues/issues/153), [#205](https://github.com/paritytech/contract-issues/issues/205) + + ## Integration + + Downstream projects using the `ReviveApi::eth_transact` runtime API should either provide a `timestamp` or pass `None`. + + ## Review Notes + - Added dry run timestamp to `ExecConfig`. + - Added a new parameter to `ReviveApi::eth_transact` for passing the current RPC timestamp. + - `eth_estimateGas` defaults to the `pending` block tag. + - `eth_estimateGas` and `eth_call` with `pending` block tag will dry run the transaction with the block timestamp set to `max(rpc_timestamp, latest_block.timestamp + 1)` and block number set to `latest_block.number + 1`. +crates: +- name: pallet-revive-eth-rpc + bump: major +- name: pallet-revive + bump: major diff --git a/substrate/frame/revive/rpc/Cargo.toml b/substrate/frame/revive/rpc/Cargo.toml index 1c387d80e4d05..60af7f08f8e7b 100644 --- a/substrate/frame/revive/rpc/Cargo.toml +++ b/substrate/frame/revive/rpc/Cargo.toml @@ -41,6 +41,7 @@ sp-core = { workspace = true, default-features = true } sp-crypto-hashing = { workspace = true } sp-rpc = { workspace = true, default-features = true } sp-runtime = { workspace = true, default-features = true } +sp-timestamp = { workspace = true } sp-weights = { workspace = true, default-features = true } sqlx = { workspace = true, features = ["macros", "runtime-tokio", "sqlite"] } subxt = { workspace = true, default-features = true, features = ["reconnecting-rpc-client"] } diff --git a/substrate/frame/revive/rpc/src/client/runtime_api.rs b/substrate/frame/revive/rpc/src/client/runtime_api.rs index 8db3df914c539..20a787c4d0479 100644 --- a/substrate/frame/revive/rpc/src/client/runtime_api.rs +++ b/substrate/frame/revive/rpc/src/client/runtime_api.rs @@ -20,12 +20,17 @@ use crate::{ subxt_client::{self, SrcChainConfig}, ClientError, }; +use futures::TryFutureExt; use pallet_revive::{ - evm::{Block as EthBlock, GenericTransaction, ReceiptGasInfo, Trace, H160, U256}, - EthTransactInfo, + evm::{ + Block as EthBlock, BlockNumberOrTagOrHash, BlockTag, GenericTransaction, ReceiptGasInfo, + Trace, H160, U256, + }, + DryRunConfig, EthTransactInfo, }; use sp_core::H256; -use subxt::OnlineClient; +use sp_timestamp::Timestamp; +use subxt::{error::MetadataError, ext::subxt_rpcs::UserError, Error::Metadata, OnlineClient}; const LOG_TARGET: &str = "eth-rpc::runtime_api"; @@ -65,9 +70,48 @@ impl RuntimeApi { pub async fn dry_run( &self, tx: GenericTransaction, + block: BlockNumberOrTagOrHash, ) -> Result, ClientError> { - let payload = subxt_client::apis().revive_api().eth_transact(tx.into()); - let result = self.0.call(payload).await?; + let timestamp_override = match block { + BlockNumberOrTagOrHash::BlockTag(BlockTag::Pending) => + Some(Timestamp::current().as_millis()), + _ => None, + }; + + let payload = subxt_client::apis() + .revive_api() + .eth_transact_with_config( + tx.clone().into(), + DryRunConfig::new(timestamp_override).into(), + ) + .unvalidated(); + + let result = self + .0 + .call(payload) + .or_else(|err| async { + match err { + // This will be hit if subxt metadata (subxt uses the latest finalized block + // metadata when the eth-rpc starts) does not contain the new method + Metadata(MetadataError::RuntimeMethodNotFound(name)) => { + log::debug!(target: LOG_TARGET, "Method {name:?} not found falling back to eth_transact"); + let payload = subxt_client::apis().revive_api().eth_transact(tx.into()); + self.0.call(payload).await + }, + // This will be hit if we are trying to hit a block where the runtime did not + // have this new runtime `eth_transact_with_config` defined + subxt::Error::Rpc(subxt::error::RpcError::ClientError( + subxt::ext::subxt_rpcs::Error::User(UserError { message, .. }), + )) if message.contains("eth_transact_with_config is not found") => { + log::debug!(target: LOG_TARGET, "{message:?} not found falling back to eth_transact"); + let payload = subxt_client::apis().revive_api().eth_transact(tx.into()); + self.0.call(payload).await + }, + e => Err(e), + } + }) + .await?; + match result { Err(err) => { log::debug!(target: LOG_TARGET, "Dry run failed {err:?}"); diff --git a/substrate/frame/revive/rpc/src/lib.rs b/substrate/frame/revive/rpc/src/lib.rs index d742ad937f3b9..1e0d9058af366 100644 --- a/substrate/frame/revive/rpc/src/lib.rs +++ b/substrate/frame/revive/rpc/src/lib.rs @@ -145,9 +145,10 @@ impl EthRpcServer for EthRpcServerImpl { block: Option, ) -> RpcResult { log::trace!(target: LOG_TARGET, "estimate_gas transaction={transaction:?} block={block:?}"); - let hash = self.client.block_hash_for_tag(block.unwrap_or_default().into()).await?; + let block = block.unwrap_or_default(); + let hash = self.client.block_hash_for_tag(block.clone().into()).await?; let runtime_api = self.client.runtime_api(hash); - let dry_run = runtime_api.dry_run(transaction).await?; + let dry_run = runtime_api.dry_run(transaction, block.into()).await?; log::trace!(target: LOG_TARGET, "estimate_gas result={dry_run:?}"); Ok(dry_run.eth_gas) } @@ -157,9 +158,10 @@ impl EthRpcServer for EthRpcServerImpl { transaction: GenericTransaction, block: Option, ) -> RpcResult { - let hash = self.client.block_hash_for_tag(block.unwrap_or_default()).await?; + let block = block.unwrap_or_default(); + let hash = self.client.block_hash_for_tag(block.clone()).await?; let runtime_api = self.client.runtime_api(hash); - let dry_run = runtime_api.dry_run(transaction).await?; + let dry_run = runtime_api.dry_run(transaction, block).await?; Ok(dry_run.data.into()) } diff --git a/substrate/frame/revive/rpc/src/subxt_client.rs b/substrate/frame/revive/rpc/src/subxt_client.rs index 3daa45df36b32..bd9666aba8b3e 100644 --- a/substrate/frame/revive/rpc/src/subxt_client.rs +++ b/substrate/frame/revive/rpc/src/subxt_client.rs @@ -47,6 +47,10 @@ pub use subxt::config::PolkadotConfig as SrcChainConfig; path = "pallet_revive::evm::api::rpc_types_gen::GenericTransaction", with = "::subxt::utils::Static<::pallet_revive::evm::GenericTransaction>" ), + substitute_type( + path = "pallet_revive::evm::api::rpc_types::DryRunConfig", + with = "::subxt::utils::Static<::pallet_revive::evm::DryRunConfig>" + ), substitute_type( path = "pallet_revive::primitives::EthTransactInfo", with = "::subxt::utils::Static<::pallet_revive::EthTransactInfo>" diff --git a/substrate/frame/revive/src/evm/api.rs b/substrate/frame/revive/src/evm/api.rs index 7a34fdc83f9a5..95cfcdda0e835 100644 --- a/substrate/frame/revive/src/evm/api.rs +++ b/substrate/frame/revive/src/evm/api.rs @@ -31,6 +31,8 @@ mod debug_rpc_types; pub use debug_rpc_types::*; mod rpc_types; +pub use rpc_types::DryRunConfig; + mod rpc_types_gen; pub use rpc_types_gen::*; diff --git a/substrate/frame/revive/src/evm/api/rpc_types.rs b/substrate/frame/revive/src/evm/api/rpc_types.rs index 73681573107cf..aa2dd04defcdf 100644 --- a/substrate/frame/revive/src/evm/api/rpc_types.rs +++ b/substrate/frame/revive/src/evm/api/rpc_types.rs @@ -17,8 +17,29 @@ //! Utility impl for the RPC types. use super::*; use alloc::vec::Vec; +use codec::{Decode, Encode}; +use frame_support::DefaultNoBound; +use scale_info::TypeInfo; use sp_core::{H160, U256}; +/// Configuration specific to a dry-run execution. +#[derive(Debug, Encode, Decode, TypeInfo, Clone, DefaultNoBound)] +pub struct DryRunConfig { + /// Optional timestamp override for dry-run in pending block. + pub timestamp_override: Option, + /// Used for future extensions without breaking encoding. + pub reserved: Option<()>, +} +impl DryRunConfig { + /// Create a new `DryRunConfig` with an optional timestamp override. + pub fn new(timestamp_override: Option) -> Self { + Self { + timestamp_override, + reserved: None, // default value + } + } +} + impl From for BlockNumberOrTagOrHash { fn from(b: BlockNumberOrTag) -> Self { match b { diff --git a/substrate/frame/revive/src/evm/runtime.rs b/substrate/frame/revive/src/evm/runtime.rs index c7edc432b051b..74e6e4b67d267 100644 --- a/substrate/frame/revive/src/evm/runtime.rs +++ b/substrate/frame/revive/src/evm/runtime.rs @@ -429,7 +429,8 @@ mod test { let account = Account::default(); Self::fund_account(&account); - let dry_run = crate::Pallet::::dry_run_eth_transact(self.tx.clone()); + let dry_run = + crate::Pallet::::dry_run_eth_transact(self.tx.clone(), Default::default()); self.tx.gas_price = Some(>::evm_base_fee()); match dry_run { diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 4115cd5c6895b..617c45ec2b099 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -38,7 +38,7 @@ use alloc::{ collections::{BTreeMap, BTreeSet}, vec::Vec, }; -use core::{fmt::Debug, marker::PhantomData, mem, ops::ControlFlow}; +use core::{cmp, fmt::Debug, marker::PhantomData, mem, ops::ControlFlow}; use frame_support::{ crypto::ecdsa::ECDSAExt, dispatch::DispatchResult, @@ -951,12 +951,24 @@ where return Ok(None); }; + let mut timestamp = T::Time::now(); + let mut block_number = >::block_number(); + // if dry run with timestamp override is provided we simulate the run in a `pending` block + if let Some(timestamp_override) = + exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override) + { + block_number = block_number.saturating_add(1u32.into()); + // Delta is in milliseconds; increment timestamp by one second + let delta = 1000u32.into(); + timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override); + } + let stack = Self { origin, gas_meter, storage_meter, - timestamp: T::Time::now(), - block_number: >::block_number(), + timestamp, + block_number, first_frame, frames: Default::default(), transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES), @@ -965,7 +977,6 @@ where contracts_to_be_destroyed: BTreeMap::new(), _phantom: Default::default(), }; - Ok(Some((stack, executable))) } @@ -1324,7 +1335,7 @@ where // When a dry-run simulates contract deployment, keep the execution result's // data. let data = if crate::tracing::if_tracing(|_| {}).is_none() && - !self.exec_config.is_dry_run + self.exec_config.is_dry_run.is_none() { core::mem::replace(&mut output.data, Default::default()) } else { @@ -1411,7 +1422,6 @@ where } else { self.transient_storage.rollback_transaction(); } - log::trace!(target: LOG_TARGET, "frame finished with: {output:?}"); self.pop_frame(success); diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 2e3fee1a89b83..fc2be4aac0b7e 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -74,7 +74,7 @@ use frame_support::{ traits::{ fungible::{Balanced, Inspect, Mutate, MutateHold}, tokens::Balance, - ConstU32, ConstU64, EnsureOrigin, Get, IsSubType, IsType, OriginTrait, Time, + ConstU32, ConstU64, EnsureOrigin, Get, IsSubType, IsType, OriginTrait, }, weights::WeightMeter, BoundedVec, RuntimeDebugNoBound, @@ -95,14 +95,17 @@ pub use crate::{ create1, create2, is_eth_derived, AccountId32Mapper, AddressMapper, TestAccountMapper, }, debug::DebugSettings, - evm::{block_hash::ReceiptGasInfo, Address as EthAddress, Block as EthBlock, ReceiptInfo}, + evm::{ + block_hash::ReceiptGasInfo, Address as EthAddress, Block as EthBlock, DryRunConfig, + ReceiptInfo, + }, exec::{DelegateInfo, Executable, Key, MomentOf, Origin as ExecOrigin}, pallet::{genesis, *}, storage::{AccountInfo, ContractInfo}, vm::{BytecodeType, ContractBlob}, }; pub use codec; -pub use frame_support::{self, dispatch::DispatchInfo, weights::Weight}; +pub use frame_support::{self, dispatch::DispatchInfo, traits::Time, weights::Weight}; pub use frame_system::{self, limits::BlockWeights}; pub use primitives::*; pub use sp_core::{keccak_256, H160, H256, U256}; @@ -1608,6 +1611,7 @@ impl Pallet { /// - `tx`: The Ethereum transaction to simulate. pub fn dry_run_eth_transact( mut tx: GenericTransaction, + dry_run_config: DryRunConfig<<::Time as Time>::Moment>, ) -> Result>, EthTransactError> where T::Nonce: Into, @@ -1672,7 +1676,7 @@ impl Pallet { call_info.encoded_len, base_info.total_weight(), ) - .with_dry_run() + .with_dry_run(dry_run_config) }; // emulate transaction behavior @@ -1688,7 +1692,7 @@ impl Pallet { } // the deposit is done when the transaction is transformed from an `eth_transact` - // we emulate this behavior for the dry-run her + // we emulate this behavior for the dry-run here T::FeeInfo::deposit_txfee(T::Currency::issue(fees)); let extract_error = |err| { @@ -2335,11 +2339,12 @@ environmental!(executing_contract: bool); sp_api::decl_runtime_apis! { /// The API used to dry-run contract interactions. #[api_version(1)] - pub trait ReviveApi where + pub trait ReviveApi where AccountId: Codec, Balance: Codec, Nonce: Codec, BlockNumber: Codec, + Moment: Codec, { /// Returns the current ETH block. /// @@ -2396,9 +2401,18 @@ sp_api::decl_runtime_apis! { /// Perform an Ethereum call. /// + /// Deprecated use `v2` version instead. /// See [`crate::Pallet::dry_run_eth_transact`] fn eth_transact(tx: GenericTransaction) -> Result, EthTransactError>; + /// Perform an Ethereum call. + /// + /// See [`crate::Pallet::dry_run_eth_transact`] + fn eth_transact_with_config( + tx: GenericTransaction, + config: DryRunConfig, + ) -> Result, EthTransactError>; + /// Upload new code without instantiating a contract from it. /// /// See [`crate::Pallet::bare_upload_code`]. @@ -2493,6 +2507,8 @@ sp_api::decl_runtime_apis! { macro_rules! impl_runtime_apis_plus_revive_traits { ($Runtime: ty, $Revive: ident, $Executive: ty, $EthExtra: ty, $($rest:tt)*) => { + type __ReviveMacroMoment = <<$Runtime as $crate::Config>::Time as $crate::Time>::Moment; + impl $crate::evm::runtime::SetWeightLimit for RuntimeCall { fn set_weight_limit(&mut self, weight_limit: Weight) -> Weight { use $crate::pallet::Call as ReviveCall; @@ -2513,7 +2529,9 @@ macro_rules! impl_runtime_apis_plus_revive_traits { impl_runtime_apis! { $($rest)* - impl pallet_revive::ReviveApi for $Runtime { + + impl pallet_revive::ReviveApi for $Runtime + { fn eth_block() -> $crate::EthBlock { $crate::Pallet::::eth_block() } @@ -2561,7 +2579,19 @@ macro_rules! impl_runtime_apis_plus_revive_traits { sp_runtime::traits::TransactionExtension, sp_runtime::traits::Block as BlockT }; - $crate::Pallet::::dry_run_eth_transact(tx) + $crate::Pallet::::dry_run_eth_transact(tx, Default::default()) + } + + fn eth_transact_with_config( + tx: $crate::evm::GenericTransaction, + config: $crate::DryRunConfig<__ReviveMacroMoment>, + ) -> Result<$crate::EthTransactInfo, $crate::EthTransactError> { + use $crate::{ + codec::Encode, evm::runtime::EthExtra, frame_support::traits::Get, + sp_runtime::traits::TransactionExtension, + sp_runtime::traits::Block as BlockT + }; + $crate::Pallet::::dry_run_eth_transact(tx, config) } fn call( @@ -2584,7 +2614,7 @@ macro_rules! impl_runtime_apis_plus_revive_traits { gas_limit.unwrap_or(blockweights.max_block), storage_deposit_limit.unwrap_or(u128::MAX), input_data, - $crate::ExecConfig::new_substrate_tx().with_dry_run(), + $crate::ExecConfig::new_substrate_tx().with_dry_run(Default::default()), ) } @@ -2610,7 +2640,7 @@ macro_rules! impl_runtime_apis_plus_revive_traits { code, data, salt, - $crate::ExecConfig::new_substrate_tx().with_dry_run(), + $crate::ExecConfig::new_substrate_tx().with_dry_run(Default::default()), ) } diff --git a/substrate/frame/revive/src/primitives.rs b/substrate/frame/revive/src/primitives.rs index d1ab4203ede0b..3f96e4495617c 100644 --- a/substrate/frame/revive/src/primitives.rs +++ b/substrate/frame/revive/src/primitives.rs @@ -17,7 +17,10 @@ //! A crate that hosts a common definitions that are relevant for the pallet-revive. -use crate::{mock::MockHandler, storage::WriteOutcome, BalanceOf, Config, H160, U256}; +use crate::{ + evm::DryRunConfig, mock::MockHandler, storage::WriteOutcome, BalanceOf, Config, Time, H160, + U256, +}; use alloc::{boxed::Box, fmt::Debug, string::String, vec::Vec}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::weights::Weight; @@ -360,7 +363,7 @@ pub struct ExecConfig { pub effective_gas_price: Option, /// Whether this configuration was created for a dry-run execution. /// Use to enable logic that should only run in dry-run mode. - pub is_dry_run: bool, + pub is_dry_run: Option::Time as Time>::Moment>>, /// An optional mock handler that can be used to override certain behaviors. /// This is primarily used for testing purposes and should be `None` in production /// environments. @@ -374,7 +377,7 @@ impl ExecConfig { bump_nonce: true, collect_deposit_from_hold: None, effective_gas_price: None, - is_dry_run: false, + is_dry_run: None, mock_handler: None, } } @@ -385,7 +388,7 @@ impl ExecConfig { collect_deposit_from_hold: None, effective_gas_price: None, mock_handler: None, - is_dry_run: false, + is_dry_run: None, } } @@ -396,13 +399,16 @@ impl ExecConfig { collect_deposit_from_hold: Some((encoded_len, base_weight)), effective_gas_price: Some(effective_gas_price), mock_handler: None, - is_dry_run: false, + is_dry_run: None, } } /// Set this config to be a dry-run. - pub fn with_dry_run(mut self) -> Self { - self.is_dry_run = true; + pub fn with_dry_run( + mut self, + dry_run_config: DryRunConfig<<::Time as Time>::Moment>, + ) -> Self { + self.is_dry_run = Some(dry_run_config); self } } diff --git a/substrate/frame/revive/src/tests/sol/block_info.rs b/substrate/frame/revive/src/tests/sol/block_info.rs index 15c186b6df0bf..628010044f5f3 100644 --- a/substrate/frame/revive/src/tests/sol/block_info.rs +++ b/substrate/frame/revive/src/tests/sol/block_info.rs @@ -21,7 +21,7 @@ use crate::{ test_utils::{builder::Contract, ALICE}, tests::{builder, Contracts, ExtBuilder, System, Test, Timestamp}, vm::evm::DIFFICULTY, - Code, Config, Pallet, + Code, Config, DryRunConfig, ExecConfig, Pallet, }; use alloy_core::sol_types::{SolCall, SolInterface}; @@ -53,6 +53,31 @@ fn block_number_works(fixture_type: FixtureType) { }); } +#[test_case(FixtureType::Solc)] +#[test_case(FixtureType::Resolc)] +fn block_number_dry_run_works(fixture_type: FixtureType) { + let (code, _) = compile_module_with_type("BlockInfo", fixture_type).unwrap(); + ExtBuilder::default().build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + + System::set_block_number(42); + let timestamp_override = Some(Timestamp::get() + 10_000); + + let result = builder::bare_call(addr) + .data( + BlockInfo::BlockInfoCalls::blockNumber(BlockInfo::blockNumberCall {}).abi_encode(), + ) + .exec_config( + ExecConfig::new_substrate_tx().with_dry_run(DryRunConfig::new(timestamp_override)), + ) + .build_and_unwrap_result(); + let decoded = BlockInfo::blockNumberCall::abi_decode_returns(&result.data).unwrap(); + assert_eq!(43u64, decoded); + }); +} + /// Tests that the blockauthor opcode works as expected. #[test_case(FixtureType::Solc)] #[test_case(FixtureType::Resolc)] @@ -113,6 +138,33 @@ fn timestamp_works(fixture_type: FixtureType) { }); } +#[test_case(FixtureType::Solc)] +#[test_case(FixtureType::Resolc)] +fn timestamp_dry_run_override_works(fixture_type: FixtureType) { + let (code, _) = compile_module_with_type("BlockInfo", fixture_type).unwrap(); + ExtBuilder::default().build().execute_with(|| { + Timestamp::set_timestamp(2000); + let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + let timestamp_override = Timestamp::get() + 10_000; + let result: crate::ExecReturnValue = builder::bare_call(addr) + .data(BlockInfo::BlockInfoCalls::timestamp(BlockInfo::timestampCall {}).abi_encode()) + .exec_config( + ExecConfig::new_substrate_tx() + .with_dry_run(DryRunConfig::new(Some(timestamp_override))), + ) + .build_and_unwrap_result(); + let decoded = BlockInfo::timestampCall::abi_decode_returns(&result.data).unwrap(); + assert_eq!( + // Solidity expects timestamps in seconds, whereas pallet_timestamp uses + // milliseconds. + (timestamp_override / 1000) as u64, + decoded + ); + }); +} + /// Tests that the gaslimit opcode works as expected. #[test_case(FixtureType::Solc)] #[test_case(FixtureType::Resolc)] diff --git a/substrate/frame/revive/src/tests/sol/contract.rs b/substrate/frame/revive/src/tests/sol/contract.rs index 74144ac3db845..542bd41420425 100644 --- a/substrate/frame/revive/src/tests/sol/contract.rs +++ b/substrate/frame/revive/src/tests/sol/contract.rs @@ -400,7 +400,7 @@ fn mock_caller_hook_works(caller_type: FixtureType, callee_type: FixtureType) { bump_nonce: false, collect_deposit_from_hold: None, effective_gas_price: None, - is_dry_run: false, + is_dry_run: None, mock_handler: Some(Box::new(MockHandlerImpl { mock_caller: Some(BOB_ADDR), mock_call: Default::default(), @@ -453,7 +453,7 @@ fn mock_call_hook_works(caller_type: FixtureType, callee_type: FixtureType) { bump_nonce: false, collect_deposit_from_hold: None, effective_gas_price: None, - is_dry_run: false, + is_dry_run: None, mock_handler: Some(Box::new(MockHandlerImpl { mock_caller: None, mock_call: iter::once(( @@ -513,7 +513,7 @@ fn mock_delegatecall_hook_works(caller_type: FixtureType, callee_type: FixtureTy bump_nonce: false, collect_deposit_from_hold: None, effective_gas_price: None, - is_dry_run: false, + is_dry_run: None, mock_handler: Some(Box::new(MockHandlerImpl { mock_caller: None, mock_call: Default::default(),