mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
core/vm: implement eip-8279: Block Access List Byte Floor
This commit is contained in:
parent
9e04883a85
commit
56408777f0
9 changed files with 207 additions and 17 deletions
|
|
@ -147,7 +147,7 @@ func Transaction(ctx *cli.Context) error {
|
|||
}
|
||||
// For Prague txs, validate the floor data gas.
|
||||
if rules.IsPrague {
|
||||
floorDataGas, err := core.FloorDataGas(rules, tx.Data(), tx.AccessList())
|
||||
floorDataGas, err := core.FloorDataGas(rules, tx.Data(), tx.AccessList(), uint64(len(tx.SetCodeAuthorizations())))
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
results = append(results, r)
|
||||
|
|
|
|||
|
|
@ -151,8 +151,11 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
|
|||
return gas, nil
|
||||
}
|
||||
|
||||
// FloorDataGas computes the minimum gas required for a transaction based on its data tokens (EIP-7623).
|
||||
func FloorDataGas(rules params.Rules, data []byte, accessList types.AccessList) (uint64, error) {
|
||||
// FloorDataGas computes the minimum gas required for a transaction based on its
|
||||
// data tokens (EIP-7623). On Amsterdam it also includes the EIP-8131 per-auth
|
||||
// tx-content floor and the EIP-8279 per-auth Block Access List floor, which
|
||||
// together form the static floor seed extended at runtime by EIP-8279.
|
||||
func FloorDataGas(rules params.Rules, data []byte, accessList types.AccessList, numAuths uint64) (uint64, error) {
|
||||
var (
|
||||
tokens uint64
|
||||
tokenCost uint64
|
||||
|
|
@ -203,7 +206,23 @@ func FloorDataGas(rules params.Rules, data []byte, accessList types.AccessList)
|
|||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
// Minimum gas required for a transaction based on its data tokens (EIP-7623).
|
||||
return params.TxGas + tokens*tokenCost, nil
|
||||
floor := params.TxGas + tokens*tokenCost
|
||||
|
||||
// EIP-8131 / EIP-8279: each EIP-7702 authorization contributes a static
|
||||
// per-auth floor. EIP-8131 prices the 101-byte authorization tuple
|
||||
// (FloorCostPerAuth) and EIP-8279 adds the worst-case BAL bytes the auth
|
||||
// writes when applied (BALBytesPerAuthorization at FloorGasPerByte). The
|
||||
// per-auth BAL term is folded into the static floor because set_delegation
|
||||
// runs outside the EVM's out-of-gas handler and cannot extend the floor at
|
||||
// runtime.
|
||||
if rules.IsAmsterdam && numAuths > 0 {
|
||||
const perAuth = params.FloorCostPerAuth + params.BALBytesPerAuthorization*params.FloorGasPerByte
|
||||
if (math.MaxUint64-floor)/perAuth < numAuths {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
floor += numAuths * perAuth
|
||||
}
|
||||
return floor, nil
|
||||
}
|
||||
|
||||
// toWordSize returns the ceiled word size required for init code payment calculation.
|
||||
|
|
@ -355,6 +374,11 @@ type stateTransition struct {
|
|||
initReservoir uint64 // initial state-gas reservoir carved out of GasLimit (EIP-8037)
|
||||
state vm.StateDB
|
||||
evm *vm.EVM
|
||||
|
||||
// floorGas is the EIP-8279 Block Access List floor accumulator, seeded with
|
||||
// the static floor and extended at runtime via the EVM. It is nil before
|
||||
// Amsterdam. settleGas reads its final value to apply the receipt floor.
|
||||
floorGas *vm.FloorGasAccumulator
|
||||
}
|
||||
|
||||
// newStateTransition initialises and returns a new state transition object.
|
||||
|
|
@ -645,7 +669,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
// Validate the EIP-7623 calldata floor against the gas limit. The floor inflates
|
||||
// the total gas usage at tx end, so the gas limit must be sufficient to cover that.
|
||||
if rules.IsPrague {
|
||||
floorDataGas, err = FloorDataGas(rules, msg.Data, msg.AccessList)
|
||||
floorDataGas, err = FloorDataGas(rules, msg.Data, msg.AccessList, uint64(len(msg.SetCodeAuthorizations)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -661,6 +685,15 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// EIP-8279: seed the per-transaction Block Access List floor accumulator
|
||||
// with the static floor and bound it by the transaction gas limit. The
|
||||
// accumulator is extended at runtime as opcodes contribute BAL bytes; at
|
||||
// settlement the receipt gas becomes max(execution_gas, floor_gas_used).
|
||||
if rules.IsAmsterdam {
|
||||
st.floorGas = vm.NewFloorGasAccumulator(floorDataGas, msg.GasLimit)
|
||||
st.evm.SetFloorGas(st.floorGas)
|
||||
}
|
||||
|
||||
if rules.IsEIP4762 {
|
||||
st.evm.AccessEvents.AddTxOrigin(msg.From)
|
||||
|
||||
|
|
@ -837,25 +870,34 @@ func (st *stateTransition) settleGas(rules params.Rules, floorDataGas uint64) (g
|
|||
gasLeft += refund
|
||||
gasUsed = gasUsedBeforeRefund - refund
|
||||
|
||||
// EIP-7623: tx_gas_used = max(tx_gas_used_after_refund, calldata_floor).
|
||||
// EIP-8279: the effective floor is the runtime accumulator (seeded with the
|
||||
// static floorDataGas and extended by the BAL bytes opcodes contributed). It
|
||||
// is always >= floorDataGas when the accumulator is active (Amsterdam); the
|
||||
// max keeps the pre-Amsterdam / accumulator-less path on the static floor.
|
||||
floorGas := floorDataGas
|
||||
if st.floorGas != nil {
|
||||
floorGas = max(floorGas, st.floorGas.FloorGasUsed())
|
||||
}
|
||||
|
||||
// EIP-7623: tx_gas_used = max(tx_gas_used_after_refund, floor).
|
||||
peakUsed = gasUsedBeforeRefund
|
||||
if rules.IsPrague && gasUsed < floorDataGas {
|
||||
diff := floorDataGas - gasUsed
|
||||
if rules.IsPrague && gasUsed < floorGas {
|
||||
diff := floorGas - gasUsed
|
||||
if st.evm.Config.Tracer.HasGasHook() {
|
||||
st.evm.Config.Tracer.EmitGasChange(tracing.Gas{Regular: gasLeft}, tracing.Gas{Regular: gasLeft - diff}, tracing.GasChangeTxDataFloor)
|
||||
}
|
||||
gasLeft -= diff
|
||||
gasUsed = floorDataGas
|
||||
peakUsed = max(peakUsed, floorDataGas)
|
||||
gasUsed = floorGas
|
||||
peakUsed = max(peakUsed, floorGas)
|
||||
}
|
||||
|
||||
if rules.IsAmsterdam {
|
||||
// EIP-7623/7976: the calldata floor applies to the block-level regular
|
||||
// gas dimension as well, mirroring its effect on the receipt gas. The
|
||||
// spec accumulates max(tx_regular_gas, calldata_floor) into
|
||||
// block_gas_used, so the block must never count fewer regular units
|
||||
// than the floor the sender was charged.
|
||||
blockRegularGas := max(txRegularGas, floorDataGas)
|
||||
// spec accumulates max(tx_regular_gas, floor) into block_gas_used, so the
|
||||
// block must never count fewer regular units than the floor the sender
|
||||
// was charged. EIP-8279 widens the floor to include BAL byte costs.
|
||||
blockRegularGas := max(txRegularGas, floorGas)
|
||||
if err = st.gp.ChargeGasAmsterdam(blockRegularGas, txStateGas, gasUsed); err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ func TestFloorDataGas(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rules := params.Rules{IsAmsterdam: tt.amsterdam}
|
||||
got, err := FloorDataGas(rules, tt.data, tt.accessList)
|
||||
got, err := FloorDataGas(rules, tt.data, tt.accessList, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
|
|||
}
|
||||
// Ensure the transaction can cover floor data gas.
|
||||
if rules.IsPrague {
|
||||
floorDataGas, err := core.FloorDataGas(rules, tx.Data(), tx.AccessList())
|
||||
floorDataGas, err := core.FloorDataGas(rules, tx.Data(), tx.AccessList(), uint64(len(tx.SetCodeAuthorizations())))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,6 +131,13 @@ type EVM struct {
|
|||
returnData []byte // Last CALL's return data for subsequent reuse
|
||||
|
||||
arena *stackArena
|
||||
|
||||
// floorGas is the per-transaction EIP-8279 Block Access List byte-floor
|
||||
// accumulator. It is set by the state transition at the start of each
|
||||
// transaction and extended at runtime as opcodes contribute BAL bytes. It
|
||||
// is nil before EIP-8279 (Amsterdam) or in contexts without BAL
|
||||
// construction, in which case the runtime extensions are no-ops.
|
||||
floorGas *FloorGasAccumulator
|
||||
}
|
||||
|
||||
// NewEVM constructs an EVM instance with the supplied block context, state
|
||||
|
|
@ -222,6 +229,26 @@ func (evm *EVM) SetTxContext(txCtx TxContext) {
|
|||
evm.TxContext = txCtx
|
||||
}
|
||||
|
||||
// SetFloorGas installs the per-transaction EIP-8279 floor accumulator. It is
|
||||
// called by the state transition once the static floor seed and gas limit are
|
||||
// known. Passing nil disables runtime floor extensions for the transaction.
|
||||
func (evm *EVM) SetFloorGas(acc *FloorGasAccumulator) {
|
||||
evm.floorGas = acc
|
||||
}
|
||||
|
||||
// FloorGas returns the active EIP-8279 floor accumulator, or nil if none is set.
|
||||
func (evm *EVM) FloorGas() *FloorGasAccumulator {
|
||||
return evm.floorGas
|
||||
}
|
||||
|
||||
// extendFloor extends the EIP-8279 floor accumulator by numBytes BAL bytes. It
|
||||
// is a no-op when no accumulator is installed (pre-Amsterdam or BAL-less
|
||||
// contexts). The returned error, when non-nil, is ErrOutOfGas and MUST abort
|
||||
// the operation before the matching BAL byte is inserted.
|
||||
func (evm *EVM) extendFloor(numBytes uint64) error {
|
||||
return evm.floorGas.extendFloor(numBytes)
|
||||
}
|
||||
|
||||
// Cancel cancels any running EVM operation. This may be called concurrently and
|
||||
// it's safe to be called multiple times.
|
||||
func (evm *EVM) Cancel() {
|
||||
|
|
@ -524,6 +551,15 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
|
|||
}
|
||||
}
|
||||
|
||||
// EIP-8279: an opcode-level CREATE/CREATE2 records the deployed address in
|
||||
// the BAL. The top-level creation transaction's contract address is part of
|
||||
// the implicit per-tx bytes covered by TX_BASE headroom, so only nested
|
||||
// creations extend the floor here.
|
||||
if evm.depth > 0 {
|
||||
if err = evm.extendFloor(params.BALBytesPerAddress); err != nil {
|
||||
return nil, common.Address{}, gas.ExitHalt(), err
|
||||
}
|
||||
}
|
||||
// We add this to the access list _before_ taking a snapshot. Even if the
|
||||
// creation fails, the access-list change should not be rolled back.
|
||||
if evm.chainRules.IsEIP2929 {
|
||||
|
|
@ -562,6 +598,21 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
|
|||
// acts inside that account.
|
||||
evm.StateDB.CreateContract(address)
|
||||
|
||||
// EIP-8279: an opcode-level CREATE/CREATE2 sets the new contract's nonce
|
||||
// (and, with a non-zero endowment, its balance), both recorded in the BAL.
|
||||
// The floor is extended after the collision check, before the state
|
||||
// mutation. The top-level creation transaction's nonce is covered by
|
||||
// TX_BASE headroom, so only nested creations extend the floor here.
|
||||
if evm.depth > 0 {
|
||||
if err = evm.extendFloor(params.BALBytesPerNonce); err != nil {
|
||||
return nil, common.Address{}, gas.ExitHalt(), err
|
||||
}
|
||||
if !value.IsZero() {
|
||||
if err = evm.extendFloor(params.BALBytesPerBalance); err != nil {
|
||||
return nil, common.Address{}, gas.ExitHalt(), err
|
||||
}
|
||||
}
|
||||
}
|
||||
if evm.chainRules.IsEIP158 {
|
||||
evm.StateDB.SetNonce(address, 1, tracing.NonceChangeNewContract)
|
||||
}
|
||||
|
|
@ -668,6 +719,16 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address) (ret
|
|||
return ret, true, err
|
||||
}
|
||||
}
|
||||
// EIP-8279: a successful opcode-level CREATE/CREATE2 deploy records the
|
||||
// deployed code in the BAL. Extend the floor by the code length before
|
||||
// set_code. A top-level creation transaction's deployed code is bounded by
|
||||
// the calldata floor on its init code, so only nested creations extend the
|
||||
// floor here.
|
||||
if evm.depth > 0 && len(ret) > 0 {
|
||||
if err := evm.extendFloor(uint64(len(ret))); err != nil {
|
||||
return ret, true, err
|
||||
}
|
||||
}
|
||||
if len(ret) > 0 {
|
||||
evm.StateDB.SetCode(address, ret, tracing.CodeChangeContractCreation)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -504,6 +504,15 @@ func gasCallIntrinsic(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
|
|||
}
|
||||
// Stateful check
|
||||
if evm.chainRules.IsAmsterdam {
|
||||
// EIP-8279: a CALL transferring non-zero value to a different account
|
||||
// records a balance change for the recipient in the BAL. Extend the
|
||||
// floor by the balance bytes before the transfer. A self-call moves no
|
||||
// value out of the executing account and adds no balance bytes.
|
||||
if transfersValue && address != contract.Address() {
|
||||
if err := evm.extendFloor(params.BALBytesPerBalance); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
// EIP-8037: the cost of creating a new account via a value-bearing
|
||||
// CALL is metered as state gas (NEW_ACCOUNT * CostPerStateByte),
|
||||
// not the legacy regular CallNewAccountGas. It drains the state
|
||||
|
|
@ -604,6 +613,10 @@ func gasSelfdestruct8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory
|
|||
address = common.Address(stack.peek().Bytes20())
|
||||
)
|
||||
if !evm.StateDB.AddressInAccessList(address) {
|
||||
// EIP-8279: a cold beneficiary access adds the address to the BAL.
|
||||
if err := evm.extendFloor(params.BALBytesPerAddress); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
// If the caller cannot afford the cost, this change will be rolled back
|
||||
evm.StateDB.AddAddressToAccessList(address)
|
||||
gas.RegularGas = params.ColdAccountAccessCostEIP2929
|
||||
|
|
@ -612,6 +625,14 @@ func gasSelfdestruct8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory
|
|||
if contract.Gas.RegularGas < gas.RegularGas {
|
||||
return gas, ErrOutOfGas
|
||||
}
|
||||
// EIP-8279: SELFDESTRUCT moving a non-zero balance to a different beneficiary
|
||||
// records the beneficiary's balance change in the BAL. A self-targeted
|
||||
// SELFDESTRUCT moves no value out and adds no balance bytes.
|
||||
if address != contract.Address() && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
|
||||
if err := evm.extendFloor(params.BALBytesPerBalance); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
}
|
||||
// Important: use StateDB.Empty instead of !StateDB.Exist. An account may exist
|
||||
// in the current state yet still be considered non-existent by EIP-161 if its
|
||||
// nonce, balance, and code are all zero. Such accounts can appear temporarily
|
||||
|
|
@ -641,12 +662,29 @@ func gasSStore8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memo
|
|||
)
|
||||
// Check slot presence in the access list
|
||||
if _, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent {
|
||||
// EIP-8279: a cold SSTORE adds the storage key to the BAL. Extend the
|
||||
// floor before the slot is recorded; an out-of-gas here aborts the
|
||||
// opcode before the unpaid BAL byte exists.
|
||||
if err := evm.extendFloor(params.BALBytesPerStorageKey); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
cost = GasCosts{RegularGas: params.ColdSloadCostEIP2929}
|
||||
// If the caller cannot afford the cost, this change will be rolled back
|
||||
evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
|
||||
}
|
||||
value := common.Hash(y.Bytes32())
|
||||
|
||||
// EIP-8279: an SSTORE that changes the slot's current value contributes a
|
||||
// post-value to the BAL. Charge the value bytes whenever the value differs,
|
||||
// mirroring the BAL StorageWrite. This may over-charge when the same slot is
|
||||
// written more than once in a transaction (the BAL records only one final
|
||||
// post-value per slot), which is safe: it never under-charges.
|
||||
if current != value {
|
||||
if err := evm.extendFloor(params.BALBytesPerStorageValue); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
}
|
||||
|
||||
if current == value { // noop (1)
|
||||
// EIP 2200 original clause:
|
||||
// return params.SloadGasEIP2200, nil
|
||||
|
|
|
|||
|
|
@ -103,6 +103,12 @@ func gasSLoadEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
|
|||
slot := common.Hash(loc.Bytes32())
|
||||
// Check slot presence in the access list
|
||||
if _, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent {
|
||||
// EIP-8279: a cold SLOAD adds the storage key to the BAL. Extend the
|
||||
// floor before the slot is recorded; an out-of-gas here aborts the
|
||||
// opcode before the unpaid BAL byte exists.
|
||||
if err := evm.extendFloor(params.BALBytesPerStorageKey); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
// If the caller cannot afford the cost, this change will be rolled back
|
||||
// If he does afford it, we can skip checking the same thing later on, during execution
|
||||
evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
|
||||
|
|
@ -126,6 +132,10 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
|
|||
addr := common.Address(stack.peek().Bytes20())
|
||||
// Check slot presence in the access list
|
||||
if !evm.StateDB.AddressInAccessList(addr) {
|
||||
// EIP-8279: a cold account access adds the address to the BAL.
|
||||
if err := evm.extendFloor(params.BALBytesPerAddress); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
evm.StateDB.AddAddressToAccessList(addr)
|
||||
var overflow bool
|
||||
// We charge (cold-warm), since 'warm' is already charged as constantGas
|
||||
|
|
@ -148,6 +158,10 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem
|
|||
addr := common.Address(stack.peek().Bytes20())
|
||||
// Check slot presence in the access list
|
||||
if !evm.StateDB.AddressInAccessList(addr) {
|
||||
// EIP-8279: a cold account access adds the address to the BAL.
|
||||
if err := evm.extendFloor(params.BALBytesPerAddress); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
// If the caller cannot afford the cost, this change will be rolled back
|
||||
evm.StateDB.AddAddressToAccessList(addr)
|
||||
// The warm storage read cost is already charged as constantGas
|
||||
|
|
@ -165,6 +179,10 @@ func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) g
|
|||
// the cost to charge for cold access, if any, is Cold - Warm
|
||||
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
|
||||
if !warmAccess {
|
||||
// EIP-8279: a cold account access adds the address to the BAL.
|
||||
if err := evm.extendFloor(params.BALBytesPerAddress); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
evm.StateDB.AddAddressToAccessList(addr)
|
||||
// Charge the remaining difference here already, to correctly calculate available
|
||||
// gas for call
|
||||
|
|
@ -286,6 +304,10 @@ func makeCallVariantGasCallEIP7702(intrinsicFunc intrinsicGasFunc) gasFunc {
|
|||
// Perform EIP-2929 checks (stateless), checking address presence
|
||||
// in the accessList and charge the cold access accordingly.
|
||||
if !evm.StateDB.AddressInAccessList(addr) {
|
||||
// EIP-8279: a cold account access adds the address to the BAL.
|
||||
if err := evm.extendFloor(params.BALBytesPerAddress); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
evm.StateDB.AddAddressToAccessList(addr)
|
||||
|
||||
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form
|
||||
|
|
@ -321,6 +343,11 @@ func makeCallVariantGasCallEIP7702(intrinsicFunc intrinsicGasFunc) gasFunc {
|
|||
if evm.StateDB.AddressInAccessList(target) {
|
||||
eip7702Cost = params.WarmStorageReadCostEIP2929
|
||||
} else {
|
||||
// EIP-8279: resolving a cold delegation target adds its address
|
||||
// to the BAL.
|
||||
if err := evm.extendFloor(params.BALBytesPerAddress); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
evm.StateDB.AddAddressToAccessList(target)
|
||||
eip7702Cost = params.ColdAccountAccessCostEIP2929
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,28 @@ const (
|
|||
TxAuthTupleGas uint64 = 12500 // Per auth tuple code specified in EIP-7702
|
||||
TxAuthTupleRegularGas uint64 = 7500 // Per auth tuple regular gas specified in EIP-8037
|
||||
|
||||
// FloorCostPerAuth is the per-authorization tx-content floor contribution
|
||||
// defined by EIP-8131: an EIP-7702 authorization tuple is 101 bytes, charged
|
||||
// at the floor rate (101 * TxCostFloorPerToken7976 * TxTokenPerNonZeroByte).
|
||||
FloorCostPerAuth uint64 = 101 * TxCostFloorPerToken7976 * TxTokenPerNonZeroByte // 6464
|
||||
|
||||
// EIP-8279: Block Access List Byte Floor. Each byte an opcode adds to the
|
||||
// EIP-7928 Block Access List extends the transaction's floor accumulator by
|
||||
// FloorGasPerByte gas, charged at runtime before the BAL grows.
|
||||
FloorGasPerByte uint64 = TxCostFloorPerToken7976 * TxTokenPerNonZeroByte // 64: per-byte floor rate (EIP-7976)
|
||||
BALBytesPerAddress uint64 = 20 // BAL bytes for an account address
|
||||
BALBytesPerStorageKey uint64 = 32 // BAL bytes for a storage key
|
||||
BALBytesPerStorageValue uint64 = 32 // BAL bytes for a storage post-value
|
||||
BALBytesPerBalance uint64 = 32 // BAL bytes for a balance change
|
||||
BALBytesPerNonce uint64 = 8 // BAL bytes for a nonce change
|
||||
BALDelegationCodeBytes uint64 = 23 // EIP-7702 delegation marker length
|
||||
// BALBytesPerAuthorization is the worst-case BAL contribution an EIP-7702
|
||||
// authorization adds when it is applied: the authority address, the
|
||||
// delegation marker written to its code, and its nonce change. It is folded
|
||||
// into the static floor seed since set_delegation runs outside the EVM's
|
||||
// out-of-gas handler.
|
||||
BALBytesPerAuthorization uint64 = BALBytesPerAddress + BALDelegationCodeBytes + BALBytesPerNonce // 51
|
||||
|
||||
// These have been changed during the course of the chain
|
||||
CallGasFrontier uint64 = 40 // Once per CALL operation & message call transaction.
|
||||
CallGasEIP150 uint64 = 700 // Static portion of gas for CALL-derivates after EIP 150 (Tangerine)
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ func (tt *TransactionTest) Run() error {
|
|||
|
||||
if rules.IsPrague {
|
||||
var floorDataGas uint64
|
||||
floorDataGas, err = core.FloorDataGas(rules, tx.Data(), tx.AccessList())
|
||||
floorDataGas, err = core.FloorDataGas(rules, tx.Data(), tx.AccessList(), uint64(len(tx.SetCodeAuthorizations())))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue