Repository navigation
Add optional state-transition gas surcharge (CON-300) #99
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
Changes from 2 commits
8174170
18d1bd6
5213511
321a5f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -235,6 +235,8 @@ type StateTransition struct { | |
| msg *Message | ||
| gasRemaining uint64 | ||
| initialGas uint64 | ||
| gasSurcharge uint64 | ||
| gasSurchargeReason tracing.GasChangeReason | ||
| state vm.StateDB | ||
| evm *vm.EVM | ||
| feeCharged bool | ||
|
|
@@ -253,6 +255,15 @@ func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool, feeCharged bool, | |
| } | ||
| } | ||
|
|
||
| // WithGasSurcharge reserves non-refundable gas before intrinsic gas and EVM execution. | ||
| // The surcharge is included in UsedGas and fees, and excluded from refund caps and data-floor gas. | ||
| // reason is the tracer category emitted when the surcharge is reserved. | ||
| func (st *StateTransition) WithGasSurcharge(gas uint64, reason tracing.GasChangeReason) *StateTransition { | ||
| st.gasSurcharge = gas | ||
| st.gasSurchargeReason = reason | ||
| return st | ||
| } | ||
|
|
||
| // to returns the recipient of the message. | ||
| func (st *StateTransition) to() common.Address { | ||
| if st.msg == nil || st.msg.To == nil /* contract creation */ { | ||
|
|
@@ -440,6 +451,15 @@ func (st *StateTransition) Execute() (*ExecutionResult, error) { | |
| if err := st.preCheck(); err != nil { | ||
| return nil, err | ||
| } | ||
| if st.gasRemaining < st.gasSurcharge { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] Reusing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] Reusing |
||
| return nil, fmt.Errorf("%w: have %d, want surcharge %d", ErrIntrinsicGas, st.gasRemaining, st.gasSurcharge) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] Reusing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] Reusing |
||
| } | ||
| if st.gasSurcharge > 0 { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] This emits |
||
| if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil { | ||
| t.OnGasChange(st.gasRemaining, st.gasRemaining-st.gasSurcharge, st.gasSurchargeReason) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] The surcharge |
||
| } | ||
| st.gasRemaining -= st.gasSurcharge | ||
| } | ||
|
|
||
| var ( | ||
| msg = st.msg | ||
|
|
@@ -462,8 +482,9 @@ func (st *StateTransition) Execute() (*ExecutionResult, error) { | |
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if msg.GasLimit < floorDataGas { | ||
| return nil, fmt.Errorf("%w: have %d, want %d", ErrFloorDataGas, msg.GasLimit, floorDataGas) | ||
| executionGasLimit := msg.GasLimit - st.gasSurcharge | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] Prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] |
||
| if executionGasLimit < floorDataGas { | ||
| return nil, fmt.Errorf("%w: have %d, want %d", ErrFloorDataGas, executionGasLimit, floorDataGas) | ||
| } | ||
| } | ||
| if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil { | ||
|
|
@@ -538,9 +559,9 @@ func (st *StateTransition) Execute() (*ExecutionResult, error) { | |
| st.gasRemaining += gasRefund | ||
| if rules.IsPrague { | ||
| // After EIP-7623: Data-heavy transactions pay the floor gas. | ||
| if st.gasUsed() < floorDataGas { | ||
| if st.executionGasUsed() < floorDataGas { | ||
| prev := st.gasRemaining | ||
| st.gasRemaining = st.initialGas - floorDataGas | ||
| st.gasRemaining = st.initialGas - st.gasSurcharge - floorDataGas | ||
| if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil { | ||
| t.OnGasChange(prev, st.gasRemaining, tracing.GasChangeTxDataFloor) | ||
| } | ||
|
|
@@ -647,11 +668,11 @@ func (st *StateTransition) applyAuthorization(auth *types.SetCodeAuthorization) | |
| func (st *StateTransition) calcRefund() uint64 { | ||
| var refund uint64 | ||
| if !st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { | ||
| // Before EIP-3529: refunds were capped to gasUsed / 2 | ||
| refund = st.gasUsed() / params.RefundQuotient | ||
| // Before EIP-3529: refunds were capped to execution gas / 2 | ||
| refund = st.executionGasUsed() / params.RefundQuotient | ||
| } else { | ||
| // After EIP-3529: refunds are capped to gasUsed / 5 | ||
| refund = st.gasUsed() / params.RefundQuotientEIP3529 | ||
| // After EIP-3529: refunds are capped to execution gas / 5 | ||
| refund = st.executionGasUsed() / params.RefundQuotientEIP3529 | ||
| } | ||
| if refund > st.state.GetRefund() { | ||
| refund = st.state.GetRefund() | ||
|
|
@@ -662,6 +683,10 @@ func (st *StateTransition) calcRefund() uint64 { | |
| return refund | ||
| } | ||
|
|
||
| func (st *StateTransition) executionGasUsed() uint64 { | ||
| return st.gasUsed() - st.gasSurcharge | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] Worth a doc comment stating the invariant, since a violation wraps silently rather than panicking. The subtraction is safe today because // executionGasUsed returns the gas consumed by intrinsic cost and EVM execution,
// excluding the non-refundable surcharge. Safe from underflow because gasRemaining
// never exceeds initialGas-gasSurcharge after the surcharge is reserved.There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] This subtraction is unguarded. It is safe today — |
||
| } | ||
|
|
||
| // returnGas returns ETH for remaining gas, | ||
| // exchanged at the original rate. | ||
| func (st *StateTransition) returnGas() { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] The doc comment covers the accounting well but omits the usage contract a caller needs: it must be called before
Execute(), it applies only to this top-level transition (ApplyMessageand nested calls are unaffected), and a gas limit below the surcharge surfaces asErrIntrinsicGas. Worth stating, since the only caller lives outside this repo.