diff --git a/op-node/rollup/derive/system_config.go b/op-node/rollup/derive/system_config.go index 0d03dd056d3..773a1c6f517 100644 --- a/op-node/rollup/derive/system_config.go +++ b/op-node/rollup/derive/system_config.go @@ -32,6 +32,11 @@ var ( ConfigUpdateEventVersion0 = common.Hash{} ) +var ( + ErrUnknownEventVersion = errors.New("unknown SystemConfig event version") + ErrUnknownEventType = errors.New("unknown SystemConfig event type") +) + // UpdateSystemConfigWithL1Receipts filters all L1 receipts to find config updates and applies the config updates to the given sysCfg // Updates are applied individually, and any malformed or invalid updates are ignored. // Any errors encountered during the update process are returned as a multierror. @@ -79,7 +84,7 @@ func ProcessSystemConfigUpdateLogEvent(destSysCfg *eth.SystemConfig, ev *types.L // indexed 0 version := ev.Topics[1] if version != ConfigUpdateEventVersion0 { - return fmt.Errorf("unrecognized SystemConfig update event version: %s", version) + return fmt.Errorf("%w: %s", ErrUnknownEventVersion, version) } // indexed 1 updateType := ev.Topics[2] @@ -150,11 +155,11 @@ func ProcessSystemConfigUpdateLogEvent(destSysCfg *eth.SystemConfig, ev *types.L destSysCfg.DAFootprintGasScalar = daFootprintGasScalar return nil default: - return fmt.Errorf("unrecognized L1 sysCfg update type: %s", updateType) + return fmt.Errorf("%w: %s", ErrUnknownEventType, updateType) } } -var ErrParsingSystemConfig = NewCriticalError(errors.New("error parsing system config")) +var ErrParsingSystemConfig = errors.New("error parsing system config") func parseSystemConfigUpdateBatcher(data []byte) (common.Address, error) { reader := bytes.NewReader(data) diff --git a/op-node/rollup/derive/system_config_test.go b/op-node/rollup/derive/system_config_test.go index 87a3bc1e291..8317587543a 100644 --- a/op-node/rollup/derive/system_config_test.go +++ b/op-node/rollup/derive/system_config_test.go @@ -387,6 +387,25 @@ func TestUpdateSystemConfigWithL1Receipts_Atomicity(t *testing.T) { }, Data: []byte{0x00}, // insufficient bytes for pointer/length -> parse error } + // Future / unknown event type + futureLogType := &types.Log{ + Address: l1Addr, + Topics: []common.Hash{ + ConfigUpdateEventABIHash, + ConfigUpdateEventVersion0, + common.Hash{0: 'a', 31: 7}, // test assumes this is not a known event type + }, + } + // Future / unknown event version + futureLogVersion := &types.Log{ + Address: l1Addr, + Topics: []common.Hash{ + ConfigUpdateEventABIHash, + common.Hash{31: 1}, // test assumes this is not a known event version + SystemConfigUpdateBatcher, + }, + Data: batcherData, + } receipts := []*types.Receipt{ { Status: types.ReceiptStatusSuccessful, @@ -396,6 +415,14 @@ func TestUpdateSystemConfigWithL1Receipts_Atomicity(t *testing.T) { Status: types.ReceiptStatusSuccessful, Logs: []*types.Log{malformedGasLog}, }, + { + Status: types.ReceiptStatusSuccessful, + Logs: []*types.Log{futureLogType}, + }, + { + Status: types.ReceiptStatusSuccessful, + Logs: []*types.Log{futureLogVersion}, + }, } err = UpdateSystemConfigWithL1Receipts(&sysCfg, receipts, &cfg, 0) // Error should be returned due to malformed update, but valid updates should apply @@ -404,6 +431,11 @@ func TestUpdateSystemConfigWithL1Receipts_Atomicity(t *testing.T) { require.Equal(t, newBatcher, sysCfg.BatcherAddr) // Confirm invalid update did not apply; GasLimit remains unchanged require.Equal(t, initial.GasLimit, sysCfg.GasLimit) + // Confirm error contains expected messages + require.ErrorContains(t, err, "invalid pointer field") + require.ErrorIs(t, err, ErrParsingSystemConfig) + require.ErrorIs(t, err, ErrUnknownEventType) + require.ErrorIs(t, err, ErrUnknownEventVersion) }) t.Run("applies multiple updates within a single receipt", func(t *testing.T) {