mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 07:58:40 +00:00
core/vm: introduce eip-8037 gas metering for SSTORE
This commit is contained in:
parent
01036bed83
commit
93ffef90cc
4 changed files with 62 additions and 9 deletions
|
|
@ -43,6 +43,7 @@ var activators = map[int]func(*JumpTable){
|
|||
7939: enable7939,
|
||||
8024: enable8024,
|
||||
7843: enable7843,
|
||||
8037: enable8037,
|
||||
}
|
||||
|
||||
// EnableEIP enables the given EIP on the config.
|
||||
|
|
@ -590,3 +591,9 @@ func enable7843(jt *JumpTable) {
|
|||
maxStack: maxStack(0, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// enable8037 applies EIP-8037: State Creation Gas Cost Increase
|
||||
func enable8037(jt *JumpTable) {
|
||||
jt[SLOAD].constantGas = params.SloadGasEIP2200
|
||||
jt[SSTORE].dynamicGas = gasSStoreEIP8037
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,6 +226,52 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
|
|||
return GasCosts{RegularGas: params.SloadGasEIP2200}, nil // dirty update (2.2)
|
||||
}
|
||||
|
||||
// EIP-8037 constants. EIP-8037 only diverges from EIP-2200 on slots whose
|
||||
// tx-original is zero AND on writes that cross the zero/non-zero boundary
|
||||
// (i.e. a state creation or its in-tx undo). Everything else stays on the
|
||||
// EIP-2200 schedule.
|
||||
const (
|
||||
stateBytesPerSlotEIP8037 = 64 // bytes attributed to one slot's state
|
||||
costPerStateByteEIP8037 = 1157 // gas per state-creation byte
|
||||
sstoreBaseGasEIP8037 = 2900 // regular gas baseline for the EIP-8037 transitions
|
||||
stateGasEIP8037 = stateBytesPerSlotEIP8037 * costPerStateByteEIP8037
|
||||
)
|
||||
|
||||
// gasSStoreEIP8037 prices SSTORE under EIP-8037.
|
||||
//
|
||||
// Two specific (original, current, value) shapes get the new pricing:
|
||||
// - O == 0, C == 0, V != 0 — creating fresh state in this tx.
|
||||
// Charge stateGasEIP8037 of state gas and sstoreBaseGasEIP8037 of regular gas.
|
||||
// - O == 0, C != 0, V == 0 — undoing the in-tx creation.
|
||||
// Refund stateGasEIP8037 of state gas (negative StateGas in the cost
|
||||
// vector) and pay sstoreBaseGasEIP8037 of regular gas.
|
||||
//
|
||||
// Every other shape — including O != 0 of any kind, and O == 0 cases that
|
||||
// don't cross zero — defers to gasSStoreEIP2200 unchanged.
|
||||
func gasSStoreEIP8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
if evm.readOnly {
|
||||
return GasCosts{}, ErrWriteProtection
|
||||
}
|
||||
if contract.Gas.RegularGas <= params.SstoreSentryGasEIP2200 {
|
||||
return GasCosts{}, errors.New("not enough gas for reentrancy sentry")
|
||||
}
|
||||
var (
|
||||
zero = common.Hash{}
|
||||
y, x = stack.back(1), stack.back(0)
|
||||
current, original = evm.StateDB.GetStateAndCommittedState(contract.Address(), x.Bytes32())
|
||||
value = common.Hash(y.Bytes32())
|
||||
)
|
||||
if original == zero {
|
||||
switch {
|
||||
case current == zero && value != zero: // creation
|
||||
return GasCosts{RegularGas: sstoreBaseGasEIP8037, StateGas: stateGasEIP8037}, nil
|
||||
case current != zero && value == zero: // undo creation
|
||||
return GasCosts{RegularGas: sstoreBaseGasEIP8037, StateGas: -stateGasEIP8037}, nil
|
||||
}
|
||||
}
|
||||
return gasSStoreEIP2200(evm, contract, stack, mem, memorySize)
|
||||
}
|
||||
|
||||
func makeGasLog(n uint64) gasFunc {
|
||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
requestedSize, overflow := stack.back(1).Uint64WithOverflow()
|
||||
|
|
|
|||
|
|
@ -18,17 +18,16 @@ package vm
|
|||
|
||||
import "fmt"
|
||||
|
||||
// GasCosts denotes a vector of gas costs in the
|
||||
// multidimensional metering paradigm. It represents the cost
|
||||
// charged by an individual operation.
|
||||
// GasCosts denotes a vector of gas costs in the multidimensional metering
|
||||
// paradigm. It represents the cost charged by an individual operation.
|
||||
//
|
||||
// StateGas is signed so an operation can express a state-gas refund
|
||||
// (negative cost) — e.g. an SSTORE that undoes an in-tx state creation.
|
||||
// Such a refund flows back into the StateGas reservoir of the GasBudget,
|
||||
// not into RegularGas.
|
||||
type GasCosts struct {
|
||||
RegularGas uint64
|
||||
StateGas uint64
|
||||
}
|
||||
|
||||
// Sum returns the total gas (regular + state).
|
||||
func (g GasCosts) Sum() uint64 {
|
||||
return g.RegularGas + g.StateGas
|
||||
StateGas int64
|
||||
}
|
||||
|
||||
// String returns a visual representation of the gas vector.
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ func newAmsterdamInstructionSet() JumpTable {
|
|||
instructionSet := newOsakaInstructionSet()
|
||||
enable7843(&instructionSet) // EIP-7843 (SLOTNUM opcode)
|
||||
enable8024(&instructionSet) // EIP-8024 (Backward compatible SWAPN, DUPN, EXCHANGE)
|
||||
enable8037(&instructionSet) // EIP-8037 (State Creation Gas Cost Increase)
|
||||
return validate(instructionSet)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue