Skip to content

Commit f3dfc7a

Browse files
author
colinlyguo
committed
add unit tests
1 parent 85a8482 commit f3dfc7a

File tree

7 files changed

+292
-0
lines changed

7 files changed

+292
-0
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ test: all
4343
$(GORUN) build/ci.go test ./consensus ./core ./eth ./miner ./node ./trie ./rollup/...
4444
# RIP-7212 (secp256r1) precompiled contract test
4545
cd ${PWD}/core/vm; go test -v -run=^TestPrecompiledP256 -bench=^BenchmarkPrecompiledP256
46+
# EIP-7702 test
47+
cd ${PWD}/core/vm/runtime; go test -v -run=^TestDelegatedAccountAccessCost
48+
cd ${PWD}/core/types; go test -v -run=^TestParseDelegation
4649

4750
lint: ## Run linters.
4851
$(GORUN) build/ci.go lint

core/blockchain_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package core
1818

1919
import (
20+
"bytes"
2021
"errors"
2122
"fmt"
2223
"io/ioutil"
@@ -27,6 +28,7 @@ import (
2728
"testing"
2829
"time"
2930

31+
"github.com/holiman/uint256"
3032
"github.com/stretchr/testify/assert"
3133

3234
"github.com/scroll-tech/go-ethereum/common"
@@ -3789,3 +3791,94 @@ func TestCurieTransition(t *testing.T) {
37893791
}
37903792
}
37913793
}
3794+
3795+
// TestEIP7702 deploys two delegation designations and calls them. It writes one
3796+
// value to storage which is verified after.
3797+
func TestEIP7702(t *testing.T) {
3798+
var (
3799+
config = *params.TestChainConfig
3800+
signer = types.LatestSigner(&config)
3801+
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
3802+
key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
3803+
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
3804+
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
3805+
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
3806+
bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb")
3807+
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
3808+
)
3809+
3810+
gspec := &Genesis{
3811+
Config: &config,
3812+
Alloc: GenesisAlloc{
3813+
addr1: {Balance: funds},
3814+
addr2: {Balance: funds},
3815+
aa: { // The address 0xAAAA calls into addr2
3816+
Code: common.Hex2Bytes("6000600060006000600173703c4b2bd70c169f5717101caee543299fc946c75af1"),
3817+
Nonce: 0,
3818+
Balance: big.NewInt(0),
3819+
},
3820+
bb: { // The address 0xBBBB sstores 42 into slot 42.
3821+
Code: common.Hex2Bytes("6042604255"),
3822+
Nonce: 0,
3823+
Balance: big.NewInt(0),
3824+
},
3825+
},
3826+
}
3827+
3828+
// Sign authorization tuples.
3829+
// The way the auths are combined, it becomes
3830+
// 1. tx -> addr1 which is delegated to 0xaaaa
3831+
// 2. addr1:0xaaaa calls into addr2:0xbbbb
3832+
// 3. addr2:0xbbbb writes to storage
3833+
auth1, _ := types.SignSetCode(key1, types.SetCodeAuthorization{
3834+
ChainID: *uint256.MustFromBig(gspec.Config.ChainID),
3835+
Address: aa,
3836+
Nonce: 1,
3837+
})
3838+
auth2, _ := types.SignSetCode(key2, types.SetCodeAuthorization{
3839+
Address: bb,
3840+
Nonce: 0,
3841+
})
3842+
3843+
db := rawdb.NewMemoryDatabase()
3844+
genesis := gspec.MustCommit(db)
3845+
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 1, func(i int, b *BlockGen) {
3846+
b.SetCoinbase(aa)
3847+
txdata := &types.SetCodeTx{
3848+
ChainID: uint256.MustFromBig(gspec.Config.ChainID),
3849+
Nonce: 0,
3850+
To: addr1,
3851+
Gas: 500000,
3852+
GasFeeCap: uint256.MustFromBig(newGwei(5)),
3853+
GasTipCap: uint256.NewInt(2),
3854+
SetCodeAuthorizations: []types.SetCodeAuthorization{auth1, auth2},
3855+
}
3856+
tx := types.MustSignNewTx(key1, signer, txdata)
3857+
b.AddTx(tx)
3858+
})
3859+
chain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
3860+
defer chain.Stop()
3861+
3862+
if n, err := chain.InsertChain(blocks); err != nil {
3863+
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
3864+
}
3865+
3866+
// Verify delegation designations were deployed.
3867+
state, _ := chain.State()
3868+
code, want := state.GetCode(addr1), types.AddressToDelegation(auth1.Address)
3869+
if !bytes.Equal(code, want) {
3870+
t.Fatalf("addr1 code incorrect: got %s, want %s", common.Bytes2Hex(code), common.Bytes2Hex(want))
3871+
}
3872+
code, want = state.GetCode(addr2), types.AddressToDelegation(auth2.Address)
3873+
if !bytes.Equal(code, want) {
3874+
t.Fatalf("addr2 code incorrect: got %s, want %s", common.Bytes2Hex(code), common.Bytes2Hex(want))
3875+
}
3876+
// Verify delegation executed the correct code.
3877+
var (
3878+
fortyTwo = common.BytesToHash([]byte{0x42})
3879+
actual = state.GetState(addr2, fortyTwo)
3880+
)
3881+
if !bytes.Equal(actual[:], fortyTwo[:]) {
3882+
t.Fatalf("addr2 storage wrong: expected %d, got %d", fortyTwo, actual)
3883+
}
3884+
}

core/state_processor_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
"golang.org/x/crypto/sha3"
2525

26+
"github.com/holiman/uint256"
2627
"github.com/scroll-tech/go-ethereum/common"
2728
"github.com/scroll-tech/go-ethereum/common/math"
2829
"github.com/scroll-tech/go-ethereum/consensus"
@@ -60,6 +61,8 @@ func TestStateProcessorErrors(t *testing.T) {
6061
CurieBlock: big.NewInt(0),
6162
DarwinTime: new(uint64),
6263
DarwinV2Time: new(uint64),
64+
EuclidTime: new(uint64),
65+
EuclidV2Time: new(uint64),
6366
Ethash: new(params.EthashConfig),
6467
}
6568
signer = types.LatestSigner(config)
@@ -92,6 +95,22 @@ func TestStateProcessorErrors(t *testing.T) {
9295
}), signer, key1)
9396
return tx
9497
}
98+
var mkSetCodeTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, setCodeAuthorizations []types.SetCodeAuthorization) *types.Transaction {
99+
tx, err := types.SignTx(types.NewTx(&types.SetCodeTx{
100+
ChainID: uint256.MustFromBig(config.ChainID),
101+
Nonce: nonce,
102+
GasTipCap: uint256.MustFromBig(gasTipCap),
103+
GasFeeCap: uint256.MustFromBig(gasFeeCap),
104+
Gas: gasLimit,
105+
To: to,
106+
Value: new(uint256.Int),
107+
SetCodeAuthorizations: setCodeAuthorizations,
108+
}), signer, key1)
109+
if err != nil {
110+
t.Fatal(err)
111+
}
112+
return tx
113+
}
95114
{ // Tests against a 'recent' chain definition
96115
var (
97116
db = rawdb.NewMemoryDatabase()
@@ -213,6 +232,13 @@ func TestStateProcessorErrors(t *testing.T) {
213232
},
214233
want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 2431633873983640103894990685182446064918669677978451844828609264166175722438635000",
215234
},
235+
{ // ErrEmptyAuthList
236+
txs: []*types.Transaction{
237+
mkSetCodeTx(0, common.Address{}, params.TxGas, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), nil),
238+
},
239+
want: "could not apply tx 0 [0xc18d10f4c809dbdfa1a074c3300de9bc4b7f16a20f0ec667f6f67312b71b956a]: EIP-7702 transaction with empty auth list (sender 0x71562b71999873DB5b286dF957af199Ec94617F7)",
240+
},
241+
// ErrSetCodeTxCreate cannot be tested: it is impossible to create a SetCode-tx with nil `to`.
216242
} {
217243
block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config)
218244
_, err := blockchain.InsertChain(types.Blocks{block})

