mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-29 09:47:38 +00:00
core: implement EIP-2780 (#35212)
Implements https://eips.ethereum.org/EIPS/eip-2780 --------- Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
This commit is contained in:
parent
ab134b2101
commit
07dd8e052f
12 changed files with 407 additions and 51 deletions
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/tests"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
@ -132,8 +133,14 @@ func Transaction(ctx *cli.Context) error {
|
|||
r.Address = sender
|
||||
}
|
||||
// Check intrinsic gas
|
||||
value, overflow := uint256.FromBig(tx.Value())
|
||||
if overflow {
|
||||
// A 256-bit overflow is reported by the field validation below; use a
|
||||
// non-zero placeholder so intrinsic gas is still computed and reported.
|
||||
value = uint256.NewInt(1)
|
||||
}
|
||||
rules := chainConfig.Rules(common.Big0, true, 0)
|
||||
cost, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules, params.CostPerStateByte)
|
||||
cost, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), r.Address, tx.To(), value, rules, params.CostPerStateByte)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
results = append(results, r)
|
||||
|
|
@ -147,7 +154,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, r.Address, tx.To(), value, tx.Data(), tx.AccessList())
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
results = append(results, r)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
|
|||
data := make([]byte, nbytes)
|
||||
return func(i int, gen *BlockGen) {
|
||||
toaddr := common.Address{}
|
||||
cost, _ := IntrinsicGas(data, nil, nil, false, params.Rules{}, params.CostPerStateByte)
|
||||
cost, _ := IntrinsicGas(data, nil, nil, common.Address{}, &toaddr, nil, params.Rules{}, params.CostPerStateByte)
|
||||
signer := gen.Signer()
|
||||
gasPrice := big.NewInt(0)
|
||||
if gen.header.BaseFee != nil {
|
||||
|
|
|
|||
|
|
@ -64,12 +64,12 @@ var (
|
|||
func TestProcessUBT(t *testing.T) {
|
||||
var (
|
||||
code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`)
|
||||
intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, nil, true, params.Rules{IsHomestead: true, IsIstanbul: true, IsShanghai: true}, 0)
|
||||
intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, nil, common.Address{}, nil, nil, params.Rules{IsHomestead: true, IsIstanbul: true, IsShanghai: true}, 0)
|
||||
// A contract creation that calls EXTCODECOPY in the constructor. Used to ensure that the witness
|
||||
// will not contain that copied data.
|
||||
// Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985
|
||||
codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`)
|
||||
intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, nil, true, params.Rules{IsHomestead: true, IsIstanbul: true, IsShanghai: true}, 0)
|
||||
intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, nil, common.Address{}, nil, nil, params.Rules{IsHomestead: true, IsIstanbul: true, IsShanghai: true}, 0)
|
||||
signer = types.LatestSigner(testUBTChainConfig)
|
||||
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain
|
||||
|
|
|
|||
214
core/eip2780_test.go
Normal file
214
core/eip2780_test.go
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
// Copyright 2026 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// TestEIP2780Intrinsic checks the intrinsic-gas decomposition.
|
||||
func TestEIP2780Intrinsic(t *testing.T) {
|
||||
var (
|
||||
from = common.HexToAddress("0x1111111111111111111111111111111111111111")
|
||||
to = common.HexToAddress("0x2222222222222222222222222222222222222222")
|
||||
)
|
||||
cases := []struct {
|
||||
name string
|
||||
to *common.Address
|
||||
value *uint256.Int
|
||||
want vm.GasCosts
|
||||
}{
|
||||
{
|
||||
name: "self-transfer",
|
||||
to: &from,
|
||||
value: uint256.NewInt(1),
|
||||
want: vm.GasCosts{RegularGas: params.TxBaseCost2780}, // 12,000
|
||||
},
|
||||
{
|
||||
name: "self-transfer/zero-value",
|
||||
to: &from,
|
||||
value: uint256.NewInt(0),
|
||||
want: vm.GasCosts{RegularGas: params.TxBaseCost2780}, // 12,000
|
||||
},
|
||||
{
|
||||
name: "zero-value call",
|
||||
to: &to,
|
||||
value: uint256.NewInt(0),
|
||||
// TxBaseCost + ColdAccountAccess = 15,000
|
||||
want: vm.GasCosts{RegularGas: params.TxBaseCost2780 + params.ColdAccountAccess2780},
|
||||
},
|
||||
{
|
||||
name: "value transfer to existing EOA",
|
||||
to: &to,
|
||||
value: uint256.NewInt(1),
|
||||
// TxBaseCost + ColdAccountAccess + TxValueCost + TransferLogCost = 21,000
|
||||
want: vm.GasCosts{RegularGas: params.TxBaseCost2780 + params.ColdAccountAccess2780 +
|
||||
params.TxValueCost2780 + params.TransferLogCost2780},
|
||||
},
|
||||
{
|
||||
name: "contract creation, value = 0",
|
||||
to: nil,
|
||||
value: uint256.NewInt(0),
|
||||
// TxBaseCost + CreateAccess = 23,000 regular, plus one account creation in state.
|
||||
want: vm.GasCosts{
|
||||
RegularGas: params.TxBaseCost2780 + params.CreateAccess2780,
|
||||
StateGas: params.AccountCreationSize * params.CostPerStateByte,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "contract creation, value > 0",
|
||||
to: nil,
|
||||
value: uint256.NewInt(1),
|
||||
// TxBaseCost + CreateAccess + TransferLogCost = 24,756 regular, plus account creation.
|
||||
want: vm.GasCosts{
|
||||
RegularGas: params.TxBaseCost2780 + params.CreateAccess2780 + params.TransferLogCost2780,
|
||||
StateGas: params.AccountCreationSize * params.CostPerStateByte,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got, err := IntrinsicGas(nil, nil, nil, from, tc.to, tc.value, rules8037, params.CostPerStateByte)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got != tc.want {
|
||||
t.Fatalf("gas mismatch: got %+v, want %+v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP2780Gas checks every "Transaction reference case" in
|
||||
// the EIP-2780 specification end-to-end, asserting the two-dimensional charge
|
||||
// (intrinsic + top-level + execution) recorded in the block gas pool.
|
||||
func TestEIP2780Gas(t *testing.T) {
|
||||
const (
|
||||
cold = params.ColdAccountAccess2780
|
||||
base = params.TxBaseCost2780
|
||||
valueCst = params.TxValueCost2780 + params.TransferLogCost2780
|
||||
)
|
||||
var (
|
||||
existingEOA = common.HexToAddress("0xe0a0000000000000000000000000000000000001")
|
||||
stopContract = common.HexToAddress("0xc0de000000000000000000000000000000000001")
|
||||
delegated = common.HexToAddress("0xde1e000000000000000000000000000000000001")
|
||||
emptyTarget = common.HexToAddress("0x7a76000000000000000000000000000000000001") // never allocated
|
||||
freshEOA = common.HexToAddress("0xbeef000000000000000000000000000000000001") // never allocated
|
||||
)
|
||||
// Shared world: a funded EOA, a STOP contract and an account delegated to a
|
||||
// non-existent (codeless) target. The delegation target is intentionally
|
||||
// absent so resolving it executes no code.
|
||||
base7702 := types.GenesisAlloc{
|
||||
existingEOA: {Balance: big.NewInt(1)},
|
||||
stopContract: {Code: []byte{0x00}}, // STOP
|
||||
delegated: {Code: types.AddressToDelegation(emptyTarget)},
|
||||
}
|
||||
// valueCreateTx builds a contract-creation transaction carrying value.
|
||||
valueCreateTx := func(value int64) *types.Transaction {
|
||||
return types.MustSignNewTx(senderKey, signer8037, &types.DynamicFeeTx{
|
||||
ChainID: cfg8037.ChainID, Nonce: 0, To: nil, Value: big.NewInt(value),
|
||||
Gas: 300_000, GasFeeCap: big.NewInt(0), GasTipCap: big.NewInt(0),
|
||||
})
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
tx *types.Transaction
|
||||
wantRegular, wantState uint64
|
||||
}{
|
||||
// case 1: ETH transfer to self.
|
||||
{"self-transfer", callTx(0, senderAddr, 1, 100_000, nil), base, 0},
|
||||
// case 2: no-transfer to an existing EOA.
|
||||
{"zero-value/eoa", callTx(0, existingEOA, 0, 100_000, nil), base + cold, 0},
|
||||
// case 3: no-transfer to a contract.
|
||||
{"zero-value/contract", callTx(0, stopContract, 0, 100_000, nil), base + cold, 0},
|
||||
// case 4: ETH transfer to an existing EOA.
|
||||
{"value/eoa", callTx(0, existingEOA, 1, 100_000, nil), base + cold + valueCst, 0},
|
||||
// case 5: ETH transfer to a contract.
|
||||
{"value/contract", callTx(0, stopContract, 1, 100_000, nil), base + cold + valueCst, 0},
|
||||
// case 6: no-transfer to a 7702-delegated account.
|
||||
{"zero-value/delegated", callTx(0, delegated, 0, 100_000, nil), base + 2*cold, 0},
|
||||
// case 7: ETH transfer to a 7702-delegated account (no new-account charge).
|
||||
{"value/delegated", callTx(0, delegated, 1, 100_000, nil), base + 2*cold + valueCst, 0},
|
||||
// case 8: ETH transfer creating a new account.
|
||||
{"value/new-account", callTx(0, freshEOA, 1, 300_000, nil), base + cold + valueCst, newAccountState},
|
||||
// case 9: contract-creation transaction, value = 0.
|
||||
{"create/zero-value", createTx(0, 300_000, nil), base + params.CreateAccess2780, newAccountState},
|
||||
// case 10: contract-creation transaction, value > 0.
|
||||
{"create/value", valueCreateTx(1), base + params.CreateAccess2780 + params.TransferLogCost2780, newAccountState},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
res, gp, err := applyMsg(t, mkState(senderAlloc(base7702)), tc.tx)
|
||||
if err != nil {
|
||||
t.Fatalf("consensus error: %v", err)
|
||||
}
|
||||
if res.Err != nil {
|
||||
t.Fatalf("execution failed: %v", res.Err)
|
||||
}
|
||||
if gp.cumulativeRegular != tc.wantRegular {
|
||||
t.Errorf("regular gas = %d, want %d", gp.cumulativeRegular, tc.wantRegular)
|
||||
}
|
||||
if gp.cumulativeState != tc.wantState {
|
||||
t.Errorf("state gas = %d, want %d", gp.cumulativeState, tc.wantState)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP2780NewAccountFunded verifies that a value transfer creating a new
|
||||
// account both materializes and funds the recipient.
|
||||
func TestEIP2780NewAccountFunded(t *testing.T) {
|
||||
fresh := common.HexToAddress("0xbeef000000000000000000000000000000000002")
|
||||
sdb := mkState(senderAlloc(nil))
|
||||
if _, _, err := applyMsg(t, sdb, callTx(0, fresh, 1, 300_000, nil)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !sdb.Exist(fresh) || sdb.GetBalance(fresh).Cmp(uint256.NewInt(1)) != 0 {
|
||||
t.Fatalf("recipient not funded: exist=%v balance=%v", sdb.Exist(fresh), sdb.GetBalance(fresh))
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP2780InsufficientGasForCallCharge verifies that a value transfer
|
||||
// creating a new account, whose gas limit only covers the 21,000 intrinsic base
|
||||
// and not the additional new-account state gas charged before the call executes,
|
||||
// halts out of gas. The transaction stays valid (no consensus error) but
|
||||
// execution fails and the recipient is not created.
|
||||
func TestEIP2780InsufficientGasForCallCharge(t *testing.T) {
|
||||
fresh := common.HexToAddress("0xbeef000000000000000000000000000000000003")
|
||||
sdb := mkState(senderAlloc(nil))
|
||||
res, _, err := applyMsg(t, sdb, callTx(0, fresh, 1, 21_000, nil))
|
||||
if err != nil {
|
||||
t.Fatalf("transaction should remain valid: %v", err)
|
||||
}
|
||||
if res.Err != vm.ErrOutOfGas {
|
||||
t.Fatalf("expected out of gas, got %v", res.Err)
|
||||
}
|
||||
if res.UsedGas != 21_000 {
|
||||
t.Fatalf("expected used gas, got %v", res.UsedGas)
|
||||
}
|
||||
if sdb.Exist(fresh) {
|
||||
t.Fatal("recipient should not be created when the call charge cannot be paid")
|
||||
}
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ var (
|
|||
|
||||
// A creation tx's intrinsic gas pre-charges one account creation as state gas.
|
||||
func TestCreateTxIntrinsicChargesAccountUnconditionally(t *testing.T) {
|
||||
cost, err := IntrinsicGas(nil, nil, nil, true, rules8037, params.CostPerStateByte)
|
||||
cost, err := IntrinsicGas(nil, nil, nil, common.Address{}, nil, nil, rules8037, params.CostPerStateByte)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -325,7 +325,7 @@ func clearSlots(addr common.Address, n int) (types.GenesisAlloc, []byte) {
|
|||
// tx_gas_used_before_refund (peak) exceeds the post-refund gas used.
|
||||
func TestGasUsedBeforeRefund(t *testing.T) {
|
||||
c := common.HexToAddress("0xc1ea0")
|
||||
alloc, _ := clearSlots(c, 1)
|
||||
alloc, _ := clearSlots(c, 4)
|
||||
res, _, err := applyMsg(t, mkState(senderAlloc(alloc)), callTx(0, c, 0, 1_000_000, nil))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -351,8 +351,8 @@ func TestRefundCappedAt20Percent(t *testing.T) {
|
|||
// The EIP-7623 calldata floor is applied after the refund.
|
||||
func TestRefundCalldataFloorAfterRefund(t *testing.T) {
|
||||
data := make([]byte, 1000) // all-zero calldata: floor dominates a bare call
|
||||
floor, _ := FloorDataGas(rules8037, data, nil)
|
||||
to := common.HexToAddress("0xeeee")
|
||||
floor, _ := FloorDataGas(rules8037, senderAddr, &to, new(uint256.Int), data, nil)
|
||||
res, _, err := applyMsg(t, mkState(senderAlloc(nil)), callTx(0, to, 0, 1_000_000, data))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -367,7 +367,7 @@ func TestRefundFloorNegatesRefund(t *testing.T) {
|
|||
c := common.HexToAddress("0xc1ea1")
|
||||
alloc, _ := clearSlots(c, 1)
|
||||
data := make([]byte, 1000)
|
||||
floor, _ := FloorDataGas(rules8037, data, nil)
|
||||
floor, _ := FloorDataGas(rules8037, senderAddr, &c, new(uint256.Int), data, nil)
|
||||
res, _, err := applyMsg(t, mkState(senderAlloc(alloc)), callTx(0, c, 0, 1_000_000, data))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -474,7 +474,7 @@ var delegate8037 = common.HexToAddress("0xde1e8a7e")
|
|||
|
||||
// Intrinsic gas pre-charges the worst-case (account + indicator) per auth.
|
||||
func TestAuthIntrinsicWorstCase(t *testing.T) {
|
||||
cost, err := IntrinsicGas(nil, nil, []types.SetCodeAuthorization{{}}, false, rules8037, params.CostPerStateByte)
|
||||
cost, err := IntrinsicGas(nil, nil, []types.SetCodeAuthorization{{}}, common.Address{}, &delegate8037, nil, rules8037, params.CostPerStateByte)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,11 +66,6 @@ var (
|
|||
// have enough funds for transfer(topmost call only).
|
||||
ErrInsufficientFundsForTransfer = errors.New("insufficient funds for transfer")
|
||||
|
||||
// ErrInsufficientBalanceWitness is returned if the transaction sender has enough
|
||||
// funds to cover the transfer, but not enough to pay for witness access/modification
|
||||
// costs for the transaction
|
||||
ErrInsufficientBalanceWitness = errors.New("insufficient funds to cover witness access costs for transaction")
|
||||
|
||||
// ErrInsufficientFunds is returned if the total cost of executing a transaction
|
||||
// is higher than the balance of the user's account.
|
||||
ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value")
|
||||
|
|
|
|||
|
|
@ -88,10 +88,10 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated
|
|||
blockAccessList = bal.NewConstructionBlockAccessList()
|
||||
)
|
||||
defer evm.Release()
|
||||
|
||||
if jumpDestCache != nil {
|
||||
evm.SetJumpDestCache(jumpDestCache)
|
||||
}
|
||||
|
||||
// Run the pre-execution system calls
|
||||
blockAccessList.Merge(PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), config, evm, block.Number(), block.Time()))
|
||||
|
||||
|
|
|
|||
|
|
@ -68,16 +68,19 @@ func (result *ExecutionResult) Revert() []byte {
|
|||
}
|
||||
|
||||
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
|
||||
func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.SetCodeAuthorization, isContractCreation bool, rules params.Rules, costPerStateByte uint64) (vm.GasCosts, error) {
|
||||
func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.SetCodeAuthorization, from common.Address, to *common.Address, value *uint256.Int, rules params.Rules, costPerStateByte uint64) (vm.GasCosts, error) {
|
||||
isContractCreation := to == nil
|
||||
|
||||
// Set the starting gas for the raw transaction
|
||||
var gas vm.GasCosts
|
||||
if isContractCreation && rules.IsHomestead {
|
||||
if rules.IsAmsterdam {
|
||||
gas.RegularGas = params.TxGas + params.CreateGasAmsterdam
|
||||
if rules.IsAmsterdam {
|
||||
gas.RegularGas = intrinsicBaseGasEIP2780(from, to, value)
|
||||
if isContractCreation {
|
||||
// New-account creation is charged as state gas (EIP-8037).
|
||||
gas.StateGas = params.AccountCreationSize * costPerStateByte
|
||||
} else {
|
||||
gas.RegularGas = params.TxGasContractCreation
|
||||
}
|
||||
} else if isContractCreation && rules.IsHomestead {
|
||||
gas.RegularGas = params.TxGasContractCreation
|
||||
} else {
|
||||
gas.RegularGas = params.TxGas
|
||||
}
|
||||
|
|
@ -151,8 +154,41 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
|
|||
return gas, nil
|
||||
}
|
||||
|
||||
// intrinsicBaseGasEIP2780 computes the regular-gas portion of the EIP-2780
|
||||
// intrinsic base cost: the per-resource decomposition of the legacy flat 21,000.
|
||||
func intrinsicBaseGasEIP2780(from common.Address, to *common.Address, value *uint256.Int) uint64 {
|
||||
var (
|
||||
isContractCreation = to == nil
|
||||
isSelfTransfer = to != nil && *to == from
|
||||
hasValue = value != nil && !value.IsZero()
|
||||
)
|
||||
// tx.sender: signature recovery plus the sender account access and write.
|
||||
gas := params.TxBaseCost2780
|
||||
|
||||
// tx.to charge.
|
||||
switch {
|
||||
case isSelfTransfer:
|
||||
// The recipient account is already accessed and written as the sender.
|
||||
case isContractCreation:
|
||||
gas += params.CreateAccess2780
|
||||
default:
|
||||
gas += params.ColdAccountAccess2780
|
||||
}
|
||||
|
||||
// tx.value charge.
|
||||
switch {
|
||||
case !hasValue || isSelfTransfer:
|
||||
// No transfer log and no recipient balance write.
|
||||
case isContractCreation:
|
||||
gas += params.TransferLogCost2780
|
||||
default:
|
||||
gas += params.TransferLogCost2780 + params.TxValueCost2780
|
||||
}
|
||||
return gas
|
||||
}
|
||||
|
||||
// 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) {
|
||||
func FloorDataGas(rules params.Rules, from common.Address, to *common.Address, value *uint256.Int, data []byte, accessList types.AccessList) (uint64, error) {
|
||||
var (
|
||||
tokens uint64
|
||||
tokenCost uint64
|
||||
|
|
@ -198,12 +234,19 @@ func FloorDataGas(rules params.Rules, data []byte, accessList types.AccessList)
|
|||
tokenCost = params.TxCostFloorPerToken
|
||||
}
|
||||
|
||||
// The floor is anchored to the transaction base cost. Under EIP-2780 that
|
||||
// base is the per-resource decomposition (the same one used by the intrinsic
|
||||
// gas), so the floor never undercuts the transaction's own base.
|
||||
floorBase := params.TxGas
|
||||
if rules.IsAmsterdam {
|
||||
floorBase = intrinsicBaseGasEIP2780(from, to, value)
|
||||
}
|
||||
// Check for overflow
|
||||
if (math.MaxUint64-params.TxGas)/tokenCost < tokens {
|
||||
if (math.MaxUint64-floorBase)/tokenCost < tokens {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
// Minimum gas required for a transaction based on its data tokens (EIP-7623).
|
||||
return params.TxGas + tokens*tokenCost, nil
|
||||
return floorBase + tokens*tokenCost, nil
|
||||
}
|
||||
|
||||
// toWordSize returns the ceiled word size required for init code payment calculation.
|
||||
|
|
@ -614,7 +657,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
contractCreation = msg.To == nil
|
||||
floorDataGas uint64
|
||||
)
|
||||
cost, err := IntrinsicGas(msg.Data, msg.AccessList, msg.SetCodeAuthorizations, contractCreation, rules, st.evm.Context.CostPerStateByte)
|
||||
cost, err := IntrinsicGas(msg.Data, msg.AccessList, msg.SetCodeAuthorizations, msg.From, msg.To, msg.Value, rules, st.evm.Context.CostPerStateByte)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -629,7 +672,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.From, msg.To, msg.Value, msg.Data, msg.AccessList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -705,9 +748,16 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
if addr, ok := types.ParseDelegation(st.state.GetCode(*msg.To)); ok {
|
||||
st.state.AddAddressToAccessList(addr)
|
||||
}
|
||||
// Execute the transaction's call.
|
||||
ret, result, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining.ForwardAll(), value)
|
||||
st.gasRemaining.Absorb(result)
|
||||
// EIP-2780: charge the transaction's top-level recipient costs. If the
|
||||
// budget cannot cover the charge, the top frame halts out of gas.
|
||||
if rules.IsAmsterdam && !st.chargeCallRecipientEIP2780(value) {
|
||||
vmerr = vm.ErrOutOfGas
|
||||
st.gasRemaining = st.gasRemaining.ExitHalt()
|
||||
} else {
|
||||
// Execute the transaction's call.
|
||||
ret, result, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining.ForwardAll(), value)
|
||||
st.gasRemaining.Absorb(result)
|
||||
}
|
||||
}
|
||||
|
||||
// Settle down the gas usage and refund the ETH back if any remaining
|
||||
|
|
@ -754,6 +804,47 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// chargeCallRecipientEIP2780 applies the EIP-2780 transaction top-level gas costs for
|
||||
// a message-call transaction, charged before any opcode executes:
|
||||
//
|
||||
// - if the recipient is EIP-161 non-existent and the transaction carries value,
|
||||
// charge for account creation.
|
||||
//
|
||||
// - if the recipient is an EIP-7702 delegated account, resolving the delegation
|
||||
// loads the target's code, charged an additional cold account access in
|
||||
// regular gas.
|
||||
func (st *stateTransition) chargeCallRecipientEIP2780(value *uint256.Int) bool {
|
||||
var (
|
||||
cost vm.GasCosts
|
||||
to = *st.msg.To
|
||||
)
|
||||
// This runs in the topmost frame before any bytecode executes, so unlike the
|
||||
// execution-level checks which must use StateDB.Empty because SELFDESTRUCT can
|
||||
// leave a transient EIP-161-empty account, no empty account can exist here, and
|
||||
// !Exist is equivalent to Empty.
|
||||
if !value.IsZero() && !st.state.Exist(to) {
|
||||
cost.StateGas += params.AccountCreationSize * st.evm.Context.CostPerStateByte
|
||||
}
|
||||
if _, ok := types.ParseDelegation(st.state.GetCode(to)); ok {
|
||||
// EIP-2780: The tx.sender, tx.to, and (where applicable) delegation-target
|
||||
// charges above are always at the cold rate.
|
||||
//
|
||||
// The delegation-target is already warmed before, no double warming here.
|
||||
cost.RegularGas += params.ColdAccountAccess2780
|
||||
}
|
||||
if cost == (vm.GasCosts{}) {
|
||||
return true
|
||||
}
|
||||
prior, ok := st.gasRemaining.Charge(cost)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if st.evm.Config.Tracer.HasGasHook() {
|
||||
st.evm.Config.Tracer.EmitGasChange(prior.AsTracing(), st.gasRemaining.AsTracing(), tracing.GasChangeTxIntrinsicGas)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// settleGas finalizes the per-tx gas accounting after EVM execution:
|
||||
//
|
||||
// - Snapshots the EIP-8037 block-level 2D figures (tx_regular_gas,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
func TestFloorDataGas(t *testing.T) {
|
||||
|
|
@ -73,21 +74,22 @@ func TestFloorDataGas(t *testing.T) {
|
|||
{
|
||||
name: "amsterdam/empty",
|
||||
amsterdam: true,
|
||||
want: params.TxGas,
|
||||
// EIP-2780 anchors the floor to the reduced base cost.
|
||||
want: params.TxBaseCost2780,
|
||||
},
|
||||
{
|
||||
name: "amsterdam/data-only",
|
||||
amsterdam: true,
|
||||
data: bytes.Repeat([]byte{0x00}, 1024),
|
||||
// post-amsterdam: every byte = 4 tokens regardless of value
|
||||
want: params.TxGas + 1024*params.TxTokenPerNonZeroByte*params.TxCostFloorPerToken7976,
|
||||
want: params.TxBaseCost2780 + 1024*params.TxTokenPerNonZeroByte*params.TxCostFloorPerToken7976,
|
||||
},
|
||||
{
|
||||
name: "amsterdam/data-non-zero",
|
||||
amsterdam: true,
|
||||
data: bytes.Repeat([]byte{0xff}, 1024),
|
||||
// same as zero data post-amsterdam
|
||||
want: params.TxGas + 1024*params.TxTokenPerNonZeroByte*params.TxCostFloorPerToken7976,
|
||||
want: params.TxBaseCost2780 + 1024*params.TxTokenPerNonZeroByte*params.TxCostFloorPerToken7976,
|
||||
},
|
||||
{
|
||||
name: "amsterdam/access-list-addresses-only",
|
||||
|
|
@ -97,7 +99,7 @@ func TestFloorDataGas(t *testing.T) {
|
|||
{Address: addr2},
|
||||
},
|
||||
// 2 * 20 bytes * 4 tokens/byte * 16 cost/token
|
||||
want: params.TxGas + 2*common.AddressLength*params.TxTokenPerNonZeroByte*params.TxCostFloorPerToken7976,
|
||||
want: params.TxBaseCost2780 + 2*common.AddressLength*params.TxTokenPerNonZeroByte*params.TxCostFloorPerToken7976,
|
||||
},
|
||||
{
|
||||
name: "amsterdam/access-list-with-storage-keys",
|
||||
|
|
@ -106,7 +108,7 @@ func TestFloorDataGas(t *testing.T) {
|
|||
{Address: addr1, StorageKeys: []common.Hash{key1, key2}},
|
||||
},
|
||||
// 1 addr * 20 * 4 + 2 keys * 32 * 4 = 80 + 256 = 336 tokens * 16
|
||||
want: params.TxGas + (1*common.AddressLength+2*common.HashLength)*params.TxTokenPerNonZeroByte*params.TxCostFloorPerToken7976,
|
||||
want: params.TxBaseCost2780 + (1*common.AddressLength+2*common.HashLength)*params.TxTokenPerNonZeroByte*params.TxCostFloorPerToken7976,
|
||||
},
|
||||
{
|
||||
name: "amsterdam/mixed",
|
||||
|
|
@ -117,13 +119,13 @@ func TestFloorDataGas(t *testing.T) {
|
|||
{Address: addr2, StorageKeys: []common.Hash{key1, key2}},
|
||||
},
|
||||
// data: 100*4 = 400; addrs: 2*20*4 = 160; keys: 3*32*4 = 384; total = 944 * 16
|
||||
want: params.TxGas + (100*params.TxTokenPerNonZeroByte+2*common.AddressLength*params.TxTokenPerNonZeroByte+3*common.HashLength*params.TxTokenPerNonZeroByte)*params.TxCostFloorPerToken7976,
|
||||
want: params.TxBaseCost2780 + (100*params.TxTokenPerNonZeroByte+2*common.AddressLength*params.TxTokenPerNonZeroByte+3*common.HashLength*params.TxTokenPerNonZeroByte)*params.TxCostFloorPerToken7976,
|
||||
},
|
||||
}
|
||||
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, addr1, &addr1, new(uint256.Int), tt.data, tt.accessList)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
|
@ -155,6 +157,7 @@ func TestIntrinsicGas(t *testing.T) {
|
|||
isEIP2028 bool
|
||||
isEIP3860 bool
|
||||
isAmsterdam bool
|
||||
value *uint256.Int
|
||||
want vm.GasCosts
|
||||
}{
|
||||
{
|
||||
|
|
@ -237,8 +240,9 @@ func TestIntrinsicGas(t *testing.T) {
|
|||
},
|
||||
isEIP2028: true,
|
||||
isAmsterdam: true,
|
||||
// base access-list charge + EIP-7981 extra
|
||||
want: vm.GasCosts{RegularGas: params.TxGas +
|
||||
// EIP-2780: zero-value call base is TxBaseCost + ColdAccountAccess
|
||||
// (15,000). Plus base access-list charge + EIP-7981 extra.
|
||||
want: vm.GasCosts{RegularGas: params.TxBaseCost2780 + params.ColdAccountAccess2780 +
|
||||
2*params.TxAccessListAddressGas + 3*params.TxAccessListStorageKeyGas +
|
||||
2*amsterdamAddressCost + 3*amsterdamStorageKeyCost},
|
||||
},
|
||||
|
|
@ -259,10 +263,10 @@ func TestIntrinsicGas(t *testing.T) {
|
|||
isHomestead: true,
|
||||
isEIP2028: true,
|
||||
isAmsterdam: true,
|
||||
// EIP-8037: creation regular gas is TxGas + CreateGasAmsterdam (not TxGasContractCreation),
|
||||
// and account-creation cost is moved to state gas.
|
||||
// EIP-2780: creation regular gas is TxBaseCost + CreateAccess (23,000),
|
||||
// and account-creation cost is charged as state gas.
|
||||
want: vm.GasCosts{
|
||||
RegularGas: params.TxGas + params.CreateGasAmsterdam,
|
||||
RegularGas: params.TxBaseCost2780 + params.CreateAccess2780,
|
||||
StateGas: params.AccountCreationSize * params.CostPerStateByte,
|
||||
},
|
||||
},
|
||||
|
|
@ -275,7 +279,7 @@ func TestIntrinsicGas(t *testing.T) {
|
|||
isEIP3860: true, // Shanghai gates init-code word gas
|
||||
isAmsterdam: true,
|
||||
want: vm.GasCosts{
|
||||
RegularGas: params.TxGas + params.CreateGasAmsterdam +
|
||||
RegularGas: params.TxBaseCost2780 + params.CreateAccess2780 +
|
||||
64*params.TxDataZeroGas + 2*params.InitCodeWordGas,
|
||||
StateGas: params.AccountCreationSize * params.CostPerStateByte,
|
||||
},
|
||||
|
|
@ -292,7 +296,7 @@ func TestIntrinsicGas(t *testing.T) {
|
|||
isEIP3860: true,
|
||||
isAmsterdam: true,
|
||||
want: vm.GasCosts{
|
||||
RegularGas: params.TxGas + params.CreateGasAmsterdam +
|
||||
RegularGas: params.TxBaseCost2780 + params.CreateAccess2780 +
|
||||
32*params.TxDataNonZeroGasEIP2028 + 1*params.InitCodeWordGas +
|
||||
1*params.TxAccessListAddressGas + 1*params.TxAccessListStorageKeyGas +
|
||||
1*amsterdamAddressCost + 1*amsterdamStorageKeyCost,
|
||||
|
|
@ -314,7 +318,7 @@ func TestIntrinsicGas(t *testing.T) {
|
|||
// regular: TxAuthTupleRegularGas (7500) per auth
|
||||
// state: (AuthorizationCreationSize + AccountCreationSize) * CostPerStateByte per auth
|
||||
want: vm.GasCosts{
|
||||
RegularGas: params.TxGas +
|
||||
RegularGas: params.TxBaseCost2780 + params.ColdAccountAccess2780 +
|
||||
100*params.TxDataNonZeroGasEIP2028 +
|
||||
1*params.TxAccessListAddressGas + 1*params.TxAccessListStorageKeyGas +
|
||||
1*amsterdamAddressCost + 1*amsterdamStorageKeyCost +
|
||||
|
|
@ -322,6 +326,28 @@ func TestIntrinsicGas(t *testing.T) {
|
|||
StateGas: 1 * (params.AuthorizationCreationSize + params.AccountCreationSize) * params.CostPerStateByte,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "amsterdam/value-transfer-call",
|
||||
isEIP2028: true,
|
||||
isAmsterdam: true,
|
||||
value: uint256.NewInt(1),
|
||||
// EIP-2780: TxBaseCost + ColdAccountAccess + TransferLogCost + TxValueCost = 21,000.
|
||||
want: vm.GasCosts{RegularGas: params.TxBaseCost2780 + params.ColdAccountAccess2780 +
|
||||
params.TransferLogCost2780 + params.TxValueCost2780},
|
||||
},
|
||||
{
|
||||
name: "amsterdam/value-bearing-contract-creation",
|
||||
creation: true,
|
||||
isHomestead: true,
|
||||
isEIP2028: true,
|
||||
isAmsterdam: true,
|
||||
value: uint256.NewInt(1),
|
||||
// EIP-2780: TxBaseCost + CreateAccess + TransferLogCost = 24,756, plus account-creation state gas.
|
||||
want: vm.GasCosts{
|
||||
RegularGas: params.TxBaseCost2780 + params.CreateAccess2780 + params.TransferLogCost2780,
|
||||
StateGas: params.AccountCreationSize * params.CostPerStateByte,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
@ -331,8 +357,12 @@ func TestIntrinsicGas(t *testing.T) {
|
|||
IsShanghai: tt.isEIP3860,
|
||||
IsAmsterdam: tt.isAmsterdam,
|
||||
}
|
||||
var to *common.Address
|
||||
if !tt.creation {
|
||||
to = &addr1
|
||||
}
|
||||
got, err := IntrinsicGas(tt.data, tt.accessList, tt.authList,
|
||||
tt.creation, rules, params.CostPerStateByte)
|
||||
common.Address{}, to, tt.value, rules, params.CostPerStateByte)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -116,16 +117,22 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
|
|||
return core.ErrTipAboveFeeCap
|
||||
}
|
||||
// Make sure the transaction is signed properly
|
||||
if _, err := types.Sender(signer, tx); err != nil {
|
||||
from, err := types.Sender(signer, tx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrInvalidSender, err)
|
||||
}
|
||||
// Limit nonce to 2^64-1 per EIP-2681
|
||||
if tx.Nonce()+1 < tx.Nonce() {
|
||||
return core.ErrNonceMax
|
||||
}
|
||||
// Sanity check for extremely large numbers (supported by RLP or RPC)
|
||||
value, overflow := uint256.FromBig(tx.Value())
|
||||
if overflow {
|
||||
return core.ErrInsufficientFunds
|
||||
}
|
||||
// Ensure the transaction has more gas than the bare minimum needed to cover
|
||||
// the transaction metadata
|
||||
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules, params.CostPerStateByte)
|
||||
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), from, tx.To(), value, rules, params.CostPerStateByte)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -134,7 +141,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, from, tx.To(), value, tx.Data(), tx.AccessList())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,13 @@ const (
|
|||
TxAuthTupleGas uint64 = 12500 // Per auth tuple code specified in EIP-7702
|
||||
TxAuthTupleRegularGas uint64 = 7500 // Per auth tuple regular gas specified in EIP-8037
|
||||
|
||||
// EIP-2780: resource-based intrinsic transaction gas.
|
||||
TxBaseCost2780 uint64 = 12000
|
||||
ColdAccountAccess2780 uint64 = 3000
|
||||
CreateAccess2780 uint64 = 11000
|
||||
TxValueCost2780 uint64 = 4244
|
||||
TransferLogCost2780 uint64 = 1756
|
||||
|
||||
// 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)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// TransactionTest checks RLP decoding and sender derivation of transactions.
|
||||
|
|
@ -81,7 +82,11 @@ func (tt *TransactionTest) Run() error {
|
|||
return
|
||||
}
|
||||
// Intrinsic cost
|
||||
cost, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules, params.CostPerStateByte)
|
||||
value, overflow := uint256.FromBig(tx.Value())
|
||||
if overflow {
|
||||
return sender, hash, 0, errors.New("value exceeds 256 bits")
|
||||
}
|
||||
cost, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), sender, tx.To(), value, rules, params.CostPerStateByte)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -92,7 +97,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, sender, tx.To(), value, tx.Data(), tx.AccessList())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue