From 847c12ce8e9c2bf31a8d07803ef6c85e6b5bfe1f Mon Sep 17 00:00:00 2001 From: pgherveou Date: Mon, 6 Oct 2025 16:24:14 +0200 Subject: [PATCH 01/10] Update basefee instruction --- .../frame/revive/src/tests/sol/block_info.rs | 17 +++++++++++++++++ substrate/frame/revive/src/vm/evm.rs | 6 ------ .../src/vm/evm/instructions/block_info.rs | 4 ++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/substrate/frame/revive/src/tests/sol/block_info.rs b/substrate/frame/revive/src/tests/sol/block_info.rs index a1c7c9c2642e..3976045320fe 100644 --- a/substrate/frame/revive/src/tests/sol/block_info.rs +++ b/substrate/frame/revive/src/tests/sol/block_info.rs @@ -173,3 +173,20 @@ fn difficulty_works(fixture_type: FixtureType) { ); }); } + +/// Tests that the difficulty opcode works as expected. +#[test_case(FixtureType::Solc)] +fn base_fee_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(); + + let result = builder::bare_call(addr) + .data(BlockInfo::BlockInfoCalls::basefee(BlockInfo::basefeeCall {}).abi_encode()) + .build_and_unwrap_result(); + let decoded = BlockInfo::difficultyCall::abi_decode_returns(&result.data).unwrap(); + assert_eq!(>::evm_gas_price().as_u64(), decoded); + }); +} diff --git a/substrate/frame/revive/src/vm/evm.rs b/substrate/frame/revive/src/vm/evm.rs index 04fd659215d3..23232f3512d8 100644 --- a/substrate/frame/revive/src/vm/evm.rs +++ b/substrate/frame/revive/src/vm/evm.rs @@ -19,7 +19,6 @@ use crate::{ vm::{evm::instructions::exec_instruction, BytecodeType, ExecResult, Ext}, weights::WeightInfo, AccountIdOf, CodeInfo, Config, ContractBlob, DispatchError, Error, Weight, H256, LOG_TARGET, - U256, }; use alloc::vec::Vec; use core::{convert::Infallible, ops::ControlFlow}; @@ -48,11 +47,6 @@ mod util; /// opcode. The value is aligned with the difficulty hardcoded for PVM contracts. pub(crate) const DIFFICULTY: u64 = 2500000000000000_u64; -/// The base fee per gas used in the network as defined by EIP-1559. -/// -/// For `pallet-revive`, this is hardcoded to 0 -pub(crate) const BASE_FEE: U256 = U256::zero(); - /// Cost for a single unit of EVM gas. #[derive(Eq, PartialEq, Debug, Clone, Copy)] pub struct EVMGas(u64); diff --git a/substrate/frame/revive/src/vm/evm/instructions/block_info.rs b/substrate/frame/revive/src/vm/evm/instructions/block_info.rs index b2d236e22c79..a3e1a02cee74 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/block_info.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/block_info.rs @@ -17,7 +17,7 @@ use crate::{ vm::{ - evm::{interpreter::Halt, EVMGas, Interpreter, BASE_FEE, DIFFICULTY}, + evm::{interpreter::Halt, EVMGas, Interpreter, DIFFICULTY}, Ext, }, Error, RuntimeCosts, @@ -85,7 +85,7 @@ pub fn gaslimit(interpreter: &mut Interpreter) -> ControlFlow { /// EIP-3198: BASEFEE opcode pub fn basefee(interpreter: &mut Interpreter) -> ControlFlow { interpreter.ext.charge_or_halt(RuntimeCosts::BaseFee)?; - interpreter.stack.push(BASE_FEE)?; + interpreter.stack.push(interpreter.ext.effective_gas_price())?; ControlFlow::Continue(()) } From f8d00dff9b5ec3ff1b25fdb26ad90c41a79961cb Mon Sep 17 00:00:00 2001 From: pgherveou Date: Mon, 6 Oct 2025 16:39:24 +0000 Subject: [PATCH 02/10] fix --- .../frame/revive/src/tests/sol/block_info.rs | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/substrate/frame/revive/src/tests/sol/block_info.rs b/substrate/frame/revive/src/tests/sol/block_info.rs index 3976045320fe..24423b7466bd 100644 --- a/substrate/frame/revive/src/tests/sol/block_info.rs +++ b/substrate/frame/revive/src/tests/sol/block_info.rs @@ -137,7 +137,8 @@ fn gaslimit_works(fixture_type: FixtureType) { /// Tests that the basefee opcode works as expected. #[test_case(FixtureType::Solc)] #[test_case(FixtureType::Resolc)] -fn basefee_works(fixture_type: FixtureType) { +#[test_case(FixtureType::Solc)] +fn base_fee_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); @@ -147,8 +148,8 @@ fn basefee_works(fixture_type: FixtureType) { let result = builder::bare_call(addr) .data(BlockInfo::BlockInfoCalls::basefee(BlockInfo::basefeeCall {}).abi_encode()) .build_and_unwrap_result(); - let decoded = BlockInfo::basefeeCall::abi_decode_returns(&result.data).unwrap(); - assert_eq!(0u64, decoded); + let decoded = BlockInfo::difficultyCall::abi_decode_returns(&result.data).unwrap(); + assert_eq!(>::evm_gas_price().as_u64(), decoded); }); } @@ -173,20 +174,3 @@ fn difficulty_works(fixture_type: FixtureType) { ); }); } - -/// Tests that the difficulty opcode works as expected. -#[test_case(FixtureType::Solc)] -fn base_fee_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(); - - let result = builder::bare_call(addr) - .data(BlockInfo::BlockInfoCalls::basefee(BlockInfo::basefeeCall {}).abi_encode()) - .build_and_unwrap_result(); - let decoded = BlockInfo::difficultyCall::abi_decode_returns(&result.data).unwrap(); - assert_eq!(>::evm_gas_price().as_u64(), decoded); - }); -} From a4583a04fd79686b21b116b9e502f49ff0f9173e Mon Sep 17 00:00:00 2001 From: pgherveou Date: Mon, 6 Oct 2025 16:42:01 +0000 Subject: [PATCH 03/10] fix --- substrate/frame/revive/src/tests/sol/block_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/tests/sol/block_info.rs b/substrate/frame/revive/src/tests/sol/block_info.rs index 24423b7466bd..dcf787968eee 100644 --- a/substrate/frame/revive/src/tests/sol/block_info.rs +++ b/substrate/frame/revive/src/tests/sol/block_info.rs @@ -148,7 +148,7 @@ fn base_fee_works(fixture_type: FixtureType) { let result = builder::bare_call(addr) .data(BlockInfo::BlockInfoCalls::basefee(BlockInfo::basefeeCall {}).abi_encode()) .build_and_unwrap_result(); - let decoded = BlockInfo::difficultyCall::abi_decode_returns(&result.data).unwrap(); + let decoded = BlockInfo::basefeeCall::abi_decode_returns(&result.data).unwrap(); assert_eq!(>::evm_gas_price().as_u64(), decoded); }); } From a33650c3431f7485a28ae68c45137279bf6d77dc Mon Sep 17 00:00:00 2001 From: pgherveou Date: Mon, 6 Oct 2025 16:42:19 +0000 Subject: [PATCH 04/10] fix --- substrate/frame/revive/src/tests/sol/block_info.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/substrate/frame/revive/src/tests/sol/block_info.rs b/substrate/frame/revive/src/tests/sol/block_info.rs index dcf787968eee..5553afda8a6c 100644 --- a/substrate/frame/revive/src/tests/sol/block_info.rs +++ b/substrate/frame/revive/src/tests/sol/block_info.rs @@ -137,7 +137,6 @@ fn gaslimit_works(fixture_type: FixtureType) { /// Tests that the basefee opcode works as expected. #[test_case(FixtureType::Solc)] #[test_case(FixtureType::Resolc)] -#[test_case(FixtureType::Solc)] fn base_fee_works(fixture_type: FixtureType) { let (code, _) = compile_module_with_type("BlockInfo", fixture_type).unwrap(); ExtBuilder::default().build().execute_with(|| { From a508134529bda91fc3989ff9d482ee03e4d47c85 Mon Sep 17 00:00:00 2001 From: pgherveou Date: Mon, 6 Oct 2025 21:34:53 +0200 Subject: [PATCH 05/10] fix evm --- substrate/frame/revive/src/vm/evm/instructions/block_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/vm/evm/instructions/block_info.rs b/substrate/frame/revive/src/vm/evm/instructions/block_info.rs index a3e1a02cee74..6386c4de66d8 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/block_info.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/block_info.rs @@ -85,7 +85,7 @@ pub fn gaslimit(interpreter: &mut Interpreter) -> ControlFlow { /// EIP-3198: BASEFEE opcode pub fn basefee(interpreter: &mut Interpreter) -> ControlFlow { interpreter.ext.charge_or_halt(RuntimeCosts::BaseFee)?; - interpreter.stack.push(interpreter.ext.effective_gas_price())?; + interpreter.stack.push(crate::Pallet::::evm_gas_price())?; ControlFlow::Continue(()) } From e12379101f899c2354e430aa74170b39f752054d Mon Sep 17 00:00:00 2001 From: pgherveou Date: Mon, 6 Oct 2025 21:36:46 +0200 Subject: [PATCH 06/10] fix --- substrate/frame/revive/src/vm/pvm/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/vm/pvm/env.rs b/substrate/frame/revive/src/vm/pvm/env.rs index 49f54ce3532d..f57b1fef2b5b 100644 --- a/substrate/frame/revive/src/vm/pvm/env.rs +++ b/substrate/frame/revive/src/vm/pvm/env.rs @@ -660,7 +660,7 @@ pub mod env { Ok(self.write_fixed_sandbox_output( memory, out_ptr, - &U256::zero().to_little_endian(), + &Pallet::::evm_gas_price().to_little_endian(), false, already_charged, )?) From f2af74273edd2cdc30ce78fde1970093d5dc6e64 Mon Sep 17 00:00:00 2001 From: pgherveou Date: Tue, 7 Oct 2025 06:32:22 +0200 Subject: [PATCH 07/10] fix --- substrate/frame/revive/src/benchmarking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index f0aa4ce7b407..c8193ce4579d 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -1006,7 +1006,7 @@ mod benchmarks { result = runtime.bench_base_fee(memory.as_mut_slice(), 0); } assert_ok!(result); - assert_eq!(U256::from_little_endian(&memory[..]), U256::zero()); + assert_eq!(U256::from_little_endian(&memory[..]), >::evm_gas_price()); } #[benchmark(pov_mode = Measured)] From 22a03bedf9035225bfcacc37097f318ee3bbc31d Mon Sep 17 00:00:00 2001 From: pgherveou Date: Tue, 7 Oct 2025 12:35:32 +0000 Subject: [PATCH 08/10] rename evm_gas_price to evm_base_fee --- substrate/frame/revive/src/benchmarking.rs | 4 ++-- substrate/frame/revive/src/evm/call.rs | 2 +- substrate/frame/revive/src/evm/runtime.rs | 4 ++-- substrate/frame/revive/src/exec.rs | 2 +- substrate/frame/revive/src/lib.rs | 6 +++--- substrate/frame/revive/src/tests/pvm.rs | 2 +- substrate/frame/revive/src/tests/sol/block_info.rs | 2 +- substrate/frame/revive/src/tests/sol/tx_info.rs | 2 +- .../frame/revive/src/vm/evm/instructions/block_info.rs | 2 +- substrate/frame/revive/src/vm/pvm/env.rs | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index c8193ce4579d..b8d03c8d015c 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -994,7 +994,7 @@ mod benchmarks { { result = runtime.bench_gas_price(memory.as_mut_slice()); } - assert_eq!(U256::from(result.unwrap()), >::evm_gas_price()); + assert_eq!(U256::from(result.unwrap()), >::evm_base_fee()); } #[benchmark(pov_mode = Measured)] @@ -1006,7 +1006,7 @@ mod benchmarks { result = runtime.bench_base_fee(memory.as_mut_slice(), 0); } assert_ok!(result); - assert_eq!(U256::from_little_endian(&memory[..]), >::evm_gas_price()); + assert_eq!(U256::from_little_endian(&memory[..]), >::evm_base_fee()); } #[benchmark(pov_mode = Measured)] diff --git a/substrate/frame/revive/src/evm/call.rs b/substrate/frame/revive/src/evm/call.rs index 420068a70d59..0b6326d488be 100644 --- a/substrate/frame/revive/src/evm/call.rs +++ b/substrate/frame/revive/src/evm/call.rs @@ -55,7 +55,7 @@ where T: Config, CallOf: SetWeightLimit, { - let base_fee = >::evm_gas_price(); + let base_fee = >::evm_base_fee(); let Some(gas) = tx.gas else { log::debug!(target: LOG_TARGET, "No gas provided"); diff --git a/substrate/frame/revive/src/evm/runtime.rs b/substrate/frame/revive/src/evm/runtime.rs index 9d34d65a7856..a09ce71f4033 100644 --- a/substrate/frame/revive/src/evm/runtime.rs +++ b/substrate/frame/revive/src/evm/runtime.rs @@ -291,7 +291,7 @@ pub trait EthExtra { InvalidTransaction::BadProof })?; let signer = ::AddressMapper::to_fallback_account_id(&signer_addr); - let base_fee = >::evm_gas_price(); + let base_fee = >::evm_base_fee(); let tx = GenericTransaction::from_signed(tx, base_fee, None); let nonce = tx.nonce.unwrap_or_default().try_into().map_err(|_| { log::debug!(target: LOG_TARGET, "Failed to convert nonce"); @@ -406,7 +406,7 @@ mod test { Self::fund_account(&account); let dry_run = crate::Pallet::::dry_run_eth_transact(self.tx.clone()); - self.tx.gas_price = Some(>::evm_gas_price()); + self.tx.gas_price = Some(>::evm_base_fee()); match dry_run { Ok(dry_run) => { diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index b62faaba7ca3..0ce7dbd42e74 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -2192,7 +2192,7 @@ where fn effective_gas_price(&self) -> U256 { self.exec_config .effective_gas_price - .unwrap_or_else(|| >::evm_gas_price()) + .unwrap_or_else(|| >::evm_base_fee()) } } diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 965ae16d502a..793be8ed42db 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -1414,7 +1414,7 @@ impl Pallet { let origin = T::AddressMapper::to_account_id(&tx.from.unwrap_or_default()); Self::prepare_dry_run(&origin); - let base_fee = Self::evm_gas_price(); + let base_fee = Self::evm_base_fee(); let effective_gas_price = tx.effective_gas_price(base_fee).unwrap_or(base_fee); if effective_gas_price < base_fee { @@ -1706,7 +1706,7 @@ impl Pallet { } /// Get the base gas price. - pub fn evm_gas_price() -> U256 { + pub fn evm_base_fee() -> U256 { let multiplier = T::FeeInfo::next_fee_multiplier(); multiplier.saturating_mul_int::(T::NativeToEthRatio::get().into()).into() } @@ -2266,7 +2266,7 @@ macro_rules! impl_runtime_apis_plus_revive_traits { } fn gas_price() -> $crate::U256 { - $crate::Pallet::::evm_gas_price() + $crate::Pallet::::evm_base_fee() } fn nonce(address: $crate::H160) -> Nonce { diff --git a/substrate/frame/revive/src/tests/pvm.rs b/substrate/frame/revive/src/tests/pvm.rs index eb92d7a73439..e1c27a3ed21b 100644 --- a/substrate/frame/revive/src/tests/pvm.rs +++ b/substrate/frame/revive/src/tests/pvm.rs @@ -3375,7 +3375,7 @@ fn gas_price_api_works() { assert_eq!(received.flags, ReturnFlags::empty()); assert_eq!( u64::from_le_bytes(received.data[..].try_into().unwrap()), - u64::try_from(>::evm_gas_price()).unwrap(), + u64::try_from(>::evm_base_fee()).unwrap(), ); }); } diff --git a/substrate/frame/revive/src/tests/sol/block_info.rs b/substrate/frame/revive/src/tests/sol/block_info.rs index 5553afda8a6c..94d5f8f5198b 100644 --- a/substrate/frame/revive/src/tests/sol/block_info.rs +++ b/substrate/frame/revive/src/tests/sol/block_info.rs @@ -148,7 +148,7 @@ fn base_fee_works(fixture_type: FixtureType) { .data(BlockInfo::BlockInfoCalls::basefee(BlockInfo::basefeeCall {}).abi_encode()) .build_and_unwrap_result(); let decoded = BlockInfo::basefeeCall::abi_decode_returns(&result.data).unwrap(); - assert_eq!(>::evm_gas_price().as_u64(), decoded); + assert_eq!(>::evm_base_fee().as_u64(), decoded); }); } diff --git a/substrate/frame/revive/src/tests/sol/tx_info.rs b/substrate/frame/revive/src/tests/sol/tx_info.rs index 6a4f0c2b0a61..a2072ab67a98 100644 --- a/substrate/frame/revive/src/tests/sol/tx_info.rs +++ b/substrate/frame/revive/src/tests/sol/tx_info.rs @@ -46,7 +46,7 @@ fn gasprice_works(fixture_type: FixtureType) { ) .build_and_unwrap_result(); let decoded = TransactionInfo::gaspriceCall::abi_decode_returns(&result.data).unwrap(); - assert_eq!(>::evm_gas_price().as_u64(), decoded); + assert_eq!(>::evm_base_fee().as_u64(), decoded); }); } diff --git a/substrate/frame/revive/src/vm/evm/instructions/block_info.rs b/substrate/frame/revive/src/vm/evm/instructions/block_info.rs index 6386c4de66d8..c73881cf2435 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/block_info.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/block_info.rs @@ -85,7 +85,7 @@ pub fn gaslimit(interpreter: &mut Interpreter) -> ControlFlow { /// EIP-3198: BASEFEE opcode pub fn basefee(interpreter: &mut Interpreter) -> ControlFlow { interpreter.ext.charge_or_halt(RuntimeCosts::BaseFee)?; - interpreter.stack.push(crate::Pallet::::evm_gas_price())?; + interpreter.stack.push(crate::Pallet::::evm_base_fee())?; ControlFlow::Continue(()) } diff --git a/substrate/frame/revive/src/vm/pvm/env.rs b/substrate/frame/revive/src/vm/pvm/env.rs index f57b1fef2b5b..c4a7fff999fa 100644 --- a/substrate/frame/revive/src/vm/pvm/env.rs +++ b/substrate/frame/revive/src/vm/pvm/env.rs @@ -660,7 +660,7 @@ pub mod env { Ok(self.write_fixed_sandbox_output( memory, out_ptr, - &Pallet::::evm_gas_price().to_little_endian(), + &Pallet::::evm_base_fee().to_little_endian(), false, already_charged, )?) From 3a87a41363bbac242e17063843fe8a86c9f90c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Wed, 8 Oct 2025 13:08:46 +0400 Subject: [PATCH 09/10] fix test --- substrate/frame/revive/src/tests/pvm.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/tests/pvm.rs b/substrate/frame/revive/src/tests/pvm.rs index e1c27a3ed21b..aef961d812fb 100644 --- a/substrate/frame/revive/src/tests/pvm.rs +++ b/substrate/frame/revive/src/tests/pvm.rs @@ -3394,7 +3394,10 @@ fn base_fee_api_works() { // Call the contract: It echoes back the value returned by the base fee API. let received = builder::bare_call(addr).build_and_unwrap_result(); assert_eq!(received.flags, ReturnFlags::empty()); - assert_eq!(U256::from_little_endian(received.data[..].try_into().unwrap()), U256::zero()); + assert_eq!( + U256::from_little_endian(received.data[..].try_into().unwrap()), + >::evm_base_fee(), + ); }); } From 23af40d2a8ab5bb7c449f1db005b1f9ced524fca Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 09:15:26 +0000 Subject: [PATCH 10/10] Update from github-actions[bot] running command 'prdoc --audience runtime_dev' --- prdoc/pr_9945.prdoc | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 prdoc/pr_9945.prdoc diff --git a/prdoc/pr_9945.prdoc b/prdoc/pr_9945.prdoc new file mode 100644 index 000000000000..5219d461ec7e --- /dev/null +++ b/prdoc/pr_9945.prdoc @@ -0,0 +1,8 @@ +title: pallet-revive update basefee instruction +doc: +- audience: Runtime Dev + description: The base fee instruction now returns the proper base price instead + of a hard coded value. +crates: +- name: pallet-revive + bump: major