Skip to content

Commit 4d0abed

Browse files
authored
feat: add bid-options-slash-enabled flag to oracle (#909)
* disable bid options slashing in oracle service Comment out bid options unmarshaling, position constraint checking, and shutterised bid option logic in the oracle updater. Bundle atomicity slashing is preserved. * feat: add bid-options-slash-enabled flag to oracle (default false) Add a --bid-options-slash-enabled CLI flag (env: MEV_ORACLE_BID_OPTIONS_SLASH_ENABLED) that gates bid options slashing in the oracle updater. When disabled (default), the oracle skips position constraint checking, shutterised bid option handling, and unsatisfied constraint slashing. Bundle atomicity slashing is always active. * test: cover both enabled and disabled bid options slash in TestBidOptions Split TestBidOptions into subtests for enabled/disabled flag. When disabled, all commitments settle as reward with no bid options slashing.
1 parent f78fb5d commit 4d0abed

4 files changed

Lines changed: 193 additions & 143 deletions

File tree

oracle/cmd/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ var (
256256
"https://bloxroute.regulated.blxrbdn.com",
257257
),
258258
})
259+
260+
optionBidOptionsSlashEnabled = altsrc.NewBoolFlag(&cli.BoolFlag{
261+
Name: "bid-options-slash-enabled",
262+
Usage: "Enable slashing based on bid options (position constraints, shutterised bids)",
263+
EnvVars: []string{"MEV_ORACLE_BID_OPTIONS_SLASH_ENABLED"},
264+
Value: false,
265+
})
259266
)
260267

261268
func main() {
@@ -288,6 +295,7 @@ func main() {
288295
optionGasTipCap,
289296
optionGasFeeCap,
290297
optionRelayUrls,
298+
optionBidOptionsSlashEnabled,
291299
}
292300
app := &cli.App{
293301
Name: "mev-oracle",
@@ -408,6 +416,7 @@ func launchOracleWithConfig(c *cli.Context) error {
408416
DefaultGasTipCap: gasTipCap,
409417
DefaultGasFeeCap: gasFeeCap,
410418
RelayUrls: c.StringSlice(optionRelayUrls.Name),
419+
BidOptionsSlashEnabled: c.Bool(optionBidOptionsSlashEnabled.Name),
411420
})
412421
if err != nil {
413422
return fmt.Errorf("failed starting node: %w", err)

oracle/pkg/node/node.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type Options struct {
6363
DefaultGasLimit uint64
6464
DefaultGasTipCap *big.Int
6565
DefaultGasFeeCap *big.Int
66+
BidOptionsSlashEnabled bool
6667
}
6768

6869
type Node struct {
@@ -269,6 +270,7 @@ func NewNode(opts *Options) (*Node, error) {
269270
evtMgr,
270271
oracleTransactorSession,
271272
txmonitor.NewEVMHelperWithLogger(rawClient, nd.logger, contracts),
273+
opts.BidOptionsSlashEnabled,
272274
)
273275
if err != nil {
274276
nd.logger.Error("failed to instantiate updater", "error", err)

oracle/pkg/updater/updater.go

Lines changed: 61 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,16 @@ type EVMClient interface {
8484
}
8585

8686
type Updater struct {
87-
logger *slog.Logger
88-
l1Client EVMClient
89-
winnerRegister WinnerRegister
90-
oracle Oracle
91-
evtMgr events.EventManager
92-
l1BlockCache *lru.Cache[uint64, map[string]TxMetadata]
93-
openedCmts chan *preconf.PreconfmanagerOpenedCommitmentStored
94-
metrics *metrics
95-
receiptBatcher txmonitor.BatchReceiptGetter
87+
logger *slog.Logger
88+
l1Client EVMClient
89+
winnerRegister WinnerRegister
90+
oracle Oracle
91+
evtMgr events.EventManager
92+
l1BlockCache *lru.Cache[uint64, map[string]TxMetadata]
93+
openedCmts chan *preconf.PreconfmanagerOpenedCommitmentStored
94+
metrics *metrics
95+
receiptBatcher txmonitor.BatchReceiptGetter
96+
bidOptionsSlashEnabled bool
9697
}
9798

9899
func NewUpdater(
@@ -102,21 +103,23 @@ func NewUpdater(
102103
evtMgr events.EventManager,
103104
oracle Oracle,
104105
receiptBatcher txmonitor.BatchReceiptGetter,
106+
bidOptionsSlashEnabled bool,
105107
) (*Updater, error) {
106108
l1BlockCache, err := lru.New[uint64, map[string]TxMetadata](1024)
107109
if err != nil {
108110
return nil, fmt.Errorf("failed to create L1 block cache: %w", err)
109111
}
110112
return &Updater{
111-
logger: logger,
112-
l1Client: l1Client,
113-
l1BlockCache: l1BlockCache,
114-
winnerRegister: winnerRegister,
115-
evtMgr: evtMgr,
116-
oracle: oracle,
117-
receiptBatcher: receiptBatcher,
118-
metrics: newMetrics(),
119-
openedCmts: make(chan *preconf.PreconfmanagerOpenedCommitmentStored),
113+
logger: logger,
114+
l1Client: l1Client,
115+
l1BlockCache: l1BlockCache,
116+
winnerRegister: winnerRegister,
117+
evtMgr: evtMgr,
118+
oracle: oracle,
119+
receiptBatcher: receiptBatcher,
120+
metrics: newMetrics(),
121+
openedCmts: make(chan *preconf.PreconfmanagerOpenedCommitmentStored),
122+
bidOptionsSlashEnabled: bidOptionsSlashEnabled,
120123
}, nil
121124
}
122125

@@ -309,15 +312,18 @@ func (u *Updater) handleOpenedCommitment(
309312
revertableTxnsMap[txn] = true
310313
}
311314

312-
opts := new(bidderapiv1.BidOptions)
313-
if update.BidOptions != nil {
314-
if err := proto.Unmarshal(update.BidOptions, opts); err != nil {
315-
u.logger.Error(
316-
"failed to unmarshal bid options",
317-
"commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]),
318-
"error", err,
319-
)
320-
return err
315+
var opts *bidderapiv1.BidOptions
316+
if u.bidOptionsSlashEnabled {
317+
opts = new(bidderapiv1.BidOptions)
318+
if update.BidOptions != nil {
319+
if err := proto.Unmarshal(update.BidOptions, opts); err != nil {
320+
u.logger.Error(
321+
"failed to unmarshal bid options",
322+
"commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]),
323+
"error", err,
324+
)
325+
return err
326+
}
321327
}
322328
}
323329

@@ -339,16 +345,18 @@ func (u *Updater) handleOpenedCommitment(
339345
"revertible", revertableTxnsMap[commitmentTxnHashes[i]],
340346
)
341347

342-
for _, opt := range opts.Options {
343-
if sOpt := opt.GetShutterisedBidOption(); sOpt != nil {
344-
u.logger.Info(
345-
"shutterised bid option present, skipping slash",
346-
"commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]),
347-
"txnHash", update.TxnHash,
348-
"blockNumber", update.BlockNumber,
349-
"shutter option", sOpt,
350-
)
351-
return nil
348+
if u.bidOptionsSlashEnabled {
349+
for _, opt := range opts.Options {
350+
if sOpt := opt.GetShutterisedBidOption(); sOpt != nil {
351+
u.logger.Info(
352+
"shutterised bid option present, skipping slash",
353+
"commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]),
354+
"txnHash", update.TxnHash,
355+
"blockNumber", update.BlockNumber,
356+
"shutter option", sOpt,
357+
)
358+
return nil
359+
}
352360
}
353361
}
354362

@@ -362,25 +370,27 @@ func (u *Updater) handleOpenedCommitment(
362370
)
363371
}
364372

365-
for idx, opt := range opts.Options {
366-
if opt.GetPositionConstraint() != nil {
367-
if checkPositionConstraintSatisfied(opt.GetPositionConstraint(), txnDetails, txns) {
368-
u.logger.Debug(
369-
"positional constraint satisfied",
370-
"commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]),
371-
"txnHash", update.TxnHash,
372-
"blockNumber", update.BlockNumber,
373-
"constraint", opt.GetPositionConstraint(),
374-
)
375-
// Remove the satisfied constraint
376-
opts.Options = append(opts.Options[:idx], opts.Options[idx+1:]...)
377-
break
373+
if u.bidOptionsSlashEnabled {
374+
for idx, opt := range opts.Options {
375+
if opt.GetPositionConstraint() != nil {
376+
if checkPositionConstraintSatisfied(opt.GetPositionConstraint(), txnDetails, txns) {
377+
u.logger.Debug(
378+
"positional constraint satisfied",
379+
"commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]),
380+
"txnHash", update.TxnHash,
381+
"blockNumber", update.BlockNumber,
382+
"constraint", opt.GetPositionConstraint(),
383+
)
384+
// Remove the satisfied constraint
385+
opts.Options = append(opts.Options[:idx], opts.Options[idx+1:]...)
386+
break
387+
}
378388
}
379389
}
380390
}
381391
}
382392

383-
if len(opts.Options) > 0 {
393+
if u.bidOptionsSlashEnabled && len(opts.Options) > 0 {
384394
u.logger.Info(
385395
"not all positional constraints satisfied",
386396
"commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]),

0 commit comments

Comments
 (0)