Skip to content
This repository was archived by the owner on Oct 20, 2024. It is now read-only.

Commit 1b2b732

Browse files
authored
Refactor: Move sender sanity checks into separate file with tests (#66)
1 parent 9278227 commit 1b2b732

File tree

5 files changed

+122
-44
lines changed

5 files changed

+122
-44
lines changed

internal/testutils/opmock.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package testutils
2+
3+
import "github.com/stackup-wallet/stackup-bundler/pkg/userop"
4+
5+
var (
6+
MockUserOpData = map[string]any{
7+
"sender": "0xa13D69573f994bf662C2714560c44dd7266FC547",
8+
"nonce": "0x0",
9+
"initCode": "0xe19e9755942bb0bd0cccce25b1742596b8a8250b3bf2c3e700000000000000000000000078d4f01f56b982a3b03c4e127a5d3afa8ebee6860000000000000000000000008b388a082f370d8ac2e2b3997e9151168bd09ff50000000000000000000000000000000000000000000000000000000000000000",
10+
"callData": "0x80c5c7d0000000000000000000000000a13d69573f994bf662c2714560c44dd7266fc547000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
11+
"callGasLimit": "0x558c",
12+
"verificationGasLimit": "0x129727",
13+
"maxFeePerGas": "0xa862145e",
14+
"maxPriorityFeePerGas": "0xa8621440",
15+
"paymasterAndData": "0x",
16+
"preVerificationGas": "0xc650",
17+
"signature": "0xa925dcc5e5131636e244d4405334c25f034ebdd85c0cb12e8cdb13c15249c2d466d0bade18e2cafd3513497f7f968dcbb63e519acd9b76dcae7acd61f11aa8421b",
18+
}
19+
MockByteCode = "0x6080604052"
20+
)
21+
22+
// Returns a valid initial userOperation for an EIP-4337 account.
23+
func MockValidInitUserOp() *userop.UserOperation {
24+
op, _ := userop.New(MockUserOpData)
25+
return op
26+
}

pkg/modules/checks/sanitychecks.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,6 @@ import (
1313
"github.com/stackup-wallet/stackup-bundler/pkg/userop"
1414
)
1515

16-
// Checks that the sender is an existing contract, or the initCode is not empty (but not both)
17-
func checkSender(eth *ethclient.Client, op *userop.UserOperation) error {
18-
bytecode, err := eth.CodeAt(context.Background(), op.Sender, nil)
19-
if err != nil {
20-
return err
21-
}
22-
23-
if len(bytecode) == 0 && len(op.InitCode) == 0 {
24-
return errors.New("sender: not deployed, initCode must be set")
25-
}
26-
if len(bytecode) > 0 && len(op.InitCode) > 0 {
27-
return errors.New("sender: already deployed, initCode must be empty")
28-
}
29-
30-
return nil
31-
}
32-
3316
// Checks that the verificationGasLimit is sufficiently low (<= MAX_VERIFICATION_GAS) and the
3417
// preVerificationGas is sufficiently high (enough to pay for the calldata gas cost of serializing
3518
// the UserOperation plus PRE_VERIFICATION_OVERHEAD_GAS)

pkg/modules/checks/sanitychecks_test.go

Lines changed: 0 additions & 27 deletions
This file was deleted.

pkg/modules/checks/sender.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package checks
2+
3+
import (
4+
"context"
5+
"errors"
6+
7+
"github.com/ethereum/go-ethereum/ethclient"
8+
"github.com/stackup-wallet/stackup-bundler/pkg/userop"
9+
)
10+
11+
// Checks that the sender is an existing contract, or the initCode is not empty (but not both)
12+
func checkSender(eth *ethclient.Client, op *userop.UserOperation) error {
13+
bytecode, err := eth.CodeAt(context.Background(), op.Sender, nil)
14+
if err != nil {
15+
return err
16+
}
17+
18+
if len(bytecode) == 0 && len(op.InitCode) == 0 {
19+
return errors.New("sender: not deployed, initCode must be set")
20+
}
21+
if len(bytecode) > 0 && len(op.InitCode) > 0 {
22+
return errors.New("sender: already deployed, initCode must be empty")
23+
}
24+
25+
return nil
26+
}

pkg/modules/checks/sender_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package checks
2+
3+
import (
4+
"testing"
5+
6+
"github.com/ethereum/go-ethereum/ethclient"
7+
"github.com/stackup-wallet/stackup-bundler/internal/testutils"
8+
)
9+
10+
// TestSenderExistAndInitCodeDNE calls checks.CheckSender where sender contract exist and initCode does not.
11+
// Expect nil.
12+
func TestSenderExistAndInitCodeDNE(t *testing.T) {
13+
server := testutils.EthMock(testutils.MethodMocks{
14+
"eth_getCode": testutils.MockByteCode,
15+
})
16+
defer server.Close()
17+
18+
eth, _ := ethclient.Dial(server.URL)
19+
op := testutils.MockValidInitUserOp()
20+
op.InitCode = []byte{}
21+
if err := checkSender(eth, op); err != nil {
22+
t.Fatalf(`got err %v, want nil`, err)
23+
}
24+
}
25+
26+
// TestSenderAndInitCodeExist calls checks.CheckSender where sender contract and initCode exist. Expect
27+
// error.
28+
func TestSenderAndInitCodeExist(t *testing.T) {
29+
server := testutils.EthMock(testutils.MethodMocks{
30+
"eth_getCode": testutils.MockByteCode,
31+
})
32+
defer server.Close()
33+
34+
eth, _ := ethclient.Dial(server.URL)
35+
op := testutils.MockValidInitUserOp()
36+
if err := checkSender(eth, op); err == nil {
37+
t.Fatalf(`got nil, want err`)
38+
}
39+
}
40+
41+
// TestSenderDNEAndInitCodeExist calls checks.CheckSender where sender contract does not exist and initCode
42+
// does. Expect nil.
43+
func TestSenderDNEAndInitCodeExist(t *testing.T) {
44+
server := testutils.EthMock(testutils.MethodMocks{
45+
"eth_getCode": "0x",
46+
})
47+
defer server.Close()
48+
49+
eth, _ := ethclient.Dial(server.URL)
50+
op := testutils.MockValidInitUserOp()
51+
if err := checkSender(eth, op); err != nil {
52+
t.Fatalf(`got err %v, want nil`, err)
53+
}
54+
}
55+
56+
// TestSenderAndInitCodeDNE calls checks.CheckSender where sender contract and initCode does not exist.
57+
// Expect error.
58+
func TestSenderAndInitCodeDNE(t *testing.T) {
59+
server := testutils.EthMock(testutils.MethodMocks{
60+
"eth_getCode": "0x",
61+
})
62+
defer server.Close()
63+
64+
eth, _ := ethclient.Dial(server.URL)
65+
op := testutils.MockValidInitUserOp()
66+
op.InitCode = []byte{}
67+
if err := checkSender(eth, op); err == nil {
68+
t.Fatalf(`got nil, want err`)
69+
}
70+
}

0 commit comments

Comments
 (0)