@@ -10,6 +10,7 @@ import (
10
10
"github.com/stackup-wallet/stackup-bundler/internal/logger"
11
11
"github.com/stackup-wallet/stackup-bundler/pkg/mempool"
12
12
"github.com/stackup-wallet/stackup-bundler/pkg/modules"
13
+ "github.com/stackup-wallet/stackup-bundler/pkg/modules/gasprice"
13
14
"github.com/stackup-wallet/stackup-bundler/pkg/modules/noop"
14
15
"github.com/stackup-wallet/stackup-bundler/pkg/userop"
15
16
)
@@ -23,10 +24,11 @@ type Bundler struct {
23
24
batchHandler modules.BatchHandlerFunc
24
25
logger logr.Logger
25
26
isRunning bool
26
- stop chan bool
27
- watch chan bool
28
- onStop func ()
27
+ done chan bool
28
+ stop func ()
29
29
maxBatch int
30
+ gbf gasprice.GetBaseFeeFunc
31
+ ggp gasprice.GetLegacyGasPriceFunc
30
32
}
31
33
32
34
// New initializes a new EIP-4337 bundler which can be extended with modules for validating batches and
@@ -39,10 +41,11 @@ func New(mempool *mempool.Mempool, chainID *big.Int, supportedEntryPoints []comm
39
41
batchHandler : noop .BatchHandler ,
40
42
logger : logger .NewZeroLogr ().WithName ("bundler" ),
41
43
isRunning : false ,
42
- stop : make (chan bool ),
43
- watch : make (chan bool ),
44
- onStop : func () {},
44
+ done : make (chan bool ),
45
+ stop : func () {},
45
46
maxBatch : 0 ,
47
+ gbf : gasprice .NoopGetBaseFeeFunc (),
48
+ ggp : gasprice .NoopGetLegacyGasPriceFunc (),
46
49
}
47
50
}
48
51
@@ -51,6 +54,17 @@ func (i *Bundler) SetMaxBatch(max int) {
51
54
i .maxBatch = max
52
55
}
53
56
57
+ // SetGetBaseFeeFunc defines the function used to retrieve an estimate for basefee during each bundler run.
58
+ func (i * Bundler ) SetGetBaseFeeFunc (gbf gasprice.GetBaseFeeFunc ) {
59
+ i .gbf = gbf
60
+ }
61
+
62
+ // SetGetLegacyGasPriceFunc defines the function used to retrieve an estimate for gas price during each
63
+ // bundler run.
64
+ func (i * Bundler ) SetGetLegacyGasPriceFunc (ggp gasprice.GetLegacyGasPriceFunc ) {
65
+ i .ggp = ggp
66
+ }
67
+
54
68
// UseLogger defines the logger object used by the Bundler instance based on the go-logr/logr interface.
55
69
func (i * Bundler ) UseLogger (logger logr.Logger ) {
56
70
i .logger = logger .WithName ("bundler" )
@@ -63,13 +77,30 @@ func (i *Bundler) UseModules(handlers ...modules.BatchHandlerFunc) {
63
77
64
78
// Process will create a batch from the mempool and send it through to the EntryPoint.
65
79
func (i * Bundler ) Process (ep common.Address ) (* modules.BatchHandlerCtx , error ) {
80
+ // Init logger
66
81
start := time .Now ()
67
82
l := i .logger .
68
83
WithName ("run" ).
69
84
WithValues ("entrypoint" , ep .String ()).
70
85
WithValues ("chain_id" , i .chainID .String ())
71
86
72
- batch , err := i .mempool .BundleOps (ep )
87
+ // Get current block basefee
88
+ bf , err := i .gbf ()
89
+ if err != nil {
90
+ l .Error (err , "bundler run error" )
91
+ return nil , err
92
+ }
93
+
94
+ // Get suggested gas price (for networks that don't support EIP-1559)
95
+ gp , err := i .ggp ()
96
+ if err != nil {
97
+ l .Error (err , "bundler run error" )
98
+ return nil , err
99
+ }
100
+
101
+ // Get all pending userOps from the mempool. This will be in FIFO order. Downstream modules should sort it
102
+ // based on more specific strategies.
103
+ batch , err := i .mempool .Dump (ep )
73
104
if err != nil {
74
105
l .Error (err , "bundler run error" )
75
106
return nil , err
@@ -79,19 +110,22 @@ func (i *Bundler) Process(ep common.Address) (*modules.BatchHandlerCtx, error) {
79
110
}
80
111
batch = adjustBatchSize (i .maxBatch , batch )
81
112
82
- ctx := modules .NewBatchHandlerContext (batch , ep , i .chainID )
113
+ // Create context and execute modules.
114
+ ctx := modules .NewBatchHandlerContext (batch , ep , i .chainID , bf , gp )
83
115
if err := i .batchHandler (ctx ); err != nil {
84
116
l .Error (err , "bundler run error" )
85
117
return nil , err
86
118
}
87
119
120
+ // Remove userOps that remain in the context from mempool.
88
121
rmOps := append ([]* userop.UserOperation {}, ctx .Batch ... )
89
122
rmOps = append (rmOps , ctx .PendingRemoval ... )
90
123
if err := i .mempool .RemoveOps (ep , rmOps ... ); err != nil {
91
124
l .Error (err , "bundler run error" )
92
125
return nil , err
93
126
}
94
127
128
+ // Update logs for the current run.
95
129
bat := []string {}
96
130
for _ , op := range ctx .Batch {
97
131
bat = append (bat , op .GetUserOpHash (ep , i .chainID ).String ())
@@ -118,12 +152,13 @@ func (i *Bundler) Run() error {
118
152
return nil
119
153
}
120
154
155
+ ticker := time .NewTicker (1 * time .Second )
121
156
go func (i * Bundler ) {
122
157
for {
123
158
select {
124
- case <- i .stop :
159
+ case <- i .done :
125
160
return
126
- case <- i . watch :
161
+ case <- ticker . C :
127
162
for _ , ep := range i .supportedEntryPoints {
128
163
_ , err := i .Process (ep )
129
164
if err != nil {
@@ -136,7 +171,7 @@ func (i *Bundler) Run() error {
136
171
}(i )
137
172
138
173
i .isRunning = true
139
- i .onStop = i . mempool . OnAdd ( i . watch )
174
+ i .stop = ticker . Stop
140
175
return nil
141
176
}
142
177
@@ -147,6 +182,6 @@ func (i *Bundler) Stop() {
147
182
}
148
183
149
184
i .isRunning = false
150
- i .stop <- true
151
- i .onStop ()
185
+ i .stop ()
186
+ i .done <- true
152
187
}
0 commit comments