From c397631778e180d34d86c46142b0541899ef2cd4 Mon Sep 17 00:00:00 2001 From: alindima Date: Fri, 21 Nov 2025 14:43:14 +0200 Subject: [PATCH 1/5] pallet-revive: add DebugSetting for bypassing eip-3607 Only works for contract accounts, not precompiles. This is needed so that test nodes like anvil can send transactions from contract accounts, a widely-used feature in tests --- Cargo.lock | 1 + substrate/frame/revive/Cargo.toml | 1 + substrate/frame/revive/src/debug.rs | 11 +- substrate/frame/revive/src/lib.rs | 2 +- substrate/frame/revive/src/tests/pvm.rs | 174 ++++++++++++++++++------ substrate/frame/revive/src/tests/sol.rs | 2 +- 6 files changed, 142 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae446c1f38fdd..be445fa620e1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13307,6 +13307,7 @@ dependencies = [ "revm", "ripemd", "rlp 0.6.1", + "rstest", "scale-info", "secp256k1 0.28.2", "serde", diff --git a/substrate/frame/revive/Cargo.toml b/substrate/frame/revive/Cargo.toml index d51d6db753546..7d3c0f2c69884 100644 --- a/substrate/frame/revive/Cargo.toml +++ b/substrate/frame/revive/Cargo.toml @@ -70,6 +70,7 @@ alloy-consensus = { workspace = true, default-features = true } array-bytes = { workspace = true, default-features = true } assert_matches = { workspace = true } pretty_assertions = { workspace = true } +rstest = { workspace = true } secp256k1 = { workspace = true, features = ["recovery"] } serde_json = { workspace = true } test-case = { workspace = true } diff --git a/substrate/frame/revive/src/debug.rs b/substrate/frame/revive/src/debug.rs index 82cea3e8c308e..081f786d2a21b 100644 --- a/substrate/frame/revive/src/debug.rs +++ b/substrate/frame/revive/src/debug.rs @@ -38,11 +38,13 @@ use sp_runtime::RuntimeDebug; pub struct DebugSettings { /// Whether to allow unlimited contract size. allow_unlimited_contract_size: bool, + /// Whether to allow bypassing EIP-3607 (allowing transactions coming from contract accounts). + bypass_eip_3607: bool, } impl DebugSettings { - pub fn new(allow_unlimited_contract_size: bool) -> Self { - Self { allow_unlimited_contract_size } + pub fn new(allow_unlimited_contract_size: bool, bypass_eip_3607: bool) -> Self { + Self { allow_unlimited_contract_size, bypass_eip_3607 } } /// Returns true if unlimited contract size is allowed. @@ -50,6 +52,11 @@ impl DebugSettings { T::DebugEnabled::get() && DebugSettingsOf::::get().allow_unlimited_contract_size } + /// Returns true if transactions coming from contract accounts are allowed (bypassing EIP-3607) + pub fn bypass_eip_3607() -> bool { + T::DebugEnabled::get() && DebugSettingsOf::::get().bypass_eip_3607 + } + /// Write the debug settings to storage. pub fn write_to_storage(&self) { DebugSettingsOf::::put(self); diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 3b6f884711f7a..b2b9ea640e31c 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -2376,7 +2376,7 @@ impl Pallet { return Ok(()) }; if exec::is_precompile::>(&address) || - >::is_contract(&address) + (>::is_contract(&address) && !DebugSettings::bypass_eip_3607::()) { log::debug!( target: crate::LOG_TARGET, diff --git a/substrate/frame/revive/src/tests/pvm.rs b/substrate/frame/revive/src/tests/pvm.rs index fc163113453b4..9af9a132a0a4e 100644 --- a/substrate/frame/revive/src/tests/pvm.rs +++ b/substrate/frame/revive/src/tests/pvm.rs @@ -41,8 +41,8 @@ use crate::{ tracing::trace, weights::WeightInfo, AccountInfo, AccountInfoOf, BalanceWithDust, Code, Combinator, Config, ContractInfo, - DeletionQueueCounter, Error, ExecConfig, HoldReason, Origin, Pallet, PristineCode, - StorageDeposit, H160, + DebugSettings, DeletionQueueCounter, Error, ExecConfig, HoldReason, Origin, Pallet, + PristineCode, StorageDeposit, H160, }; use assert_matches::assert_matches; use codec::Encode; @@ -60,6 +60,7 @@ use frame_system::{EventRecord, Phase}; use pallet_revive_fixtures::compile_module; use pallet_revive_uapi::{ReturnErrorCode as RuntimeReturnCode, ReturnFlags}; use pretty_assertions::{assert_eq, assert_ne}; +use rstest::rstest; use sp_core::U256; use sp_io::hashing::blake2_256; use sp_runtime::{ @@ -4944,71 +4945,154 @@ fn storage_deposit_from_hold_works() { }); } -#[test] -fn eip3607_reject_tx_from_contract_or_precompile() { +#[rstest] +#[case(true)] +#[case(false)] +fn eip3607_reject_tx_from_contract_or_precompile(#[case] bypass_eip3607_for_contracts: bool) { let (binary, _code_hash) = compile_module("dummy").unwrap(); - ExtBuilder::default().existential_deposit(200).build().execute_with(|| { - let _ = ::Currency::set_balance(&ALICE, 1_000_000); + let genesis_config = GenesisConfig:: { + debug_settings: Some(DebugSettings::new(false, bypass_eip3607_for_contracts)), + ..Default::default() + }; + + ExtBuilder::default() + .genesis_config(Some(genesis_config)) + .existential_deposit(200) + .build() + .execute_with(|| { + DebugFlag::set(bypass_eip3607_for_contracts); + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + + // the origins from which we try to call a dispatchable + let Contract { addr: contract_addr, .. } = + builder::bare_instantiate(Code::Upload(binary)).build_and_unwrap_contract(); + assert!(>::is_contract(&contract_addr)); + let blake2_addr = H160::from_low_u64_be(9); + let system_addr = H160::from_low_u64_be(0x900); + let mut addresses = vec![blake2_addr, system_addr]; + + if !bypass_eip3607_for_contracts { + // If we are setting the bypass config to true, it will only take effect for + // contracts, not for precompiles. So if it's not true, we can also test for the + // contract. + addresses.push(contract_addr); + } - // the origins from which we try to call a dispatchable - let Contract { addr: contract_addr, .. } = - builder::bare_instantiate(Code::Upload(binary)).build_and_unwrap_contract(); - assert!(>::is_contract(&contract_addr)); - let blake2_addr = H160::from_low_u64_be(9); - let system_addr = H160::from_low_u64_be(0x900); - let addresses = [contract_addr, blake2_addr, system_addr]; + // used to test `dispatch_as_fallback_account` + let call = Box::new(RuntimeCall::Balances(pallet_balances::Call::transfer_all { + dest: EVE, + keep_alive: false, + })); + + for address in addresses.iter() { + let origin = ::AddressMapper::to_fallback_account_id(address); + + let result = + builder::call(BOB_ADDR).origin(RuntimeOrigin::signed(origin.clone())).build(); + assert_err!(result, DispatchError::BadOrigin); + + let result = builder::eth_call(BOB_ADDR) + .origin(Origin::EthTransaction(origin.clone()).into()) + .build(); + assert_err!(result, DispatchError::BadOrigin); + + let result = builder::instantiate(Default::default()) + .origin(RuntimeOrigin::signed(origin.clone())) + .build(); + assert_err!(result, DispatchError::BadOrigin); + + let result = builder::eth_instantiate_with_code(Default::default()) + .origin(Origin::EthTransaction(origin.clone()).into()) + .build(); + assert_err!(result, DispatchError::BadOrigin); + + let result = builder::instantiate_with_code(Default::default()) + .origin(RuntimeOrigin::signed(origin.clone())) + .build(); + assert_err!(result, DispatchError::BadOrigin); + + let result = >::upload_code( + RuntimeOrigin::signed(origin.clone()), + Default::default(), + >::MAX, + ); + assert_err!(result, DispatchError::BadOrigin); + + let result = >::map_account(RuntimeOrigin::signed(origin.clone())); + assert_err!(result, DispatchError::BadOrigin); + + let result = >::dispatch_as_fallback_account( + RuntimeOrigin::signed(origin.clone()), + call.clone(), + ); + assert_err!(result, DispatchError::BadOrigin); + } + }); +} - // used to test `dispatch_as_fallback_account` - let call = Box::new(RuntimeCall::Balances(pallet_balances::Call::transfer_all { - dest: EVE, - keep_alive: false, - })); +#[test] +fn eip3607_allow_tx_from_contract_if_debug_setting_configured() { + let (binary, code_hash) = compile_module("dummy").unwrap(); + + let genesis_config = GenesisConfig:: { + debug_settings: Some(DebugSettings::new(false, true)), + ..Default::default() + }; + + ExtBuilder::default() + .genesis_config(Some(genesis_config)) + .existential_deposit(200) + .build() + .execute_with(|| { + DebugFlag::set(true); + + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + + // the origins from which we try to call a dispatchable + let Contract { addr: address, account_id } = + builder::bare_instantiate(Code::Upload(binary.clone())).build_and_unwrap_contract(); + let _ = ::Currency::set_balance(&account_id, 10_000_000_000_000); - for address in addresses.iter() { - let origin = ::AddressMapper::to_fallback_account_id(address); + assert!(>::is_contract(&address)); + + let origin = ::AddressMapper::to_fallback_account_id(&address); let result = builder::call(BOB_ADDR).origin(RuntimeOrigin::signed(origin.clone())).build(); - assert_err!(result, DispatchError::BadOrigin); + assert_ok!(result); let result = builder::eth_call(BOB_ADDR) - .origin(RuntimeOrigin::signed(origin.clone())) - .build(); - assert_err!(result, DispatchError::BadOrigin); - - let result = builder::instantiate(Default::default()) - .origin(RuntimeOrigin::signed(origin.clone())) + .origin(Origin::EthTransaction(origin.clone()).into()) .build(); - assert_err!(result, DispatchError::BadOrigin); + assert_ok!(result); - let result = builder::eth_instantiate_with_code(Default::default()) + let result = builder::instantiate(code_hash) .origin(RuntimeOrigin::signed(origin.clone())) .build(); - assert_err!(result, DispatchError::BadOrigin); + assert_ok!(result); - let result = builder::instantiate_with_code(Default::default()) - .origin(RuntimeOrigin::signed(origin.clone())) + let result = builder::eth_instantiate_with_code(binary.clone()) + .origin(Origin::EthTransaction(origin.clone()).into()) .build(); - assert_err!(result, DispatchError::BadOrigin); + assert_ok!(result); - let result = >::upload_code( + let result = >::dispatch_as_fallback_account( RuntimeOrigin::signed(origin.clone()), - Default::default(), - >::MAX, + Box::new(RuntimeCall::Balances(pallet_balances::Call::transfer_all { + dest: EVE, + keep_alive: false, + })), ); - assert_err!(result, DispatchError::BadOrigin); - - let result = >::map_account(RuntimeOrigin::signed(origin.clone())); - assert_err!(result, DispatchError::BadOrigin); + assert_ok!(result); - let result = >::dispatch_as_fallback_account( + let result = >::upload_code( RuntimeOrigin::signed(origin.clone()), - call.clone(), + binary, + >::MAX, ); - assert_err!(result, DispatchError::BadOrigin); - } - }); + assert_ok!(result); + }); } #[test] diff --git a/substrate/frame/revive/src/tests/sol.rs b/substrate/frame/revive/src/tests/sol.rs index 4565d6ee796d8..895475c4176ee 100644 --- a/substrate/frame/revive/src/tests/sol.rs +++ b/substrate/frame/revive/src/tests/sol.rs @@ -180,7 +180,7 @@ fn eth_contract_too_large() { // Initialize genesis config with allow_unlimited_contract_size let genesis_config = GenesisConfig:: { - debug_settings: Some(DebugSettings::new(allow_unlimited_contract_size)), + debug_settings: Some(DebugSettings::new(allow_unlimited_contract_size, false)), ..Default::default() }; From defa76f3b155d7097a6409f4300f0d00b0717179 Mon Sep 17 00:00:00 2001 From: alindima Date: Fri, 21 Nov 2025 14:57:08 +0200 Subject: [PATCH 2/5] add prdoc --- prdoc/pr_10387.prdoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 prdoc/pr_10387.prdoc diff --git a/prdoc/pr_10387.prdoc b/prdoc/pr_10387.prdoc new file mode 100644 index 0000000000000..f8d54502fc3c0 --- /dev/null +++ b/prdoc/pr_10387.prdoc @@ -0,0 +1,12 @@ +title: "pallet-revive: add DebugSetting for bypassing eip-3607 for contracts" +doc: +- audience: Runtime Dev + description: |- + Adds a new DebugSetting option which, if enabled, allows transactions coming from contract accounts. + This is needed so that test nodes like anvil can send transactions from + contract accounts, a widely-used feature in tests. + Only works for contract accounts, not precompiles. + +crates: +- name: pallet-revive + bump: major From b373e9dd32bde728bcea9c5e0ef26de08e8962b0 Mon Sep 17 00:00:00 2001 From: alindima Date: Fri, 21 Nov 2025 15:18:51 +0200 Subject: [PATCH 3/5] switch rstest for test_case --- Cargo.lock | 1 - substrate/frame/revive/Cargo.toml | 1 - substrate/frame/revive/src/tests/pvm.rs | 9 ++++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67debd195a180..d42e29dd885d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13353,7 +13353,6 @@ dependencies = [ "revm", "ripemd", "rlp 0.6.1", - "rstest", "scale-info", "secp256k1 0.28.2", "serde", diff --git a/substrate/frame/revive/Cargo.toml b/substrate/frame/revive/Cargo.toml index 7d3c0f2c69884..d51d6db753546 100644 --- a/substrate/frame/revive/Cargo.toml +++ b/substrate/frame/revive/Cargo.toml @@ -70,7 +70,6 @@ alloy-consensus = { workspace = true, default-features = true } array-bytes = { workspace = true, default-features = true } assert_matches = { workspace = true } pretty_assertions = { workspace = true } -rstest = { workspace = true } secp256k1 = { workspace = true, features = ["recovery"] } serde_json = { workspace = true } test-case = { workspace = true } diff --git a/substrate/frame/revive/src/tests/pvm.rs b/substrate/frame/revive/src/tests/pvm.rs index 1592cea59c00a..f4ef18c29b4dc 100644 --- a/substrate/frame/revive/src/tests/pvm.rs +++ b/substrate/frame/revive/src/tests/pvm.rs @@ -60,12 +60,12 @@ use frame_system::{EventRecord, Phase}; use pallet_revive_fixtures::compile_module; use pallet_revive_uapi::{ReturnErrorCode as RuntimeReturnCode, ReturnFlags}; use pretty_assertions::{assert_eq, assert_ne}; -use rstest::rstest; use sp_core::U256; use sp_io::hashing::blake2_256; use sp_runtime::{ testing::H256, AccountId32, BoundedVec, DispatchError, SaturatedConversion, TokenError, }; +use test_case::test_case; #[test] fn eth_call_transfer_with_dust_works() { @@ -4945,10 +4945,9 @@ fn storage_deposit_from_hold_works() { }); } -#[rstest] -#[case(true)] -#[case(false)] -fn eip3607_reject_tx_from_contract_or_precompile(#[case] bypass_eip3607_for_contracts: bool) { +#[test_case(true)] +#[test_case(false)] +fn eip3607_reject_tx_from_contract_or_precompile(bypass_eip3607_for_contracts: bool) { let (binary, _code_hash) = compile_module("dummy").unwrap(); let genesis_config = GenesisConfig:: { From ccfddbb3962ee308474143d87d3a4ca9ef84c118 Mon Sep 17 00:00:00 2001 From: alindima Date: Mon, 24 Nov 2025 12:03:42 +0200 Subject: [PATCH 4/5] allow txs from precompiles as well --- prdoc/pr_10387.prdoc | 7 +- substrate/frame/revive/src/debug.rs | 6 +- substrate/frame/revive/src/lib.rs | 5 +- substrate/frame/revive/src/tests/pvm.rs | 198 +++++++++++------------- 4 files changed, 104 insertions(+), 112 deletions(-) diff --git a/prdoc/pr_10387.prdoc b/prdoc/pr_10387.prdoc index f8d54502fc3c0..f3d2a1afcbb38 100644 --- a/prdoc/pr_10387.prdoc +++ b/prdoc/pr_10387.prdoc @@ -1,11 +1,10 @@ -title: "pallet-revive: add DebugSetting for bypassing eip-3607 for contracts" +title: "pallet-revive: add DebugSetting for bypassing eip-3607 for contracts and precompiles" doc: - audience: Runtime Dev description: |- - Adds a new DebugSetting option which, if enabled, allows transactions coming from contract accounts. + Adds a new DebugSetting option which, if enabled, allows transactions coming from contract accounts or precompiles. This is needed so that test nodes like anvil can send transactions from - contract accounts, a widely-used feature in tests. - Only works for contract accounts, not precompiles. + contract or precompile accounts, a widely-used feature in tests. crates: - name: pallet-revive diff --git a/substrate/frame/revive/src/debug.rs b/substrate/frame/revive/src/debug.rs index 081f786d2a21b..2f031a67db11d 100644 --- a/substrate/frame/revive/src/debug.rs +++ b/substrate/frame/revive/src/debug.rs @@ -38,7 +38,8 @@ use sp_runtime::RuntimeDebug; pub struct DebugSettings { /// Whether to allow unlimited contract size. allow_unlimited_contract_size: bool, - /// Whether to allow bypassing EIP-3607 (allowing transactions coming from contract accounts). + /// Whether to allow bypassing EIP-3607 (allowing transactions coming from contract or + /// precompile accounts). bypass_eip_3607: bool, } @@ -52,7 +53,8 @@ impl DebugSettings { T::DebugEnabled::get() && DebugSettingsOf::::get().allow_unlimited_contract_size } - /// Returns true if transactions coming from contract accounts are allowed (bypassing EIP-3607) + /// Returns true if transactions coming from contract or precompile accounts are allowed + /// (bypassing EIP-3607) pub fn bypass_eip_3607() -> bool { T::DebugEnabled::get() && DebugSettingsOf::::get().bypass_eip_3607 } diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index b2b9ea640e31c..eacf07111e5de 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -2368,6 +2368,9 @@ impl Pallet { /// /// This enforces EIP-3607. fn ensure_non_contract_if_signed(origin: &OriginFor) -> DispatchResult { + if DebugSettings::bypass_eip_3607::() { + return Ok(()) + } let Some(address) = origin .as_system_ref() .and_then(|o| o.as_signed()) @@ -2376,7 +2379,7 @@ impl Pallet { return Ok(()) }; if exec::is_precompile::>(&address) || - (>::is_contract(&address) && !DebugSettings::bypass_eip_3607::()) + >::is_contract(&address) { log::debug!( target: crate::LOG_TARGET, diff --git a/substrate/frame/revive/src/tests/pvm.rs b/substrate/frame/revive/src/tests/pvm.rs index f4ef18c29b4dc..19859393c032a 100644 --- a/substrate/frame/revive/src/tests/pvm.rs +++ b/substrate/frame/revive/src/tests/pvm.rs @@ -65,7 +65,6 @@ use sp_io::hashing::blake2_256; use sp_runtime::{ testing::H256, AccountId32, BoundedVec, DispatchError, SaturatedConversion, TokenError, }; -use test_case::test_case; #[test] fn eth_call_transfer_with_dust_works() { @@ -4945,93 +4944,75 @@ fn storage_deposit_from_hold_works() { }); } -#[test_case(true)] -#[test_case(false)] -fn eip3607_reject_tx_from_contract_or_precompile(bypass_eip3607_for_contracts: bool) { +#[test] +fn eip3607_reject_tx_from_contract_or_precompile() { let (binary, _code_hash) = compile_module("dummy").unwrap(); - let genesis_config = GenesisConfig:: { - debug_settings: Some(DebugSettings::new(false, bypass_eip3607_for_contracts)), - ..Default::default() - }; - - ExtBuilder::default() - .genesis_config(Some(genesis_config)) - .existential_deposit(200) - .build() - .execute_with(|| { - DebugFlag::set(bypass_eip3607_for_contracts); - let _ = ::Currency::set_balance(&ALICE, 1_000_000); - - // the origins from which we try to call a dispatchable - let Contract { addr: contract_addr, .. } = - builder::bare_instantiate(Code::Upload(binary)).build_and_unwrap_contract(); - assert!(>::is_contract(&contract_addr)); - let blake2_addr = H160::from_low_u64_be(9); - let system_addr = H160::from_low_u64_be(0x900); - let mut addresses = vec![blake2_addr, system_addr]; + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 1_000_000); - if !bypass_eip3607_for_contracts { - // If we are setting the bypass config to true, it will only take effect for - // contracts, not for precompiles. So if it's not true, we can also test for the - // contract. - addresses.push(contract_addr); - } + // the origins from which we try to call a dispatchable + let Contract { addr: contract_addr, .. } = + builder::bare_instantiate(Code::Upload(binary)).build_and_unwrap_contract(); + assert!(>::is_contract(&contract_addr)); + let blake2_addr = H160::from_low_u64_be(9); + let system_addr = H160::from_low_u64_be(0x900); + let addresses = vec![contract_addr, blake2_addr, system_addr]; - // used to test `dispatch_as_fallback_account` - let call = Box::new(RuntimeCall::Balances(pallet_balances::Call::transfer_all { - dest: EVE, - keep_alive: false, - })); + // used to test `dispatch_as_fallback_account` + let call = Box::new(RuntimeCall::Balances(pallet_balances::Call::transfer_all { + dest: EVE, + keep_alive: false, + })); - for address in addresses.iter() { - let origin = ::AddressMapper::to_fallback_account_id(address); + for address in addresses.iter() { + let origin = ::AddressMapper::to_fallback_account_id(address); - let result = - builder::call(BOB_ADDR).origin(RuntimeOrigin::signed(origin.clone())).build(); - assert_err!(result, DispatchError::BadOrigin); + let result = + builder::call(BOB_ADDR).origin(RuntimeOrigin::signed(origin.clone())).build(); + assert_err!(result, DispatchError::BadOrigin); - let result = builder::eth_call(BOB_ADDR) - .origin(Origin::EthTransaction(origin.clone()).into()) - .build(); - assert_err!(result, DispatchError::BadOrigin); + let result = builder::eth_call(BOB_ADDR) + .origin(Origin::EthTransaction(origin.clone()).into()) + .build(); + assert_err!(result, DispatchError::BadOrigin); - let result = builder::instantiate(Default::default()) - .origin(RuntimeOrigin::signed(origin.clone())) - .build(); - assert_err!(result, DispatchError::BadOrigin); + let result = builder::instantiate(Default::default()) + .origin(RuntimeOrigin::signed(origin.clone())) + .build(); + assert_err!(result, DispatchError::BadOrigin); - let result = builder::eth_instantiate_with_code(Default::default()) - .origin(Origin::EthTransaction(origin.clone()).into()) - .build(); - assert_err!(result, DispatchError::BadOrigin); + let result = builder::eth_instantiate_with_code(Default::default()) + .origin(Origin::EthTransaction(origin.clone()).into()) + .build(); + assert_err!(result, DispatchError::BadOrigin); - let result = builder::instantiate_with_code(Default::default()) - .origin(RuntimeOrigin::signed(origin.clone())) - .build(); - assert_err!(result, DispatchError::BadOrigin); + let result = builder::instantiate_with_code(Default::default()) + .origin(RuntimeOrigin::signed(origin.clone())) + .build(); + assert_err!(result, DispatchError::BadOrigin); - let result = >::upload_code( - RuntimeOrigin::signed(origin.clone()), - Default::default(), - >::MAX, - ); - assert_err!(result, DispatchError::BadOrigin); + let result = >::upload_code( + RuntimeOrigin::signed(origin.clone()), + Default::default(), + >::MAX, + ); + assert_err!(result, DispatchError::BadOrigin); - let result = >::map_account(RuntimeOrigin::signed(origin.clone())); - assert_err!(result, DispatchError::BadOrigin); + let result = >::map_account(RuntimeOrigin::signed(origin.clone())); + assert_err!(result, DispatchError::BadOrigin); - let result = >::dispatch_as_fallback_account( - RuntimeOrigin::signed(origin.clone()), - call.clone(), - ); - assert_err!(result, DispatchError::BadOrigin); - } - }); + let result = >::dispatch_as_fallback_account( + RuntimeOrigin::signed(origin.clone()), + call.clone(), + ); + assert_err!(result, DispatchError::BadOrigin); + } + }); } #[test] -fn eip3607_allow_tx_from_contract_if_debug_setting_configured() { +fn eip3607_allow_tx_from_contract_or_precompile_if_debug_setting_configured() { let (binary, code_hash) = compile_module("dummy").unwrap(); let genesis_config = GenesisConfig:: { @@ -5049,48 +5030,55 @@ fn eip3607_allow_tx_from_contract_if_debug_setting_configured() { let _ = ::Currency::set_balance(&ALICE, 1_000_000); // the origins from which we try to call a dispatchable - let Contract { addr: address, account_id } = + let Contract { addr: contract_addr, .. } = builder::bare_instantiate(Code::Upload(binary.clone())).build_and_unwrap_contract(); - let _ = ::Currency::set_balance(&account_id, 10_000_000_000_000); - assert!(>::is_contract(&address)); + assert!(>::is_contract(&contract_addr)); - let origin = ::AddressMapper::to_fallback_account_id(&address); + let blake2_addr = H160::from_low_u64_be(9); + let system_addr = H160::from_low_u64_be(0x900); + let addresses = vec![contract_addr, blake2_addr, system_addr]; - let result = - builder::call(BOB_ADDR).origin(RuntimeOrigin::signed(origin.clone())).build(); - assert_ok!(result); + for address in addresses { + let origin = ::AddressMapper::to_fallback_account_id(&address); - let result = builder::eth_call(BOB_ADDR) - .origin(Origin::EthTransaction(origin.clone()).into()) - .build(); - assert_ok!(result); + let _ = ::Currency::set_balance(&origin, 10_000_000_000_000); - let result = builder::instantiate(code_hash) - .origin(RuntimeOrigin::signed(origin.clone())) - .build(); - assert_ok!(result); + let result = + builder::call(BOB_ADDR).origin(RuntimeOrigin::signed(origin.clone())).build(); + assert_ok!(result); - let result = builder::eth_instantiate_with_code(binary.clone()) - .origin(Origin::EthTransaction(origin.clone()).into()) - .build(); - assert_ok!(result); + let result = builder::eth_call(BOB_ADDR) + .origin(Origin::EthTransaction(origin.clone()).into()) + .build(); + assert_ok!(result); - let result = >::dispatch_as_fallback_account( - RuntimeOrigin::signed(origin.clone()), - Box::new(RuntimeCall::Balances(pallet_balances::Call::transfer_all { - dest: EVE, - keep_alive: false, - })), - ); - assert_ok!(result); + let result = builder::instantiate(code_hash) + .origin(RuntimeOrigin::signed(origin.clone())) + .build(); + assert_ok!(result); - let result = >::upload_code( - RuntimeOrigin::signed(origin.clone()), - binary, - >::MAX, - ); - assert_ok!(result); + let result = builder::eth_instantiate_with_code(binary.clone()) + .origin(Origin::EthTransaction(origin.clone()).into()) + .build(); + assert_ok!(result); + + let result = >::dispatch_as_fallback_account( + RuntimeOrigin::signed(origin.clone()), + Box::new(RuntimeCall::Balances(pallet_balances::Call::transfer_all { + dest: EVE, + keep_alive: false, + })), + ); + assert_ok!(result); + + let result = >::upload_code( + RuntimeOrigin::signed(origin.clone()), + binary.clone(), + >::MAX, + ); + assert_ok!(result); + } }); } From 396438d9387847cae4e899524ce7669530093468 Mon Sep 17 00:00:00 2001 From: alindima Date: Mon, 24 Nov 2025 12:06:23 +0200 Subject: [PATCH 5/5] nit --- substrate/frame/revive/src/tests/pvm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/revive/src/tests/pvm.rs b/substrate/frame/revive/src/tests/pvm.rs index 19859393c032a..5361efdd9f17f 100644 --- a/substrate/frame/revive/src/tests/pvm.rs +++ b/substrate/frame/revive/src/tests/pvm.rs @@ -4957,7 +4957,7 @@ fn eip3607_reject_tx_from_contract_or_precompile() { assert!(>::is_contract(&contract_addr)); let blake2_addr = H160::from_low_u64_be(9); let system_addr = H160::from_low_u64_be(0x900); - let addresses = vec![contract_addr, blake2_addr, system_addr]; + let addresses = [contract_addr, blake2_addr, system_addr]; // used to test `dispatch_as_fallback_account` let call = Box::new(RuntimeCall::Balances(pallet_balances::Call::transfer_all { @@ -5037,7 +5037,7 @@ fn eip3607_allow_tx_from_contract_or_precompile_if_debug_setting_configured() { let blake2_addr = H160::from_low_u64_be(9); let system_addr = H160::from_low_u64_be(0x900); - let addresses = vec![contract_addr, blake2_addr, system_addr]; + let addresses = [contract_addr, blake2_addr, system_addr]; for address in addresses { let origin = ::AddressMapper::to_fallback_account_id(&address);