Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
71e90d7
chore: update Go version to 1.21
eomti-wm Dec 23, 2025
9843306
feat: implement EIP-7702 set code transaction type
eomti-wm Dec 18, 2025
eedb025
fix: complete EIP-7702 authorization marshaling and eth_call support
eomti-wm Dec 18, 2025
78e83ba
refactor: improve EIP-7702 API naming
eomti-wm Dec 18, 2025
3240e33
fix: rename SetCodeAuthorization 'v' to 'yParity'
eomti-wm Dec 18, 2025
b32978f
refactor: rename AuthList to SetCodeAuthorizations
eomti-wm Dec 18, 2025
c2eaae0
refactor: change SetCodeTx.ChainID to uint256
eomti-wm Dec 18, 2025
685ad48
fix: correct chainId check for anzeonSigner
eomti-wm Dec 18, 2025
7437c4d
fix: initialize ChainID in SetCodeTx copy method
eomti-wm Dec 18, 2025
c89e0f9
refactor: remove EXTCODE* special handling for EIP-7702
eomti-wm Dec 18, 2025
b2334d4
feat: add EIP-7702 SetCode transaction pool support
eomti-wm Dec 23, 2025
a95916f
test: add setCodeTx reorg test
eomti-wm Dec 23, 2025
26a945a
refactor: move setcode tx validation into legacyPool
eomti-wm Dec 23, 2025
f8af462
fix: fix error logs flood caused by removeAuthorities
eomti-wm Dec 24, 2025
19aa468
refactor: reduce allocs in transaction signing
eomti-wm Dec 24, 2025
930a1c0
fix: reject gapped tx from delegated account
eomti-wm Dec 24, 2025
eebfcb9
fix: exclude 7702 authorities from eth_createAccessList result
eomti-wm Dec 24, 2025
a28c9c2
fix: data race in checkDelegationLimit
eomti-wm Dec 24, 2025
b2e0ae5
feat: add EIP-7702 protection to blobpool
eomti-wm Dec 29, 2025
bf624de
fix: slot limit check and update comments
eomti-wm Dec 30, 2025
b613232
fix: allow tx and authority regardless of admission order
eomti-wm Dec 30, 2025
4c03afd
fix: fix data race of txlookup access in test
eomti-wm Dec 30, 2025
568b681
feat: allow passing AuthorizationList to eth_call and eth_estimateGas
eomti-wm Dec 30, 2025
ed80b8a
fix: fix data race of pricedList access
eomti-wm Dec 30, 2025
f173a74
fix: resolve incorrect prestate for EIP-7702 authority accounts
eomti-wm Jan 2, 2026
6a74abc
feat: prestate tracer lookup EIP-7702 delegation account
eomti-wm Jan 2, 2026
01c9f38
refactor: expose sigHash as SigHash for SetCodeAuthorization
eomti-wm Jan 2, 2026
1b00605
fix: resolve test failures in tracer and blobpool
eomti-wm Jan 5, 2026
eb156e0
Revert "chore: update Go version to 1.21"
eomti-wm Jan 8, 2026
738b0a9
fix: support AuthorizationList in simulated backend gas estimation
eomti-wm Jan 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion accounts/external/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
switch tx.Type() {
case types.LegacyTxType, types.AccessListTxType:
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
case types.DynamicFeeTxType:
case types.DynamicFeeTxType, types.SetCodeTxType:
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
default:
Expand Down
9 changes: 6 additions & 3 deletions cmd/evm/internal/t8ntool/tracewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"math/big"

"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/eth/tracers"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -56,9 +57,11 @@ func (t *traceWriter) CaptureTxEnd(restGas uint64) {
}
}

func (t *traceWriter) CaptureTxStart(gasLimit uint64) { t.inner.CaptureTxStart(gasLimit) }
func (t *traceWriter) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
t.inner.CaptureStart(env, from, to, create, input, gas, value)
func (t *traceWriter) CaptureTxStart(env *vm.EVM, gasLimit uint64, authList []types.SetCodeAuthorization) {
t.inner.CaptureTxStart(env, gasLimit, authList)
}
func (t *traceWriter) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
t.inner.CaptureStart(from, to, create, input, gas, value)
}

func (t *traceWriter) CaptureEnd(output []byte, gasUsed uint64, err error) {
Expand Down
2 changes: 1 addition & 1 deletion cmd/evm/internal/t8ntool/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func Transaction(ctx *cli.Context) error {
r.Address = sender
}
// Check intrinsic gas
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil,
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil,
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int), 0)); err != nil {
r.Error = err
results = append(results, r)
Expand Down
8 changes: 8 additions & 0 deletions cmd/evm/t8n_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,14 @@ func TestT8n(t *testing.T) {
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
{ // Anzeon test, EIP-7702 transaction
base: "./testdata/33",
input: t8nInput{
"alloc.json", "txs.json", "env.json", "Anzeon", "",
},
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
} {
args := []string{"t8n"}
args = append(args, tc.output.get()...)
Expand Down
1 change: 1 addition & 0 deletions cmd/evm/testdata/33/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This test sets some EIP-7702 delegations and calls them.
30 changes: 30 additions & 0 deletions cmd/evm/testdata/33/alloc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"0x8a0a19589531694250d570040a0c4b74576919b8": {
"nonce": "0x00",
"balance": "0x0de0b6b3a7640000",
"code": "0x600060006000600060007310000000000000000000000000000000000000015af1600155600060006000600060007310000000000000000000000000000000000000025af16002553d600060003e600051600355",
"storage": {
"0x01": "0x0100",
"0x02": "0x0100",
"0x03": "0x0100"
}
},
"0x000000000000000000000000000000000000aaaa": {
"nonce": "0x00",
"balance": "0x4563918244f40000",
"code": "0x58808080600173703c4b2bd70c169f5717101caee543299fc946c75af100",
"storage": {}
},
"0x000000000000000000000000000000000000bbbb": {
"nonce": "0x00",
"balance": "0x29a2241af62c0000",
"code": "0x6042805500",
"storage": {}
},
"0x71562b71999873DB5b286dF957af199Ec94617F7": {
"nonce": "0x00",
"balance": "0x6124fee993bc0000",
"code": "0x",
"storage": {}
}
}
14 changes: 14 additions & 0 deletions cmd/evm/testdata/33/env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentGasLimit": "71794957647893862",
"currentNumber": "1",
"currentTimestamp": "1000",
"currentRandom": "0",
"currentDifficulty": "0",
"blockHashes": {},
"ommers": [],
"currentBaseFee": "7",
"parentUncleHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"withdrawals": [],
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
95 changes: 95 additions & 0 deletions cmd/evm/testdata/33/exp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"alloc": {
"0x000000000000000000000000000000000000aaaa": {
"code": "0x58808080600173703c4b2bd70c169f5717101caee543299fc946c75af100",
"balance": "0x4563918244f40000"
},
"0x000000000000000000000000000000000000bbbb": {
"code": "0x6042805500",
"balance": "0x29a2241af62c0000"
},
"0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": {
"balance": "0xc0189"
},
"0x703c4b2bd70c169f5717101caee543299fc946c7": {
"code": "0xef0100000000000000000000000000000000000000bbbb",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000042": "0x0000000000000000000000000000000000000000000000000000000000000042"
},
"balance": "0x1",
"nonce": "0x1"
},
"0x71562b71999873db5b286df957af199ec94617f7": {
"code": "0xef0100000000000000000000000000000000000000aaaa",
"balance": "0x6124fee993affe76",
"nonce": "0x2"
},
"0x8a0a19589531694250d570040a0c4b74576919b8": {
"code": "0x600060006000600060007310000000000000000000000000000000000000015af1600155600060006000600060007310000000000000000000000000000000000000025af16002553d600060003e600051600355",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000100",
"0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000100",
"0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000100"
},
"balance": "0xde0b6b3a7640000"
}
},
"result": {
"stateRoot": "0x1e651689182e93c4ac6ae325b3892016e4dfe61b83e690ea84299a34f0540c12",
"txRoot": "0x5d13a0b074e80388dc754da92b22922313a63417b3e25a10f324935e09697a53",
"receiptsRoot": "0xaeb286ce5a9f77001f07b7f58f3e5e5963c734b3dc8a77828911647cf7f0e8f6",
"logsHash": "0x746a99701f8a36a95ad98bc6cc600161a78944b40c0ea7c39964aefba864de97",
"logsBloom": "0x00000000000000100000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000008000000002000000000000000000000000020000000000020000000000000000001000000000000000000000000000010000000000000000000000000000000000000000000000400000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000002000000000000800000000000000000000000000000000100000000000000000000000000000000000000000000000020000000000000000000000000",
"receipts": [
{
"type": "0x4",
"root": "0x",
"status": "0x1",
"cumulativeGasUsed": "0x15581",
"logsBloom": "0x00000000000000100000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000008000000002000000000000000000000000020000000000020000000000000000001000000000000000000000000000010000000000000000000000000000000000000000000000400000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000002000000000000800000000000000000000000000000000100000000000000000000000000000000000000000000000020000000000000000000000000",
"logs": [
{
"address": "0x0000000000000000000000000000000000001000",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x00000000000000000000000071562b71999873db5b286df957af199ec94617f7",
"0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7"
],
"data": "0x0000000000000000000000000000000000000000000000000000000000000001",
"blockNumber": "0x1",
"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
"transactionIndex": "0x0",
"blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
"logIndex": "0x0",
"removed": false
},
{
"address": "0x0000000000000000000000000000000000001000",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x00000000000000000000000071562b71999873db5b286df957af199ec94617f7",
"0x0000000000000000000000002adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000c0189",
"blockNumber": "0x1",
"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
"transactionIndex": "0x0",
"blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
"logIndex": "0x1",
"removed": false
}
],
"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x15581",
"effectiveGasPrice": "0x9",
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"transactionIndex": "0x0"
}
],
"currentDifficulty": "0x0",
"gasUsed": "0x15581",
"currentBaseFee": "0x7",
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
}
37 changes: 37 additions & 0 deletions cmd/evm/testdata/33/txs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"type": "0x4",
"chainId": "0x1",
"nonce": "0x0",
"to": "0x71562b71999873db5b286df957af199ec94617f7",
"gas": "0x7a120",
"gasPrice": null,
"maxPriorityFeePerGas": "0x2",
"maxFeePerGas": "0x12a05f200",
"value": "0x0",
"input": "0x",
"accessList": [],
"authorizationList": [
{
"chainId": "0x1",
"address": "0x000000000000000000000000000000000000aaaa",
"nonce": "0x1",
"yParity": "0x1",
"r": "0xf7e3e597fc097e71ed6c26b14b25e5395bc8510d58b9136af439e12715f2d721",
"s": "0x6cf7c3d7939bfdb784373effc0ebb0bd7549691a513f395e3cdabf8602724987"
},
{
"chainId": "0x0",
"address": "0x000000000000000000000000000000000000bbbb",
"nonce": "0x0",
"yParity": "0x1",
"r": "0x5011890f198f0356a887b0779bde5afa1ed04e6acb1e3f37f8f18c7b6f521b98",
"s": "0x56c3fa3456b103f3ef4a0acb4b647b9cab9ec4bc68fbcdf1e10b49fb2bcbcf61"
}
],
"secretKey": "0xb71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291",
"v": "0x0",
"r": "0x0",
"s": "0x0"
}
]
2 changes: 1 addition & 1 deletion core/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
return func(i int, gen *BlockGen) {
toaddr := common.Address{}
data := make([]byte, nbytes)
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
gas, _ := IntrinsicGas(data, nil, nil, false, false, false, false)
signer := gen.Signer()
gasPrice := big.NewInt(0)
if gen.header.BaseFee != nil {
Expand Down
94 changes: 94 additions & 0 deletions core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package core

import (
"bytes"
"errors"
"fmt"
"math/big"
Expand All @@ -27,6 +28,7 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon"
Expand Down Expand Up @@ -4325,3 +4327,95 @@ func TestEIP3651(t *testing.T) {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
}
}

// TestEIP7702 deploys two delegation designations and calls them. It writes one
// value to storage which is verified after.
func TestEIP7702(t *testing.T) {
var (
config = *params.TestWBFTChainConfig
signer = types.LatestSigner(&config)
engine = ethash.NewFaker()
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb")
funds = new(big.Int).Mul(big.NewInt(1000), big.NewInt(params.Ether))
)
gspec := &Genesis{
Config: &config,
Alloc: types.GenesisAlloc{
addr1: {Balance: funds},
addr2: {Balance: funds},
aa: { // The address 0xAAAA calls into addr2
Code: hexutil.MustDecode("0x6000600060006000600173703c4b2bd70c169f5717101caee543299fc946c75af1"), // program.New().Call(nil, addr2, 1, 0, 0, 0, 0).Bytes()
Nonce: 0,
Balance: big.NewInt(0),
},
bb: { // The address 0xBBBB sstores 42 into slot 42.
Code: hexutil.MustDecode("0x6042604255"), // program.New().Sstore(0x42, 0x42).Bytes()
Nonce: 0,
Balance: big.NewInt(0),
},
},
}

// Sign authorization tuples.
// The way the auths are combined, it becomes
// 1. tx -> addr1 which is delegated to 0xaaaa
// 2. addr1:0xaaaa calls into addr2:0xbbbb
// 3. addr2:0xbbbb writes to storage
auth1, _ := types.SignSetCode(key1, types.SetCodeAuthorization{
ChainID: *uint256.MustFromBig(gspec.Config.ChainID),
Address: aa,
Nonce: 1,
})
auth2, _ := types.SignSetCode(key2, types.SetCodeAuthorization{
Address: bb,
Nonce: 0,
})

_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
b.SetCoinbase(aa)
txdata := &types.SetCodeTx{
ChainID: uint256.MustFromBig(gspec.Config.ChainID),
Nonce: 0,
To: addr1,
Gas: 500000,
GasFeeCap: uint256.MustFromBig(newGwei(5000)),
GasTipCap: uint256.NewInt(2),
AuthList: []types.SetCodeAuthorization{auth1, auth2},
}
tx := types.MustSignNewTx(key1, signer, txdata)
b.AddTx(tx)
})

chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
defer chain.Stop()
if n, err := chain.InsertChain(blocks); err != nil {
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
}

// Verify delegation designations were deployed.
state, _ := chain.State()
code, want := state.GetCode(addr1), types.AddressToDelegation(auth1.Address)
if !bytes.Equal(code, want) {
t.Fatalf("addr1 code incorrect: got %s, want %s", common.Bytes2Hex(code), common.Bytes2Hex(want))
}
code, want = state.GetCode(addr2), types.AddressToDelegation(auth2.Address)
if !bytes.Equal(code, want) {
t.Fatalf("addr2 code incorrect: got %s, want %s", common.Bytes2Hex(code), common.Bytes2Hex(want))
}
// Verify delegation executed the correct code.
var (
fortyTwo = common.BytesToHash([]byte{0x42})
actual = state.GetState(addr2, fortyTwo)
)
if actual.Cmp(fortyTwo) != 0 {
t.Fatalf("addr2 storage wrong: expected %d, got %d", fortyTwo, actual)
}
}
18 changes: 18 additions & 0 deletions core/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ var (
// ErrSenderNoEOA is returned if the sender of a transaction is a contract.
ErrSenderNoEOA = errors.New("sender not an eoa")

// -- EIP-4844 errors --

// ErrBlobFeeCapTooLow is returned if the transaction fee cap is less than the
// blob gas fee of the block.
ErrBlobFeeCapTooLow = errors.New("max fee per blob gas less than block blob gas fee")
Expand All @@ -112,6 +114,22 @@ var (

// ErrBlobTxCreate is returned if a blob transaction has no explicit to field.
ErrBlobTxCreate = errors.New("blob transaction of type create")

// -- EIP-7702 errors --

// Message validation errors:
ErrEmptyAuthList = errors.New("EIP-7702 transaction with empty auth list")
ErrSetCodeTxCreate = errors.New("EIP-7702 transaction cannot be used to create contract")
)

// EIP-7702 state transition errors.
// Note these are just informational, and do not cause tx execution abort.
var (
ErrAuthorizationWrongChainID = errors.New("EIP-7702 authorization chain ID mismatch")
ErrAuthorizationNonceOverflow = errors.New("EIP-7702 authorization nonce > 64 bit")
ErrAuthorizationInvalidSignature = errors.New("EIP-7702 authorization has invalid signature")
ErrAuthorizationDestinationHasCode = errors.New("EIP-7702 authorization destination is a contract")
ErrAuthorizationNonceMismatch = errors.New("EIP-7702 authorization nonce does not match current account nonce")
)

type ErrBlacklistedAccount struct {
Expand Down
Loading