Skip to content

Commit fc8a21f

Browse files
authored
Merge pull request #80 from ethpandaops/chore/7778-comments
docs: clarify gas semantics for EIP-7778 split between receipt and block gas
2 parents 3d4921c + 5592696 commit fc8a21f

File tree

4 files changed

+33
-8
lines changed

4 files changed

+33
-8
lines changed

pkg/ethereum/execution/block.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ type Receipt interface {
131131
// TxHash returns the transaction hash.
132132
TxHash() Hash
133133

134-
// GasUsed returns the gas used by the transaction.
134+
// GasUsed returns the post-refund gas used by the transaction (what the user pays).
135+
//
136+
// EIP-7778 context: This remains post-refund. The EIP-7778 split between receipt gas
137+
// and block gas only affects ExecutionResult at the EVM layer; the Receipt's GasUsed
138+
// field and its derivation from CumulativeGasUsed are unchanged.
135139
GasUsed() uint64
136140
}

pkg/ethereum/execution/structlog.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
package execution
22

3+
// TraceTransaction holds the result of a debug_traceTransaction call.
34
type TraceTransaction struct {
5+
// Gas is the post-refund gas used by this transaction (what the user pays).
6+
// Set by the data source from the execution result or receipt's GasUsed.
7+
//
8+
// EIP-7778 context: After EIP-7778, Ethereum splits gas accounting into:
9+
// - ReceiptGasUsed (post-refund): what the user pays, stored in receipts
10+
// - BlockGasUsed (pre-refund): used for block gas limit accounting
11+
// This field carries the receipt (post-refund) value. The computeIntrinsicGas()
12+
// formula in structlog_agg depends on this being post-refund.
413
Gas uint64 `json:"gas"`
514
Failed bool `json:"failed"`
615
ReturnValue *string `json:"returnValue"`

pkg/processor/transaction/structlog_agg/aggregator.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,17 @@ func mapOpcodeToCallType(op string) string {
356356
// computeIntrinsicGas computes the intrinsic gas for a transaction.
357357
// This is the gas consumed before EVM execution begins (21000 base + calldata costs).
358358
//
359-
// Formula from int_transaction_call_frame.sql:
359+
// The receiptGas parameter MUST be the post-refund value (what the user pays).
360+
// This is the value from Receipt.GasUsed / ExecutionResult.ReceiptGasUsed.
360361
//
361-
// IF gas_refund >= receipt_gas / 4 THEN
362-
// intrinsic = receipt_gas * 5 / 4 - gas_cumulative (refund was capped)
363-
// ELSE
364-
// intrinsic = receipt_gas - gas_cumulative + gas_refund (uncapped)
362+
// EIP-7778 context: This formula remains correct after EIP-7778. The EIP splits
363+
// ExecutionResult into ReceiptGasUsed (post-refund) and BlockGasUsed (pre-refund),
364+
// but the receipt gas semantics that this formula depends on are unchanged.
365+
//
366+
// The computed intrinsic gas value does not encode whether the EVM refund cap
367+
// (EIP-3529: max refund = gasUsed/5) was applied. It is up to the consumer of
368+
// this data to determine whether the cap was hit, using the gas_refund and
369+
// gas_used columns.
365370
func computeIntrinsicGas(gasCumulative, gasRefund, receiptGas uint64) uint64 {
366371
if receiptGas == 0 {
367372
return 0

pkg/processor/transaction/structlog_agg/transaction_processing.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func (p *Processor) ProcessTransaction(ctx context.Context, block execution.Bloc
7070

7171
// For simple transfers (no EVM execution), all gas is intrinsic.
7272
// This is true for both successful and failed transactions.
73+
// trace.Gas is the post-refund receipt gas — see TraceTransaction.Gas doc.
7374
intrinsicGas := trace.Gas
7475
rootFrame.IntrinsicGas = &intrinsicGas
7576

@@ -158,8 +159,14 @@ func (p *Processor) ProcessTransaction(ctx context.Context, block execution.Bloc
158159
aggregator.SetRootTargetAddress(&addr)
159160
}
160161

161-
// Get receipt gas for intrinsic gas calculation
162-
// For now, we use trace.Gas as a proxy (TODO: get actual receipt gas from block receipts)
162+
// Get receipt gas for intrinsic gas calculation.
163+
// trace.Gas is the post-refund receipt gas set by the data source (erigone/xatu sets
164+
// this from ExecutionResult.ReceiptGasUsed; RPC mode gets it from receipt.GasUsed).
165+
//
166+
// EIP-7778 context: computeIntrinsicGas() requires the post-refund value because its
167+
// formula accounts for refunds: intrinsic = receiptGas - gasCumulative + gasRefund.
168+
// This is correct both pre- and post-EIP-7778 since ReceiptGasUsed preserves the
169+
// same post-refund semantics that GasUsed had before the split.
163170
receiptGas := trace.Gas
164171

165172
// Finalize aggregation and get call frame rows

0 commit comments

Comments
 (0)