Skip to content
Closed
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
11 changes: 8 additions & 3 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type ExecutionResult struct {
UsedGas uint64 // Total used gas but include the refunded gas
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)
GasRefund uint64 // Total gas refunded
}

// Unwrap returns the internal evm error which allows us for further
Expand Down Expand Up @@ -419,12 +420,13 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value)
}

var gasRefund uint64
if !rules.IsLondon {
// Before EIP-3529: refunds were capped to gasUsed / 2
st.refundGas(params.RefundQuotient)
gasRefund = st.refundGas(params.RefundQuotient)
} else {
// After EIP-3529: refunds are capped to gasUsed / 5
st.refundGas(params.RefundQuotientEIP3529)
gasRefund = st.refundGas(params.RefundQuotientEIP3529)
}
effectiveTip := msg.GasPrice
if rules.IsLondon {
Expand All @@ -445,10 +447,11 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
UsedGas: st.gasUsed(),
Err: vmerr,
ReturnData: ret,
GasRefund: gasRefund,
}, nil
}

func (st *StateTransition) refundGas(refundQuotient uint64) {
func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {
// Apply refund counter, capped to a refund quotient
refund := st.gasUsed() / refundQuotient
if refund > st.state.GetRefund() {
Expand All @@ -463,6 +466,8 @@ func (st *StateTransition) refundGas(refundQuotient uint64) {
// Also return remaining gas to the block gas counter so it is
// available for the next transaction.
st.gp.AddGas(st.gasRemaining)

return refund
}

// gasUsed returns the amount of gas used up by the state transition.
Expand Down
9 changes: 9 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,15 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
}
return 0, fmt.Errorf("gas required exceeds allowance (%d)", hi)
}

// Optimization: if the transaction succeeded with gasLimit set to the first execution's
// usedGas + gasRefund, then return that value immediately. Else, continue with the binary search.
optimisticGasLimit := result.UsedGas + result.GasRefund
failed, _, err = executeEstimate(ctx, b, args, state.Copy(), header, gasCap, optimisticGasLimit)
if !failed && err == nil {
return hexutil.Uint64(optimisticGasLimit), nil
}

// For almost any transaction, the gas consumed by the unconstrained execution above
// lower-bounds the gas limit required for it to succeed. One exception is those txs that
// explicitly check gas remaining in order to successfully execute within a given limit, but we
Expand Down