Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f832bda
fix
pgherveou Oct 28, 2025
40bcd2d
update sha
pgherveou Oct 28, 2025
b34c502
fix
pgherveou Oct 28, 2025
2bda00e
Update from github-actions[bot] running command 'prdoc --audience run…
github-actions[bot] Oct 28, 2025
1921580
nit
pgherveou Oct 28, 2025
f08a7ce
nit
pgherveou Oct 28, 2025
7b7d5bf
nit
pgherveou Oct 28, 2025
cd94ec9
fix --all-features
pgherveou Oct 28, 2025
c47b19a
nit comment
pgherveou Oct 28, 2025
6aa60c2
clippy
pgherveou Oct 29, 2025
a162aa3
take into account storage deposit
pgherveou Oct 29, 2025
f3b81d4
bump evm-test-suite sha
pgherveou Oct 29, 2025
80ab0f0
wip
pgherveou Oct 29, 2025
76dd5db
wip
pgherveou Oct 29, 2025
5dd4242
wip
pgherveou Oct 29, 2025
3a06584
wip
pgherveou Oct 29, 2025
f119bae
fixes
pgherveou Oct 30, 2025
78b7368
pr cleanup
pgherveou Oct 30, 2025
4573b06
nit
pgherveou Oct 30, 2025
6245fe5
fix tests
pgherveou Oct 30, 2025
18f67c3
tweak
pgherveou Oct 30, 2025
0fc0535
Merge branch 'master' into pg/fix-gas-used
pgherveou Oct 30, 2025
63f99f4
pr diff
pgherveou Oct 30, 2025
e63dca2
fix benchmark
pgherveou Oct 30, 2025
d594fa6
fix build err
pgherveou Oct 30, 2025
46980de
nit
pgherveou Oct 30, 2025
47a1862
rollback SlowAdjustingFeeUpdate
pgherveou Oct 30, 2025
29c9055
fix
pgherveou Oct 30, 2025
9ba3bd2
undo
pgherveou Oct 30, 2025
98f407e
PR review use set_extension_weight
pgherveou Nov 3, 2025
dac377d
fix round up
pgherveou Nov 3, 2025
f28d699
rollback change
pgherveou Nov 3, 2025
64130a2
simplify
pgherveou Nov 3, 2025
02a43a5
Merge branch 'master' into pg/fix-gas-used
pgherveou Nov 4, 2025
2a8a2e5
simplify benchmark tests
pgherveou Nov 4, 2025
37ae634
update prdoc
pgherveou Nov 4, 2025
8f77e41
fmt
pgherveou Nov 4, 2025
df32005
Update from github-actions[bot] running command 'prdoc --audience run…
github-actions[bot] Nov 4, 2025
65265c2
Merge branch 'master' into pg/fix-gas-used
pgherveou Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests-evm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: paritytech/evm-test-suite
ref: c2422cace2fb8a4337fc1c704c49e458c8a79d6b
ref: 9c4bedda3d843efc8340336b67fb290cffc06f8f
path: evm-test-suite

- uses: denoland/setup-deno@v1
Expand Down
15 changes: 15 additions & 0 deletions prdoc/pr_10148.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
title: revive fix reported gas used
doc:
- audience: Runtime Dev
description: |-
Fix gas_used calculation introduced in #9418 to use the actual gas instead of just ref_time.
Fix as well the compute_actual_fee, and introduce a new `compute_actual_fee` in Config::FeeInfo.

The current calculation was skipping the `extension_weight`

The updated test here, ensure that the tx cost reported by the receipt match the fees deducted from the user account

