EIP-3978 - Gas refunds on reverts

Created 2021-09-16
Updated Feb. 14, 2022, midnight
Status Stagnant
Category Core
Type Standards Track
Authors
Requires

Abstract

For reverted state modification operations, keep access cost, but refund modification cost.

Motivation

Reverting a transaction, or any of its sub-calls, drops any state modifications that happened inside. But now, users are being charged for the dropped modifications as if they persisted.

Since EIP-3298, the gas refund mechanism works for storage restores only inside the same transaction. But on revert, the gas refund is not increased; it is completely erased. It can even be cheaper to transfer tokens back at the end of a transaction instead of reverting, to keep the existing gas refund. This should be changed.

Moreover, it seems fair to charge CREATE and CREATE2 operations 32,000 fix price conditionally only if returned bytecode is not empty.

Specification

For each callframe, track revert_gas_refund, initially 0.

The set of operations that modify revert_gas_refund are: - SSTORE - LOG0, LOG1, LOG2, LOG3, LOG4 - CALL - CREATE, CREATE2 - SELFDESTRUCT

They increase revert_gas_refund as follows:

call.revert_gas_refund += operation.gas - WARM_STORAGE_READ_COST

And in case of revert let's use this value instead of just erasing gas_refund:

if (call.reverted) {
    // existing behavior
    tx.gas_refund -= call.gas_refund;

    // New behavior added to existing according to the EIP-3978
    tx.gas_refund += call.revert_gas_refund;
}

Rationale

Gas should reflect the cost of use. The revert cost reflects the cost of access during execution, but not the cost of modification.

Backwards Compatibility

No known backward incompatibilities.

Test Cases

TBD

Reference Implementation

TBD

Security Considerations

TBD

Copyright

Copyright and related rights waived via CC0.