core/types/setcode_tx_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2024 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package types
18+
19+
import (
20+
"testing"
21+
22+
"github.com/scroll-tech/go-ethereum/common"
23+
)
24+
25+
// TestParseDelegation tests a few possible delegation designator values and
26+
// ensures they are parsed correctly.
27+
func TestParseDelegation(t *testing.T) {
28+
addr := common.Address{0x42}
29+
for _, tt := range []struct {
30+
val []byte
31+
want *common.Address
32+
}{
33+
{ // simple correct delegation
34+
val: append(DelegationPrefix, addr.Bytes()...),
35+
want: &addr,
36+
},
37+
{ // wrong address size
38+
val: append(DelegationPrefix, addr.Bytes()[0:19]...),
39+
},
40+
{ // short address
41+
val: append(DelegationPrefix, 0x42),
42+
},
43+
{ // long address
44+
val: append(append(DelegationPrefix, addr.Bytes()...), 0x42),
45+
},
46+
{ // wrong prefix size
47+
val: append(DelegationPrefix[:2], addr.Bytes()...),
48+
},
49+
{ // wrong prefix
50+
val: append([]byte{0xef, 0x01, 0x01}, addr.Bytes()...),
51+
},
52+
{ // wrong prefix
53+
val: append([]byte{0xef, 0x00, 0x00}, addr.Bytes()...),
54+
},
55+
{ // no prefix
56+
val: addr.Bytes(),
57+
},
58+
{ // no address
59+
val: DelegationPrefix,
60+
},
61+
} {
62+
got, ok := ParseDelegation(tt.val)
63+
if ok && tt.want == nil {
64+
t.Fatalf("expected fail, got %s", got.Hex())
65+
}
66+
if !ok && tt.want != nil {
67+
t.Fatalf("failed to parse, want %s", tt.want.Hex())
68+
}
69+
}
70+
}

