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

Commit f37296c

Browse files
authored
Add pending UserOps by same sender to context (#73)
1 parent 336d8ee commit f37296c

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

internal/testutils/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var (
1212
OneETH = big.NewInt(1000000000000000000)
1313
DefaultUnstakeDelaySec = uint32(86400)
1414
ValidAddress = common.HexToAddress("0x7357b8a705328FC283dF72D7Ac546895B596DC12")
15+
ChainID = big.NewInt(1)
1516
StakedDepositInfo = &entrypoint.IStakeManagerDepositInfo{
1617
Deposit: big.NewInt(OneETH.Int64()),
1718
Staked: true,

pkg/client/client.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,15 @@ func (i *Client) SendUserOperation(op map[string]any, ep string) (string, error)
113113
// }
114114
// }
115115

116+
// Fetch any pending UserOperations in the mempool by the same sender
117+
penOps, err := i.mempool.GetOps(epAddr, userOp.Sender)
118+
if err != nil {
119+
l.Error(err, "eth_sendUserOperation error")
120+
return "", err
121+
}
122+
116123
// Run through client module stack.
117-
ctx := modules.NewUserOpHandlerContext(userOp, epAddr, i.chainID)
124+
ctx := modules.NewUserOpHandlerContext(userOp, penOps, epAddr, i.chainID)
118125
if err := i.userOpHandler(ctx); err != nil {
119126
l.Error(err, "eth_sendUserOperation error")
120127
return "", err

pkg/modules/context.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,13 @@ type UserOpHandlerCtx struct {
6464
EntryPoint common.Address
6565
ChainID *big.Int
6666
deposits map[common.Address]*entrypoint.IStakeManagerDepositInfo
67+
pendingOps []*userop.UserOperation
6768
}
6869

6970
// NewUserOpHandlerContext creates a new UserOpHandlerCtx using a given op.
7071
func NewUserOpHandlerContext(
7172
op *userop.UserOperation,
73+
pendingOps []*userop.UserOperation,
7274
entryPoint common.Address,
7375
chainID *big.Int,
7476
) *UserOpHandlerCtx {
@@ -77,6 +79,7 @@ func NewUserOpHandlerContext(
7779
EntryPoint: entryPoint,
7880
ChainID: chainID,
7981
deposits: make(map[common.Address]*entrypoint.IStakeManagerDepositInfo),
82+
pendingOps: append([]*userop.UserOperation{}, pendingOps...),
8083
}
8184
}
8285

@@ -90,3 +93,8 @@ func (c *UserOpHandlerCtx) AddDepositInfo(entity common.Address, dep *entrypoint
9093
func (c *UserOpHandlerCtx) GetDepositInfo(entity common.Address) *entrypoint.IStakeManagerDepositInfo {
9194
return c.deposits[entity]
9295
}
96+
97+
// GetPendingOps returns all pending UserOperations in the mempool by the same UserOp.Sender.
98+
func (c *UserOpHandlerCtx) GetPendingOps() []*userop.UserOperation {
99+
return c.pendingOps
100+
}

pkg/modules/context_test.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import (
66

77
"github.com/ethereum/go-ethereum/common"
88
"github.com/stackup-wallet/stackup-bundler/internal/testutils"
9+
"github.com/stackup-wallet/stackup-bundler/pkg/userop"
910
)
1011

1112
// TestAddDepositInfoToCtx verifies that stake info can be added to a context and later retrieved.
1213
func TestAddDepositInfoToCtx(t *testing.T) {
1314
op := testutils.MockValidInitUserOp()
14-
ctx := NewUserOpHandlerContext(op, common.HexToAddress("0x"), big.NewInt(1))
15+
penOps := []*userop.UserOperation{}
16+
ctx := NewUserOpHandlerContext(op, penOps, testutils.ValidAddress, testutils.ChainID)
1517

1618
entity := op.GetFactory()
1719
dep := testutils.StakedDepositInfo
@@ -26,9 +28,34 @@ func TestAddDepositInfoToCtx(t *testing.T) {
2628
// set. Expects nil.
2729
func TestGetNilDepositInfoFromCtx(t *testing.T) {
2830
op := testutils.MockValidInitUserOp()
29-
ctx := NewUserOpHandlerContext(op, common.HexToAddress("0x"), big.NewInt(1))
31+
penOps := []*userop.UserOperation{}
32+
ctx := NewUserOpHandlerContext(op, penOps, testutils.ValidAddress, testutils.ChainID)
3033

3134
if dep := ctx.GetDepositInfo(op.GetFactory()); dep != nil {
3235
t.Fatalf("got %+v, want nil", dep)
3336
}
3437
}
38+
39+
// TestGetPendingOps calls (c *UserOpHandlerCtx).GetPendingOps and verifies that it returns the same array of
40+
// UserOperations the context was initialized with.
41+
func TestGetPendingOps(t *testing.T) {
42+
op := testutils.MockValidInitUserOp()
43+
penOp1 := testutils.MockValidInitUserOp()
44+
penOp2 := testutils.MockValidInitUserOp()
45+
penOp2.Nonce = big.NewInt(0).Add(penOp1.Nonce, common.Big1)
46+
penOp3 := testutils.MockValidInitUserOp()
47+
penOp3.Nonce = big.NewInt(0).Add(penOp2.Nonce, common.Big1)
48+
initPenOps := []*userop.UserOperation{penOp1, penOp2, penOp3}
49+
ctx := NewUserOpHandlerContext(op, initPenOps, testutils.ValidAddress, testutils.ChainID)
50+
51+
penOps := ctx.GetPendingOps()
52+
if len(penOps) != len(initPenOps) {
53+
t.Fatalf("got length %d, want %d", len(penOps), len(initPenOps))
54+
}
55+
56+
for i, penOp := range penOps {
57+
if !testutils.IsOpsEqual(penOp, initPenOps[i]) {
58+
t.Fatalf("ops not equal: %s", testutils.GetOpsDiff(penOp, initPenOps[i]))
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)