https://github.com/paritytech/evm-test-suite/blob/a1110499ca39610be22645d1f4d7a7484cca0ed7/src/methods.test.ts?plain=1#L272-L264
crates:
- name: pallet-revive
bump: patch
8 changes: 4 additions & 4 deletions substrate/frame/revive/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2741,7 +2741,7 @@ mod benchmarks {

// Create input data of fixed size for consistent transaction payloads
let input_data = vec![0x42u8; fixed_payload_size];
let gas_used = Weight::from_parts(1_000_000, 1000);
let gas_used = U256::from(1_000_000);

for _ in 0..n {
// Create real signed transaction with fixed-size input data
Expand Down Expand Up @@ -2814,7 +2814,7 @@ mod benchmarks {

// Create input data of variable size p for realistic transaction payloads
let input_data = vec![0x42u8; d as usize];
let gas_used = Weight::from_parts(1_000_000, 1000);
let gas_used = U256::from(1_000_000);

for _ in 0..fixed_tx_count {
// Create real signed transaction with variable-size input data
Expand Down Expand Up @@ -2888,7 +2888,7 @@ mod benchmarks {
input_data.clone(),
);

let gas_used = Weight::from_parts(1_000_000, 1000);
let gas_used = U256::from(1_000_000);

// Store transaction
let _ = block_storage::bench_with_ethereum_context(|| {
Expand Down Expand Up @@ -2950,7 +2950,7 @@ mod benchmarks {
input_data.clone(),
);

let gas_used = Weight::from_parts(1_000_000, 1000);
let gas_used = U256::from(1_000_000);

// Store transaction
let _ = block_storage::bench_with_ethereum_context(|| {
Expand Down
8 changes: 4 additions & 4 deletions substrate/frame/revive/src/evm/block_hash/block_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::{
use alloc::{vec, vec::Vec};

use codec::{Decode, Encode};
use frame_support::{weights::Weight, DefaultNoBound};
use frame_support::DefaultNoBound;
use scale_info::TypeInfo;
use sp_core::{keccak_256, H160, H256, U256};

Expand Down Expand Up @@ -97,7 +97,7 @@ impl<T: crate::Config> EthereumBlockBuilder<T> {
&mut self,
transaction_encoded: Vec<u8>,
success: bool,
gas_used: Weight,
gas_used: U256,
encoded_logs: Vec<u8>,
receipt_bloom: LogsBloom,
) {
Expand All @@ -108,7 +108,7 @@ impl<T: crate::Config> EthereumBlockBuilder<T> {
let transaction_type = Self::extract_transaction_type(transaction_encoded.as_slice());

// Update gas and logs bloom.
self.gas_used = self.gas_used.saturating_add(gas_used.ref_time().into());
self.gas_used = self.gas_used.saturating_add(gas_used);
self.logs_bloom.accrue_bloom(&receipt_bloom);

// Update the receipt trie.
Expand All @@ -120,7 +120,7 @@ impl<T: crate::Config> EthereumBlockBuilder<T> {
transaction_type,
);

self.gas_info.push(ReceiptGasInfo { gas_used: gas_used.ref_time().into() });
self.gas_info.push(ReceiptGasInfo { gas_used });

// The first transaction and receipt are returned to be stored in the pallet storage.
// The index of the incremental hash builders already expects the next items.
Expand Down
91 changes: 67 additions & 24 deletions substrate/frame/revive/src/evm/block_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::{
evm::block_hash::{AccumulateReceipt, EthereumBlockBuilder, LogsBloom},
dispatch_result,
evm::{
block_hash::{AccumulateReceipt, EthereumBlockBuilder, LogsBloom},
fees::InfoT,
},
limits,
sp_runtime::traits::One,
weights::WeightInfo,
BlockHash, Config, EthBlockBuilderIR, EthereumBlock, Event, Pallet, ReceiptInfoData,
UniqueSaturatedInto, H160, H256,
BlockHash, Config, Error, EthBlockBuilderIR, EthereumBlock, Event, Pallet, ReceiptInfoData,
UniqueSaturatedInto, Weight, H160, H256,
};
use alloc::vec::Vec;
use environmental::environmental;
use frame_support::{
dispatch::DispatchInfo,
pallet_prelude::{DispatchError, DispatchResultWithPostInfo},
storage::with_transaction,
weights::Weight,
};
use sp_core::U256;
use sp_runtime::TransactionOutcome;
Expand All @@ -41,6 +45,57 @@ pub const BLOCK_HASH_COUNT: u32 = 256;
// that are needed to construct the final transaction receipt.
environmental!(receipt: AccumulateReceipt);

/// Result of an Ethereum context call execution.
pub(crate) struct EthereumCallResult {
/// The amount of gas used by the call.
pub gas_used: U256,
/// The dispatch result with post-dispatch information.
pub result: DispatchResultWithPostInfo,
}

impl EthereumCallResult {
/// Create a new `EthereumCallResult` from contract execution details.
///
/// # Parameters
///
/// - `result`: The execution result
/// - `gas_consumed`: The weight consumed during execution
/// - `base_call_weight`: The base call weight
/// - `encoded_len`: The length of the encoded transaction in bytes
/// - `info`: Dispatch information used for fee computation
/// - `effective_gas_price`: The EVM gas price
pub(crate) fn new<T: Config>(
mut result: Result<crate::ExecReturnValue, DispatchError>,
mut gas_consumed: Weight,
base_call_weight: Weight,
encoded_len: u32,
info: &DispatchInfo,
effective_gas_price: U256,
) -> Self {
if let Ok(retval) = &result {
if retval.did_revert() {
result = Err(<Error<T>>::ContractReverted.into());
}
}

// Refund pre-charged revert event weight if the call succeeds.
if result.is_ok() {
gas_consumed.saturating_reduce(T::WeightInfo::deposit_eth_extrinsic_revert_event())
}

let result = dispatch_result(result, gas_consumed, base_call_weight);
let native_fee = T::FeeInfo::compute_actual_fee(encoded_len, &info, &result);
let result = T::FeeInfo::ensure_not_overdrawn(native_fee, result);
let eth_fee = Pallet::<T>::convert_native_to_evm(native_fee);
let gas_used = if effective_gas_price.is_zero() {
Default::default()
} else {
eth_fee / effective_gas_price
};
Self { gas_used, result }
}
}

/// Capture the Ethereum log for the current transaction.
///
/// This method does nothing if called from outside of the ethereum context.
Expand Down Expand Up @@ -72,23 +127,19 @@ pub fn bench_with_ethereum_context<R>(f: impl FnOnce() -> R) -> R {
///
/// # Parameters
/// - transaction_encoded: The RLP encoded transaction bytes.
/// - call: A closure that executes the transaction logic and returns the gas consumed and result.
/// - call: A closure that executes the transaction logic and returns an `EthereumCallResult`.
pub fn with_ethereum_context<T: Config>(
transaction_encoded: Vec<u8>,
call: impl FnOnce() -> (Weight, DispatchResultWithPostInfo),
call: impl FnOnce() -> EthereumCallResult,
) -> DispatchResultWithPostInfo {
receipt::using(&mut AccumulateReceipt::new(), || {
let (err, gas_consumed, mut post_info) =
let (err, gas_consumed, post_info) =
with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
let (gas_consumed, result) = call();
let EthereumCallResult { gas_used, result } = call();
match result {
Ok(post_info) =>
TransactionOutcome::Commit(Ok((None, gas_consumed, post_info))),
Err(err) => TransactionOutcome::Rollback(Ok((
Some(err.error),
gas_consumed,
err.post_info,
))),
Ok(post_info) => TransactionOutcome::Commit(Ok((None, gas_used, post_info))),
Err(err) =>
TransactionOutcome::Rollback(Ok((Some(err.error), gas_used, err.post_info))),
}
})?;

Expand All @@ -106,10 +157,6 @@ pub fn with_ethereum_context<T: Config>(
deposit_eth_extrinsic_revert_event::<T>(crate::Error::<T>::BenchmarkingError.into());

crate::block_storage::process_transaction::<T>(transaction_encoded, true, gas_consumed);
post_info
.actual_weight
.as_mut()
.map(|w| w.saturating_reduce(T::WeightInfo::deposit_eth_extrinsic_revert_event()));
Ok(post_info)
}
})
Expand Down Expand Up @@ -174,11 +221,7 @@ pub fn on_finalize_build_eth_block<T: Config>(
/// This stores the RLP encoded transaction and receipt details into storage.
///
/// The data is used during the `on_finalize` hook to reconstruct the ETH block.
pub fn process_transaction<T: Config>(
transaction_encoded: Vec<u8>,
success: bool,
gas_used: Weight,
) {
pub fn process_transaction<T: Config>(transaction_encoded: Vec<u8>, success: bool, gas_used: U256) {
// Method returns `None` only when called from outside of the ethereum context.
// This is not the case here, since this is called from within the
// ethereum context.
Expand Down
35 changes: 29 additions & 6 deletions substrate/frame/revive/src/evm/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,18 @@ pub trait InfoT<T: Config>: seal::Sealed {
Zero::zero()
}

/// Makes sure that not too much storage deposit was withdrawn.
fn ensure_not_overdrawn(
/// Compute the actual post_dispatch fee
fn compute_actual_fee(
_encoded_len: u32,
_info: &DispatchInfo,
_result: &DispatchResultWithPostInfo,
) -> BalanceOf<T> {
Default::default()
}

/// Makes sure that not too much storage deposit was withdrawn.
fn ensure_not_overdrawn(
_fee: BalanceOf<T>,
result: DispatchResultWithPostInfo,
) -> DispatchResultWithPostInfo {
result
Expand Down Expand Up @@ -259,9 +267,27 @@ where
.saturating_add(Self::length_to_fee(encoded_len))
}

fn ensure_not_overdrawn(
fn compute_actual_fee(
encoded_len: u32,
info: &DispatchInfo,
result: &DispatchResultWithPostInfo,
) -> BalanceOf<E::Config> {
let mut post_info = *match result {
Ok(post_info) => post_info,
Err(err) => &err.post_info,
};

post_info
.actual_weight
.as_mut()
.map(|w| w.saturating_accrue(info.extension_weight));

<TxPallet<E::Config>>::compute_actual_fee(encoded_len, info, &post_info, Zero::zero())
.into()
}

fn ensure_not_overdrawn(
fee: BalanceOf<E::Config>,
result: DispatchResultWithPostInfo,
) -> DispatchResultWithPostInfo {
// if tx is already failing we can ignore
Expand All @@ -270,9 +296,6 @@ where
return result;
};

let fee: BalanceOf<E::Config> =
<TxPallet<E::Config>>::compute_actual_fee(encoded_len, info, &post_info, Zero::zero())
.into();
let available = Self::remaining_txfee();
if fee > available {
log::debug!(target: LOG_TARGET, "Drew too much from the txhold. \
Expand Down
39 changes: 16 additions & 23 deletions substrate/frame/revive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@ pub mod pallet {
drop(call);

block_storage::with_ethereum_context::<T>(transaction_encoded, || {
let mut output = Self::bare_instantiate(
let output = Self::bare_instantiate(
origin,
value,
gas_limit,
Expand All @@ -1256,19 +1256,14 @@ pub mod pallet {
),
);

if let Ok(retval) = &output.result {
if retval.result.did_revert() {
output.result = Err(<Error<T>>::ContractReverted.into());
}
}

let result = dispatch_result(
output.result.map(|result| result.result),
block_storage::EthereumCallResult::new::<T>(
output.result.map(|r| r.result),
output.gas_consumed,
base_info.call_weight,
);
let result = T::FeeInfo::ensure_not_overdrawn(encoded_len, &info, result);
(output.gas_consumed, result)
encoded_len,
&info,
effective_gas_price,
)
})
}

Expand Down Expand Up @@ -1307,7 +1302,7 @@ pub mod pallet {
drop(call);

block_storage::with_ethereum_context::<T>(transaction_encoded, || {
let mut output = Self::bare_call(
let output = Self::bare_call(
origin,
dest,
value,
Expand All @@ -1321,16 +1316,14 @@ pub mod pallet {
),
);

if let Ok(return_value) = &output.result {
if return_value.did_revert() {
output.result = Err(<Error<T>>::ContractReverted.into());
}
}

let result =
dispatch_result(output.result, output.gas_consumed, base_info.call_weight);
let result = T::FeeInfo::ensure_not_overdrawn(encoded_len, &info, result);
(output.gas_consumed, result)
block_storage::EthereumCallResult::new::<T>(
output.result,
output.gas_consumed,
base_info.call_weight,
encoded_len,
&info,
effective_gas_price,
)
})
}

Expand Down
Loading