core/vm/runtime/runtime_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ import (
2020
"fmt"
2121
"math/big"
2222
"os"
23+
"reflect"
2324
"strings"
2425
"testing"
2526
"time"
2627

28+
"github.com/agiledragon/gomonkey/v2"
2729
"github.com/scroll-tech/go-ethereum/accounts/abi"
2830
"github.com/scroll-tech/go-ethereum/common"
2931
"github.com/scroll-tech/go-ethereum/consensus"
@@ -964,3 +966,98 @@ func BenchmarkTracerStepVsCallFrame(b *testing.B) {
964966
benchmarkNonModifyingCode(10000000, code, "tracer-step-10M", stepTracer, b)
965967
benchmarkNonModifyingCode(10000000, code, "tracer-call-frame-10M", callFrameTracer, b)
966968
}
969+
970+
// TestDelegatedAccountAccessCost tests that calling an account with an EIP-7702
971+
// delegation designator incurs the correct amount of gas based on the tracer.
972+
func TestDelegatedAccountAccessCost(t *testing.T) {
973+
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
974+
statedb.SetCode(common.HexToAddress("0xff"), types.AddressToDelegation(common.HexToAddress("0xaa")))
975+
statedb.SetCode(common.HexToAddress("0xaa"), []byte{
976+
byte(vm.PUSH1), 0x00, // PUSH1 0
977+
byte(vm.PUSH1), 0x00, // PUSH1 0
978+
byte(vm.RETURN), // RETURN
979+
})
980+
981+
code := statedb.GetCode(common.HexToAddress("0xff"))
982+
t.Logf("Code at 0xff: %x", code)
983+
984+
code = statedb.GetCode(common.HexToAddress("0xaa"))
985+
t.Logf("Code at 0xaa: %x", code)
986+
987+
fmt.Println(statedb.Exist(common.HexToAddress("0xff")))
988+
989+
patches := gomonkey.ApplyMethod(reflect.TypeOf(statedb), "GetPoseidonCodeHash", func(_ *state.StateDB, addr common.Address) common.Hash {
990+
return common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef")
991+
})
992+
defer patches.Reset()
993+
994+
for i, tc := range []struct {
995+
code []byte
996+
step int
997+
want uint64
998+
}{
999+
{ // CALL(0xff)
1000+
code: []byte{
1001+
byte(vm.PUSH1), 0x0,
1002+
byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1),
1003+
byte(vm.PUSH1), 0xff, byte(vm.DUP1), byte(vm.CALL), byte(vm.POP),
1004+
},
1005+
step: 7,
1006+
want: 5455,
1007+
},
1008+
{ // CALLCODE(0xff)
1009+
code: []byte{
1010+
byte(vm.PUSH1), 0x0,
1011+
byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1),
1012+
byte(vm.PUSH1), 0xff, byte(vm.DUP1), byte(vm.CALLCODE), byte(vm.POP),
1013+
},
1014+
step: 7,
1015+
want: 5455,
1016+
},
1017+
{ // DELEGATECALL(0xff)
1018+
code: []byte{
1019+
byte(vm.PUSH1), 0x0,
1020+
byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1),
1021+
byte(vm.PUSH1), 0xff, byte(vm.DUP1), byte(vm.DELEGATECALL), byte(vm.POP),
1022+
},
1023+
step: 6,
1024+
want: 5455,
1025+
},
1026+
{ // STATICCALL(0xff)
1027+
code: []byte{
1028+
byte(vm.PUSH1), 0x0,
1029+
byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1),
1030+
byte(vm.PUSH1), 0xff, byte(vm.DUP1), byte(vm.STATICCALL), byte(vm.POP),
1031+
},
1032+
step: 6,
1033+
want: 5455,
1034+
},
1035+
{ // SELFDESTRUCT(0xff): should not be affected by resolution
1036+
code: []byte{
1037+
byte(vm.PUSH1), 0xff, byte(vm.SELFDESTRUCT),
1038+
},
1039+
step: 1,
1040+
want: 3,
1041+
},
1042+
} {
1043+
tracer := vm.NewStructLogger(nil)
1044+
Execute(tc.code, nil, &Config{
1045+
ChainConfig: params.TestChainConfig,
1046+
State: statedb,
1047+
EVMConfig: vm.Config{
1048+
Debug: true,
1049+
Tracer: tracer,
1050+
},
1051+
})
1052+
have := tracer.StructLogs()[tc.step].GasCost
1053+
if want := tc.want; have != want {
1054+
for ii, op := range tracer.StructLogs() {
1055+
t.Logf("%d: %v %d", ii, op.OpName(), op.GasCost)
1056+
}
1057+
t.Fatalf("tescase %d, gas report wrong, step %d, have %d want %d", i, tc.step, have, want)
1058+
}
1059+
if want := tc.want; have != want {
1060+
t.Fatalf("testcase %d, gas report wrong, step %d, have %d want %d", i, tc.step, have, want)
1061+
}
1062+
}
1063+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.21
55
require (
66
github.com/Azure/azure-storage-blob-go v0.7.0
77
github.com/VictoriaMetrics/fastcache v1.12.2
8+
github.com/agiledragon/gomonkey/v2 v2.12.0
89
github.com/aws/aws-sdk-go-v2 v1.2.0
910
github.com/aws/aws-sdk-go-v2/config v1.1.1
1011
github.com/aws/aws-sdk-go-v2/credentials v1.1.1

params/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,8 @@ var (
499499
CurieBlock: big.NewInt(0),
500500
DarwinTime: new(uint64),
501501
DarwinV2Time: new(uint64),
502+
EuclidTime: new(uint64),
503+
EuclidV2Time: new(uint64),
502504
TerminalTotalDifficulty: nil,
503505
Ethash: new(EthashConfig),
504506
Clique: nil,

0 commit comments

Comments
 (0)