Skip to content

core, eth/gasestimator: introduce MaximumGasUsed for estimation #31735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 16 additions & 10 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import (
// ExecutionResult includes all output after executing given evm
// message no matter the execution itself is successful or not.
type ExecutionResult struct {
UsedGas uint64 // Total used gas, not including the refunded gas
RefundedGas uint64 // Total gas refunded after execution
Err error // Any error encountered during the execution(listed in core/vm/errors.go)
ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode)
UsedGas uint64 // Total used gas, not including the refunded gas
MaxUsedGas uint64 // Maximum gas consumed during execution, excluding gas refunds.
Err error // Any error encountered during the execution(listed in core/vm/errors.go)
ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode)
}

// Unwrap returns the internal evm error which allows us for further
Expand Down Expand Up @@ -509,9 +509,12 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
ret, st.gasRemaining, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining, value)
}

// Record the gas used excluding gas refunds. This value represents the actual
// gas allowance required to complete execution.
peakGasUsed := st.gasUsed()

// Compute refund counter, capped to a refund quotient.
gasRefund := st.calcRefund()
st.gasRemaining += gasRefund
st.gasRemaining += st.calcRefund()
if rules.IsPrague {
// After EIP-7623: Data-heavy transactions pay the floor gas.
if st.gasUsed() < floorDataGas {
Expand All @@ -521,6 +524,9 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
t.OnGasChange(prev, st.gasRemaining, tracing.GasChangeTxDataFloor)
}
}
if peakGasUsed < floorDataGas {
peakGasUsed = floorDataGas
}
}
st.returnGas()

Expand Down Expand Up @@ -549,10 +555,10 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
}

return &ExecutionResult{
UsedGas: st.gasUsed(),
RefundedGas: gasRefund,
Err: vmerr,
ReturnData: ret,
UsedGas: st.gasUsed(),
MaxUsedGas: peakGasUsed,
Err: vmerr,
ReturnData: ret,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion eth/gasestimator/gasestimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
// There's a fairly high chance for the transaction to execute successfully
// with gasLimit set to the first execution's usedGas + gasRefund. Explicitly
// check that gas amount and use as a limit for the binary search.
optimisticGasLimit := (result.UsedGas + result.RefundedGas + params.CallStipend) * 64 / 63
optimisticGasLimit := (result.MaxUsedGas + params.CallStipend) * 64 / 63
if optimisticGasLimit < hi {
failed, _, err = execute(ctx, call, opts, optimisticGasLimit)
if err != nil {
Expand Down