mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-20 11:46:44 +00:00
core/vm: add access cost check
This commit is contained in:
parent
dd8dd1520f
commit
b0b042e44c
2 changed files with 27 additions and 5 deletions
|
|
@ -21,6 +21,7 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -235,3 +236,19 @@ func TestEIP8038SelfdestructAccountWrite(t *testing.T) {
|
|||
t.Fatalf("state gas = %d, want %d", res.UsedStateGas, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP8038SStoreAccessGuard covers the affordability check that bails out
|
||||
// before the slot is read once the gas left cannot cover the slot's access cost.
|
||||
// The two PUSH1s cost 6, so a 2506 budget leaves 2500 at the SSTORE: above the
|
||||
// reentrancy sentry (2300) yet below COLD_STORAGE_ACCESS (3000). The guard must
|
||||
// fire, distinguishable from the sentry/charge OOG by its "slot access" message.
|
||||
func TestEIP8038SStoreAccessGuard(t *testing.T) {
|
||||
budget := NewGasBudget(6+params.SstoreSentryGasEIP2200+200, 0)
|
||||
_, _, err := run8038(t, sstore(0, 1), budget, new(uint256.Int), nil)
|
||||
if err == nil {
|
||||
t.Fatal("expected failure: gas left cannot cover cold-slot access")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "not enough gas for slot access") {
|
||||
t.Fatalf("got %q, want the slot-access guard error", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -696,10 +696,10 @@ func gasSStore8037And8038(evm *EVM, contract *Contract, stack *Stack, mem *Memor
|
|||
return GasCosts{}, errors.New("not enough gas for reentrancy sentry")
|
||||
}
|
||||
var (
|
||||
y, x = stack.back(1), stack.peek()
|
||||
slot = common.Hash(x.Bytes32())
|
||||
current, original = evm.StateDB.GetStateAndCommittedState(contract.Address(), slot)
|
||||
value = common.Hash(y.Bytes32())
|
||||
y, x = stack.back(1), stack.peek()
|
||||
slot = common.Hash(x.Bytes32())
|
||||
value = common.Hash(y.Bytes32())
|
||||
stateSet = params.StorageCreationSize * evm.Context.CostPerStateByte
|
||||
)
|
||||
// Check slot presence in the access list
|
||||
access := params.WarmStorageReadCostEIP2929
|
||||
|
|
@ -707,7 +707,12 @@ func gasSStore8037And8038(evm *EVM, contract *Contract, stack *Stack, mem *Memor
|
|||
access = params.ColdStorageAccessAmsterdam
|
||||
evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
|
||||
}
|
||||
stateSet := params.StorageCreationSize * evm.Context.CostPerStateByte
|
||||
// Check access cost affordability before reading slot
|
||||
if contract.Gas.RegularGas < access {
|
||||
return GasCosts{}, errors.New("not enough gas for slot access")
|
||||
}
|
||||
// Read the slot value for gas cost measurement
|
||||
current, original := evm.StateDB.GetStateAndCommittedState(contract.Address(), slot)
|
||||
|
||||
if current == value { // noop (1)
|
||||
return GasCosts{RegularGas: access}, nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue