Skip to content

Commit f5e86d7

Browse files
committed
feat: add EIP-7702
1 parent ea43834 commit f5e86d7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1115
-194
lines changed

accounts/abi/bind/backends/simulated.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
639639
// about the transaction and calling mechanisms.
640640
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})
641641
gasPool := new(core.GasPool).AddGas(math.MaxUint64)
642-
signer := types.MakeSigner(b.blockchain.Config(), head.Number)
642+
signer := types.MakeSigner(b.blockchain.Config(), head.Number, head.Time)
643643
l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, head.BaseFee, b.blockchain.Config(), signer, stateDB, head.Number)
644644
if err != nil {
645645
return nil, err
@@ -660,7 +660,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
660660
panic("could not fetch parent")
661661
}
662662
// Check transaction validity
663-
signer := types.MakeSigner(b.blockchain.Config(), block.Number())
663+
signer := types.MakeSigner(b.blockchain.Config(), block.Number(), block.Time())
664664
sender, err := types.Sender(signer, tx)
665665
if err != nil {
666666
panic(fmt.Errorf("invalid transaction: %v", err))
@@ -809,19 +809,20 @@ type callMsg struct {
809809
ethereum.CallMsg
810810
}
811811

812-
func (m callMsg) From() common.Address { return m.CallMsg.From }
813-
func (m callMsg) Nonce() uint64 { return 0 }
814-
func (m callMsg) IsFake() bool { return true }
815-
func (m callMsg) To() *common.Address { return m.CallMsg.To }
816-
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
817-
func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap }
818-
func (m callMsg) GasTipCap() *big.Int { return m.CallMsg.GasTipCap }
819-
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
820-
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
821-
func (m callMsg) Data() []byte { return m.CallMsg.Data }
822-
func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList }
823-
func (m callMsg) IsL1MessageTx() bool { return false }
824-
func (m callMsg) TxSize() common.StorageSize { return 0 }
812+
func (m callMsg) From() common.Address { return m.CallMsg.From }
813+
func (m callMsg) Nonce() uint64 { return 0 }
814+
func (m callMsg) IsFake() bool { return true }
815+
func (m callMsg) To() *common.Address { return m.CallMsg.To }
816+
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
817+
func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap }
818+
func (m callMsg) GasTipCap() *big.Int { return m.CallMsg.GasTipCap }
819+
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
820+
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
821+
func (m callMsg) Data() []byte { return m.CallMsg.Data }
822+
func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList }
823+
func (m callMsg) IsL1MessageTx() bool { return false }
824+
func (m callMsg) TxSize() common.StorageSize { return 0 }
825+
func (m callMsg) SetCodeAuthorizations() []types.SetCodeAuthorization { return nil }
825826

826827
// filterBackend implements filters.Backend to support filtering for logs without
827828
// taking bloom-bits acceleration structures into account.

accounts/external/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
218218
switch tx.Type() {
219219
case types.LegacyTxType, types.AccessListTxType:
220220
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
221-
case types.DynamicFeeTxType:
221+
case types.DynamicFeeTxType, types.SetCodeTxType:
222222
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
223223
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
224224
default:

cmd/evm/internal/t8ntool/execution.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
117117
}
118118
var (
119119
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre)
120-
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number))
120+
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
121121
gaspool = new(core.GasPool)
122122
blockHash = common.Hash{0x13, 0x37}
123123
rejectedTxs []*rejectedTx

cmd/evm/internal/t8ntool/transaction.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func Transaction(ctx *cli.Context) error {
113113
return NewError(ErrorIO, errors.New("only rlp supported"))
114114
}
115115
}
116-
signer := types.MakeSigner(chainConfig, new(big.Int))
116+
signer := types.MakeSigner(chainConfig, new(big.Int), 0)
117117
// We now have the transactions in 'body', which is supposed to be an
118118
// rlp list of transactions
119119
it, err := rlp.NewListIterator([]byte(body))
@@ -140,7 +140,7 @@ func Transaction(ctx *cli.Context) error {
140140
r.Address = sender
141141
}
142142
// Check intrinsic gas
143-
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil,
143+
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil,
144144
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int))); err != nil {
145145
r.Error = err
146146
results = append(results, r)

cmd/evm/internal/t8ntool/transition.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ func Transition(ctx *cli.Context) error {
241241
}
242242
}
243243
// We may have to sign the transactions.
244-
signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)))
244+
signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp)
245245

246246
if txs, err = signUnsignedTransactions(txsWithKeys, signer); err != nil {
247247
return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err))

common/hexutil/json.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ import (
2323
"math/big"
2424
"reflect"
2525
"strconv"
26+
27+
"github.com/holiman/uint256"
2628
)
2729

2830
var (
2931
bytesT = reflect.TypeOf(Bytes(nil))
3032
bigT = reflect.TypeOf((*Big)(nil))
3133
uintT = reflect.TypeOf(Uint(0))
3234
uint64T = reflect.TypeOf(Uint64(0))
35+
u256T = reflect.TypeOf((*uint256.Int)(nil))
3336
)
3437

3538
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
@@ -225,6 +228,48 @@ func (b *Big) UnmarshalGraphQL(input interface{}) error {
225228
return err
226229
}
227230

231+
// U256 marshals/unmarshals as a JSON string with 0x prefix.
232+
// The zero value marshals as "0x0".
233+
type U256 uint256.Int
234+
235+
// MarshalText implements encoding.TextMarshaler
236+
func (b U256) MarshalText() ([]byte, error) {
237+
u256 := (*uint256.Int)(&b)
238+
return []byte(u256.Hex()), nil
239+
}
240+
241+
// UnmarshalJSON implements json.Unmarshaler.
242+
func (b *U256) UnmarshalJSON(input []byte) error {
243+
// The uint256.Int.UnmarshalJSON method accepts "dec", "0xhex"; we must be
244+
// more strict, hence we check string and invoke SetFromHex directly.
245+
if !isString(input) {
246+
return errNonString(u256T)
247+
}
248+
// The hex decoder needs to accept empty string ("") as '0', which uint256.Int
249+
// would reject.
250+
if len(input) == 2 {
251+
(*uint256.Int)(b).Clear()
252+
return nil
253+
}
254+
err := (*uint256.Int)(b).SetFromHex(string(input[1 : len(input)-1]))
255+
if err != nil {
256+
return &json.UnmarshalTypeError{Value: err.Error(), Type: u256T}
257+
}
258+
return nil
259+
}
260+
261+
// UnmarshalText implements encoding.TextUnmarshaler
262+
func (b *U256) UnmarshalText(input []byte) error {
263+
// The uint256.Int.UnmarshalText method accepts "dec", "0xhex"; we must be
264+
// more strict, hence we check string and invoke SetFromHex directly.
265+
return (*uint256.Int)(b).SetFromHex(string(input))
266+
}
267+
268+
// String returns the hex encoding of b.
269+
func (b *U256) String() string {
270+
return (*uint256.Int)(b).Hex()
271+
}
272+
228273
// Uint64 marshals/unmarshals as a JSON string with 0x prefix.
229274
// The zero value marshals as "0x0".
230275
type Uint64 uint64

core/bench_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
8585
return func(i int, gen *BlockGen) {
8686
toaddr := common.Address{}
8787
data := make([]byte, nbytes)
88-
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
89-
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)))
88+
gas, _ := IntrinsicGas(data, nil, nil, false, false, false, false)
89+
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), 0)
9090
gasPrice := big.NewInt(0)
9191
if gen.header.BaseFee != nil {
9292
gasPrice = gen.header.BaseFee
@@ -130,7 +130,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
130130
if gen.header.BaseFee != nil {
131131
gasPrice = gen.header.BaseFee
132132
}
133-
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)))
133+
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), 0)
134134
for {
135135
gas -= params.TxGas
136136
if gas < params.TxGas {

core/blockchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1507,7 +1507,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
15071507
}
15081508

15091509
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
1510-
senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain)
1510+
senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain)
15111511

15121512
var (
15131513
stats = insertStats{startTime: mclock.Now()}

core/chain_makers.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ func (b *BlockGen) Number() *big.Int {
150150
return new(big.Int).Set(b.header.Number)
151151
}
152152

153+
// Time returns the timestamp of the block being generated.
154+
func (b *BlockGen) Time() uint64 {
155+
return b.header.Time
156+
}
157+
153158
// BaseFee returns the EIP-1559 base fee of the block being generated.
154159
func (b *BlockGen) BaseFee() *big.Int {
155160
if b.header.BaseFee != nil {

core/error.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,20 @@ var (
103103

104104
// ErrSenderNoEOA is returned if the sender of a transaction is a contract.
105105
ErrSenderNoEOA = errors.New("sender not an eoa")
106+
107+
// -- EIP-7702 errors --
108+
109+
// Message validation errors:
110+
ErrEmptyAuthList = errors.New("EIP-7702 transaction with empty auth list")
111+
ErrSetCodeTxCreate = errors.New("EIP-7702 transaction cannot be used to create contract")
112+
)
113+
114+
// EIP-7702 state transition errors.
115+
// Note these are just informational, and do not cause tx execution abort.
116+
var (
117+
ErrAuthorizationWrongChainID = errors.New("EIP-7702 authorization chain ID mismatch")
118+
ErrAuthorizationNonceOverflow = errors.New("EIP-7702 authorization nonce > 64 bit")
119+
ErrAuthorizationInvalidSignature = errors.New("EIP-7702 authorization has invalid signature")
120+
ErrAuthorizationDestinationHasCode = errors.New("EIP-7702 authorization destination is a contract")
121+
ErrAuthorizationNonceMismatch = errors.New("EIP-7702 authorization nonce does not match current account nonce")
106122
)

core/rawdb/accessors_chain.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,8 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *para
586586
log.Error("Missing body but have receipt", "hash", hash, "number", number)
587587
return nil
588588
}
589-
if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil {
589+
header := ReadHeader(db, hash, number)
590+
if err := receipts.DeriveFields(config, hash, number, header.Time, body.Transactions); err != nil {
590591
log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
591592
return nil
592593
}

core/state_prefetcher.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
5555
gaspool = new(GasPool).AddGas(block.GasLimit())
5656
blockContext = NewEVMBlockContext(header, p.bc, p.config, nil)
5757
evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
58-
signer = types.MakeSigner(p.config, header.Number)
58+
signer = types.MakeSigner(p.config, header.Number, header.Time)
5959
)
6060
// Iterate over and process the individual transactions
6161
byzantium := p.config.IsByzantium(block.Number())

core/state_processor.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
9696
processorBlockTransactionGauge.Update(int64(block.Transactions().Len()))
9797
// Iterate over and process the individual transactions
9898
for i, tx := range block.Transactions() {
99-
msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number), header.BaseFee)
99+
msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number, header.Time), header.BaseFee)
100100
if err != nil {
101101
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
102102
}
@@ -190,7 +190,7 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon
190190
// for the transaction, gas used and an error if the transaction failed,
191191
// indicating the block was invalid.
192192
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
193-
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number), header.BaseFee)
193+
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number, header.Time), header.BaseFee)
194194
if err != nil {
195195
return nil, err
196196
}

core/state_processor_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ func TestStateProcessorErrors(t *testing.T) {
301301
txs: []*types.Transaction{
302302
mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)),
303303
},
304-
want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1",
304+
want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, len(code): 4",
305305
},
306306
} {
307307
block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config)

0 commit comments

Comments
 (0)