legacy_bridge_processor.go 16.7 KB
Newer Older
Hamdi Allam's avatar
Hamdi Allam committed
1 2 3 4 5 6
package bridge

import (
	"fmt"
	"math/big"

Hamdi Allam's avatar
Hamdi Allam committed
7
	"github.com/ethereum/go-ethereum/common"
8
	"github.com/ethereum/go-ethereum/crypto"
Hamdi Allam's avatar
Hamdi Allam committed
9 10 11 12 13 14 15 16 17 18
	"github.com/ethereum/go-ethereum/log"

	"github.com/ethereum-optimism/optimism/indexer/config"
	"github.com/ethereum-optimism/optimism/indexer/database"
	"github.com/ethereum-optimism/optimism/indexer/node"
	"github.com/ethereum-optimism/optimism/indexer/processors/contracts"
)

// Legacy Bridge Initiation

19 20 21 22 23
// LegacyL1ProcessInitiatedEvents will query the data for bridge events within the specified block range
// according the pre-bedrock protocol. This follows:
//  1. CanonicalTransactionChain
//  2. L1CrossDomainMessenger
//  3. L1StandardBridge
Hamdi Allam's avatar
Hamdi Allam committed
24
func LegacyL1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L1Metricer, l1Contracts config.L1Contracts, fromHeight, toHeight *big.Int) error {
Hamdi Allam's avatar
Hamdi Allam committed
25
	// (1) CanonicalTransactionChain
26
	ctcTxDepositEvents, err := contracts.LegacyCTCDepositEvents(l1Contracts.LegacyCanonicalTransactionChain, db, fromHeight, toHeight)
Hamdi Allam's avatar
Hamdi Allam committed
27 28 29
	if err != nil {
		return err
	}
Hamdi Allam's avatar
Hamdi Allam committed
30 31 32
	if len(ctcTxDepositEvents) > 0 {
		log.Info("detected legacy transaction deposits", "size", len(ctcTxDepositEvents))
	}
Hamdi Allam's avatar
Hamdi Allam committed
33 34 35 36 37 38 39

	ctcTxDeposits := make(map[logKey]*contracts.LegacyCTCDepositEvent, len(ctcTxDepositEvents))
	transactionDeposits := make([]database.L1TransactionDeposit, len(ctcTxDepositEvents))
	for i := range ctcTxDepositEvents {
		deposit := ctcTxDepositEvents[i]
		ctcTxDeposits[logKey{deposit.Event.BlockHash, deposit.Event.LogIndex}] = &deposit
		transactionDeposits[i] = database.L1TransactionDeposit{
40 41 42 43 44
			// We re-use the L2 Transaction hash as the source hash
			// to remain consistent in the schema.
			SourceHash:        deposit.TxHash,
			L2TransactionHash: deposit.TxHash,

Hamdi Allam's avatar
Hamdi Allam committed
45 46 47 48 49 50 51 52 53
			InitiatedL1EventGUID: deposit.Event.GUID,
			GasLimit:             deposit.GasLimit,
			Tx:                   deposit.Tx,
		}
	}
	if len(ctcTxDepositEvents) > 0 {
		if err := db.BridgeTransactions.StoreL1TransactionDeposits(transactionDeposits); err != nil {
			return err
		}
Hamdi Allam's avatar
Hamdi Allam committed
54
		metrics.RecordL1TransactionDeposits(len(transactionDeposits))
Hamdi Allam's avatar
Hamdi Allam committed
55 56 57
	}

	// (2) L1CrossDomainMessenger
58
	crossDomainSentMessages, err := contracts.CrossDomainMessengerSentMessageEvents("l1", l1Contracts.L1CrossDomainMessengerProxy, db, fromHeight, toHeight)
Hamdi Allam's avatar
Hamdi Allam committed
59 60 61
	if err != nil {
		return err
	}
Hamdi Allam's avatar
Hamdi Allam committed
62 63 64 65
	if len(crossDomainSentMessages) > 0 {
		log.Info("detected legacy sent messages", "size", len(crossDomainSentMessages))
	}

Hamdi Allam's avatar
Hamdi Allam committed
66
	sentMessages := make(map[logKey]*contracts.CrossDomainMessengerSentMessageEvent, len(crossDomainSentMessages))
Hamdi Allam's avatar
Hamdi Allam committed
67
	bridgeMessages := make([]database.L1BridgeMessage, len(crossDomainSentMessages))
Hamdi Allam's avatar
Hamdi Allam committed
68 69 70 71 72 73 74 75 76 77 78
	for i := range crossDomainSentMessages {
		sentMessage := crossDomainSentMessages[i]
		sentMessages[logKey{sentMessage.Event.BlockHash, sentMessage.Event.LogIndex}] = &sentMessage

		// extract the deposit hash from the previous TransactionDepositedEvent
		ctcTxDeposit, ok := ctcTxDeposits[logKey{sentMessage.Event.BlockHash, sentMessage.Event.LogIndex - 1}]
		if !ok {
			log.Error("missing transaction deposit for cross domain message", "tx_hash", sentMessage.Event.TransactionHash.String())
			return fmt.Errorf("missing preceding TransactionEnqueued for SentMessage event. tx_hash = %s", sentMessage.Event.TransactionHash.String())
		}

Hamdi Allam's avatar
Hamdi Allam committed
79
		bridgeMessages[i] = database.L1BridgeMessage{TransactionSourceHash: ctcTxDeposit.TxHash, BridgeMessage: sentMessage.BridgeMessage}
Hamdi Allam's avatar
Hamdi Allam committed
80
	}
Hamdi Allam's avatar
Hamdi Allam committed
81 82
	if len(bridgeMessages) > 0 {
		if err := db.BridgeMessages.StoreL1BridgeMessages(bridgeMessages); err != nil {
Hamdi Allam's avatar
Hamdi Allam committed
83 84
			return err
		}
Hamdi Allam's avatar
Hamdi Allam committed
85
		metrics.RecordL1CrossDomainSentMessages(len(bridgeMessages))
Hamdi Allam's avatar
Hamdi Allam committed
86 87 88
	}

	// (3) L1StandardBridge
89
	initiatedBridges, err := contracts.L1StandardBridgeLegacyDepositInitiatedEvents(l1Contracts.L1StandardBridgeProxy, db, fromHeight, toHeight)
Hamdi Allam's avatar
Hamdi Allam committed
90 91 92
	if err != nil {
		return err
	}
Hamdi Allam's avatar
Hamdi Allam committed
93 94 95 96
	if len(initiatedBridges) > 0 {
		log.Info("detected iegacy bridge deposits", "size", len(initiatedBridges))
	}

Hamdi Allam's avatar
Hamdi Allam committed
97 98
	bridgedTokens := make(map[common.Address]int)
	bridgeDeposits := make([]database.L1BridgeDeposit, len(initiatedBridges))
Hamdi Allam's avatar
Hamdi Allam committed
99 100 101 102 103 104 105 106 107
	for i := range initiatedBridges {
		initiatedBridge := initiatedBridges[i]

		// extract the cross domain message hash & deposit source hash from the following events
		// Unlike bedrock, the bridge events are emitted AFTER sending the cross domain message
		// 	- Event Flow: TransactionEnqueued -> SentMessage -> DepositInitiated
		sentMessage, ok := sentMessages[logKey{initiatedBridge.Event.BlockHash, initiatedBridge.Event.LogIndex - 1}]
		if !ok {
			log.Error("missing cross domain message for bridge transfer", "tx_hash", initiatedBridge.Event.TransactionHash.String())
108
			return fmt.Errorf("expected SentMessage preceding DepositInitiated event. tx_hash = %s", initiatedBridge.Event.TransactionHash.String())
Hamdi Allam's avatar
Hamdi Allam committed
109 110 111 112
		}
		ctcTxDeposit, ok := ctcTxDeposits[logKey{initiatedBridge.Event.BlockHash, initiatedBridge.Event.LogIndex - 2}]
		if !ok {
			log.Error("missing transaction deposit for bridge transfer", "tx_hash", initiatedBridge.Event.TransactionHash.String())
113
			return fmt.Errorf("expected TransactionEnqueued preceding DepostInitiated event. tx_hash = %s", initiatedBridge.Event.TransactionHash.String())
Hamdi Allam's avatar
Hamdi Allam committed
114 115 116
		}

		initiatedBridge.BridgeTransfer.CrossDomainMessageHash = &sentMessage.BridgeMessage.MessageHash
Hamdi Allam's avatar
Hamdi Allam committed
117 118
		bridgedTokens[initiatedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++
		bridgeDeposits[i] = database.L1BridgeDeposit{
Hamdi Allam's avatar
Hamdi Allam committed
119 120 121 122
			TransactionSourceHash: ctcTxDeposit.TxHash,
			BridgeTransfer:        initiatedBridge.BridgeTransfer,
		}
	}
Hamdi Allam's avatar
Hamdi Allam committed
123 124
	if len(bridgeDeposits) > 0 {
		if err := db.BridgeTransfers.StoreL1BridgeDeposits(bridgeDeposits); err != nil {
Hamdi Allam's avatar
Hamdi Allam committed
125 126
			return err
		}
Hamdi Allam's avatar
Hamdi Allam committed
127 128 129
		for tokenAddr, size := range bridgedTokens {
			metrics.RecordL1InitiatedBridgeTransfers(tokenAddr, size)
		}
Hamdi Allam's avatar
Hamdi Allam committed
130 131 132 133 134 135
	}

	// a-ok!
	return nil
}

136 137
// LegacyL2ProcessInitiatedEvents will query the data for bridge events within the specified block range
// according the pre-bedrock protocol. This follows:
138
//  1. L2CrossDomainMessenger - The LegacyMessagePasser contract cannot be used as entrypoint to bridge transactions from L2. The protocol
139 140
//     only allows the L2CrossDomainMessenger as the sole sender when relaying a bridged message.
//  2. L2StandardBridge
Hamdi Allam's avatar
Hamdi Allam committed
141
func LegacyL2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L2Metricer, l2Contracts config.L2Contracts, fromHeight, toHeight *big.Int) error {
142
	// (1) L2CrossDomainMessenger
143
	crossDomainSentMessages, err := contracts.CrossDomainMessengerSentMessageEvents("l2", l2Contracts.L2CrossDomainMessenger, db, fromHeight, toHeight)
Hamdi Allam's avatar
Hamdi Allam committed
144 145 146
	if err != nil {
		return err
	}
Hamdi Allam's avatar
Hamdi Allam committed
147 148 149 150
	if len(crossDomainSentMessages) > 0 {
		log.Info("detected legacy transaction withdrawals (via L2CrossDomainMessenger)", "size", len(crossDomainSentMessages))
	}

Hamdi Allam's avatar
Hamdi Allam committed
151
	sentMessages := make(map[logKey]*contracts.CrossDomainMessengerSentMessageEvent, len(crossDomainSentMessages))
Hamdi Allam's avatar
Hamdi Allam committed
152 153
	bridgeMessages := make([]database.L2BridgeMessage, len(crossDomainSentMessages))
	transactionWithdrawals := make([]database.L2TransactionWithdrawal, len(crossDomainSentMessages))
Hamdi Allam's avatar
Hamdi Allam committed
154 155 156 157
	for i := range crossDomainSentMessages {
		sentMessage := crossDomainSentMessages[i]
		sentMessages[logKey{sentMessage.Event.BlockHash, sentMessage.Event.LogIndex}] = &sentMessage

158 159
		// To ensure consistency in the schema, we duplicate this as the "root" transaction withdrawal. The storage key in the message
		// passer contract is sha3(calldata + sender). The sender always being the L2CrossDomainMessenger pre-bedrock.
160
		withdrawalHash := crypto.Keccak256Hash(append(sentMessage.MessageCalldata, l2Contracts.L2CrossDomainMessenger[:]...))
Hamdi Allam's avatar
Hamdi Allam committed
161
		transactionWithdrawals[i] = database.L2TransactionWithdrawal{
162
			WithdrawalHash:       withdrawalHash,
Hamdi Allam's avatar
Hamdi Allam committed
163 164 165 166 167 168 169 170 171 172 173
			InitiatedL2EventGUID: sentMessage.Event.GUID,
			Nonce:                sentMessage.BridgeMessage.Nonce,
			GasLimit:             sentMessage.BridgeMessage.GasLimit,
			Tx: database.Transaction{
				FromAddress: sentMessage.BridgeMessage.Tx.FromAddress,
				ToAddress:   sentMessage.BridgeMessage.Tx.ToAddress,
				Amount:      big.NewInt(0),
				Data:        sentMessage.BridgeMessage.Tx.Data,
				Timestamp:   sentMessage.Event.Timestamp,
			},
		}
174

Hamdi Allam's avatar
Hamdi Allam committed
175
		bridgeMessages[i] = database.L2BridgeMessage{
176
			TransactionWithdrawalHash: withdrawalHash,
177 178
			BridgeMessage:             sentMessage.BridgeMessage,
		}
Hamdi Allam's avatar
Hamdi Allam committed
179
	}
Hamdi Allam's avatar
Hamdi Allam committed
180 181
	if len(bridgeMessages) > 0 {
		if err := db.BridgeTransactions.StoreL2TransactionWithdrawals(transactionWithdrawals); err != nil {
Hamdi Allam's avatar
Hamdi Allam committed
182 183
			return err
		}
Hamdi Allam's avatar
Hamdi Allam committed
184
		if err := db.BridgeMessages.StoreL2BridgeMessages(bridgeMessages); err != nil {
Hamdi Allam's avatar
Hamdi Allam committed
185 186
			return err
		}
Hamdi Allam's avatar
Hamdi Allam committed
187 188
		metrics.RecordL2TransactionWithdrawals(len(transactionWithdrawals))
		metrics.RecordL2CrossDomainSentMessages(len(bridgeMessages))
Hamdi Allam's avatar
Hamdi Allam committed
189 190 191
	}

	// (2) L2StandardBridge
192
	initiatedBridges, err := contracts.L2StandardBridgeLegacyWithdrawalInitiatedEvents(l2Contracts.L2StandardBridge, db, fromHeight, toHeight)
Hamdi Allam's avatar
Hamdi Allam committed
193 194 195
	if err != nil {
		return err
	}
Hamdi Allam's avatar
Hamdi Allam committed
196 197 198 199
	if len(initiatedBridges) > 0 {
		log.Info("detected legacy bridge withdrawals", "size", len(initiatedBridges))
	}

Hamdi Allam's avatar
Hamdi Allam committed
200
	bridgedTokens := make(map[common.Address]int)
Hamdi Allam's avatar
Hamdi Allam committed
201 202 203 204 205 206 207 208 209
	l2BridgeWithdrawals := make([]database.L2BridgeWithdrawal, len(initiatedBridges))
	for i := range initiatedBridges {
		initiatedBridge := initiatedBridges[i]

		// extract the cross domain message hash & deposit source hash from the following events
		// Unlike bedrock, the bridge events are emitted AFTER sending the cross domain message
		// 	- Event Flow: TransactionEnqueued -> SentMessage -> DepositInitiated
		sentMessage, ok := sentMessages[logKey{initiatedBridge.Event.BlockHash, initiatedBridge.Event.LogIndex - 1}]
		if !ok {
Hamdi Allam's avatar
Hamdi Allam committed
210
			log.Error("expected SentMessage preceding DepositInitiated event", "tx_hash", initiatedBridge.Event.TransactionHash.String())
Hamdi Allam's avatar
Hamdi Allam committed
211 212 213
			return fmt.Errorf("expected SentMessage preceding DepositInitiated event. tx_hash = %s", initiatedBridge.Event.TransactionHash)
		}
		initiatedBridge.BridgeTransfer.CrossDomainMessageHash = &sentMessage.BridgeMessage.MessageHash
Hamdi Allam's avatar
Hamdi Allam committed
214 215

		bridgedTokens[initiatedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++
Hamdi Allam's avatar
Hamdi Allam committed
216 217 218 219 220 221 222 223 224
		l2BridgeWithdrawals[i] = database.L2BridgeWithdrawal{
			TransactionWithdrawalHash: sentMessage.BridgeMessage.MessageHash,
			BridgeTransfer:            initiatedBridge.BridgeTransfer,
		}
	}
	if len(l2BridgeWithdrawals) > 0 {
		if err := db.BridgeTransfers.StoreL2BridgeWithdrawals(l2BridgeWithdrawals); err != nil {
			return err
		}
Hamdi Allam's avatar
Hamdi Allam committed
225 226 227
		for tokenAddr, size := range bridgedTokens {
			metrics.RecordL2InitiatedBridgeTransfers(tokenAddr, size)
		}
Hamdi Allam's avatar
Hamdi Allam committed
228 229 230 231 232 233 234 235
	}

	// a-ok
	return nil
}

// Legacy Bridge Finalization

236
// LegacyL1ProcessFinalizedBridgeEvents will query for bridge events within the specified block range
Hamdi Allam's avatar
Hamdi Allam committed
237
// according to the pre-bedrock protocol. This follows:
238 239
//  1. L1CrossDomainMessenger
//  2. L1StandardBridge
Hamdi Allam's avatar
Hamdi Allam committed
240
func LegacyL1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L1Metricer, l1Client node.EthClient, l1Contracts config.L1Contracts, fromHeight, toHeight *big.Int) error {
Hamdi Allam's avatar
Hamdi Allam committed
241 242
	// (1) L1CrossDomainMessenger -> This is the root-most contract from which bridge events are finalized since withdrawals must be initiated from the
	// L2CrossDomainMessenger. Since there's no two-step withdrawal process, we mark the transaction as proven/finalized in the same step
243
	crossDomainRelayedMessages, err := contracts.CrossDomainMessengerRelayedMessageEvents("l1", l1Contracts.L1CrossDomainMessengerProxy, db, fromHeight, toHeight)
Hamdi Allam's avatar
Hamdi Allam committed
244 245 246
	if err != nil {
		return err
	}
Hamdi Allam's avatar
Hamdi Allam committed
247 248 249
	if len(crossDomainRelayedMessages) > 0 {
		log.Info("detected relayed messages", "size", len(crossDomainRelayedMessages))
	}
Hamdi Allam's avatar
Hamdi Allam committed
250 251 252 253 254 255 256 257 258 259 260 261 262 263

	skippedPreRegenesisMessages := 0
	for i := range crossDomainRelayedMessages {
		relayedMessage := crossDomainRelayedMessages[i]
		message, err := db.BridgeMessages.L2BridgeMessage(relayedMessage.MessageHash)
		if err != nil {
			return err
		} else if message == nil {
			// Before surfacing an error about a missing withdrawal, we need to handle an edge case
			// for OP-Mainnet pre-regensis withdrawals that no longer exist on L2.
			tx, err := l1Client.TxByHash(relayedMessage.Event.TransactionHash)
			if err != nil {
				return err
			} else if tx == nil {
Hamdi Allam's avatar
Hamdi Allam committed
264 265
				log.Error("missing tx for relayed message", "tx_hash", relayedMessage.Event.TransactionHash.String())
				return fmt.Errorf("missing tx for relayed message. tx_hash = %s", relayedMessage.Event.TransactionHash.String())
Hamdi Allam's avatar
Hamdi Allam committed
266 267 268 269 270
			}

			relayMessageData := tx.Data()[4:]
			inputs, err := contracts.CrossDomainMessengerLegacyRelayMessageEncoding.Inputs.Unpack(relayMessageData)
			if err != nil || inputs == nil {
Hamdi Allam's avatar
Hamdi Allam committed
271 272
				log.Error("failed to extract XDomainCallData from relayMessage transaction", "err", err, "tx_hash", relayedMessage.Event.TransactionHash.String())
				return fmt.Errorf("unable to extract XDomainCallData from relayMessage transaction. err = %w. tx_hash = %s", err, relayedMessage.Event.TransactionHash.String())
Hamdi Allam's avatar
Hamdi Allam committed
273 274 275 276 277 278 279 280 281 282
			}

			// NOTE: Since OP-Mainnet is the only network to go through a regensis we can simply harcode the
			// the starting message nonce at genesis (100k). Any relayed withdrawal on L1 with a lesser nonce
			// is a clear indicator of a pre-regenesis withdrawal.
			if inputs[3].(*big.Int).Int64() < 100_000 {
				// skip pre-regenesis withdrawals
				skippedPreRegenesisMessages++
				continue
			} else {
Hamdi Allam's avatar
Hamdi Allam committed
283 284
				log.Error("missing indexed legacy L2CrossDomainMessenger message", "tx_hash", relayedMessage.Event.TransactionHash.String())
				return fmt.Errorf("missing indexed L2CrossDomainMessager message. tx_hash %s", relayedMessage.Event.TransactionHash.String())
Hamdi Allam's avatar
Hamdi Allam committed
285 286 287 288 289
			}
		}

		// Mark the associated tx withdrawal as proven/finalized with the same event
		if err := db.BridgeTransactions.MarkL2TransactionWithdrawalProvenEvent(relayedMessage.MessageHash, relayedMessage.Event.GUID); err != nil {
Hamdi Allam's avatar
Hamdi Allam committed
290
			log.Error("failed to mark withdrawal as proven", "err", err)
Hamdi Allam's avatar
Hamdi Allam committed
291 292 293
			return err
		}
		if err := db.BridgeTransactions.MarkL2TransactionWithdrawalFinalizedEvent(relayedMessage.MessageHash, relayedMessage.Event.GUID, true); err != nil {
Hamdi Allam's avatar
Hamdi Allam committed
294
			log.Error("failed to mark withdrawal as finalzed", "err", err)
Hamdi Allam's avatar
Hamdi Allam committed
295 296 297
			return err
		}
		if err := db.BridgeMessages.MarkRelayedL2BridgeMessage(relayedMessage.MessageHash, relayedMessage.Event.GUID); err != nil {
Hamdi Allam's avatar
Hamdi Allam committed
298
			log.Error("failed to relay cross domain message", "err", err)
Hamdi Allam's avatar
Hamdi Allam committed
299 300 301
			return err
		}
	}
Hamdi Allam's avatar
Hamdi Allam committed
302 303 304 305 306
	if len(crossDomainRelayedMessages) > 0 {
		metrics.RecordL1ProvenWithdrawals(len(crossDomainRelayedMessages))
		metrics.RecordL1FinalizedWithdrawals(len(crossDomainRelayedMessages))
		metrics.RecordL1CrossDomainRelayedMessages(len(crossDomainRelayedMessages))
	}
Hamdi Allam's avatar
Hamdi Allam committed
307 308 309
	if skippedPreRegenesisMessages > 0 {
		// Logged as a warning just for visibility
		log.Warn("skipped pre-regensis relayed L2CrossDomainMessenger withdrawals", "size", skippedPreRegenesisMessages)
Hamdi Allam's avatar
Hamdi Allam committed
310 311
	}

312
	// (2) L2StandardBridge -- no-op for now as there's nothing actionable to do here besides
Hamdi Allam's avatar
Hamdi Allam committed
313 314 315
	// santiy checks which is not important for legacy code. Not worth extra code pre-bedrock.
	// The message status is already tracked via the relayed bridge messed through the cross domain messenger.
	//  - NOTE: This means we dont increment metrics for finalized bridge transfers
Hamdi Allam's avatar
Hamdi Allam committed
316 317 318 319 320

	// a-ok!
	return nil
}

321
// LegacyL2ProcessFinalizedBridgeEvents will query for bridge events within the specified block range
Hamdi Allam's avatar
Hamdi Allam committed
322
// according to the pre-bedrock protocol. This follows:
323 324
//  1. L2CrossDomainMessenger
//  2. L2StandardBridge
Hamdi Allam's avatar
Hamdi Allam committed
325
func LegacyL2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L2Metricer, l2Contracts config.L2Contracts, fromHeight, toHeight *big.Int) error {
Hamdi Allam's avatar
Hamdi Allam committed
326
	// (1) L2CrossDomainMessenger
327
	crossDomainRelayedMessages, err := contracts.CrossDomainMessengerRelayedMessageEvents("l2", l2Contracts.L2CrossDomainMessenger, db, fromHeight, toHeight)
Hamdi Allam's avatar
Hamdi Allam committed
328 329 330
	if err != nil {
		return err
	}
Hamdi Allam's avatar
Hamdi Allam committed
331 332 333
	if len(crossDomainRelayedMessages) > 0 {
		log.Info("detected relayed legacy messages", "size", len(crossDomainRelayedMessages))
	}
Hamdi Allam's avatar
Hamdi Allam committed
334 335 336 337 338 339 340

	for i := range crossDomainRelayedMessages {
		relayedMessage := crossDomainRelayedMessages[i]
		message, err := db.BridgeMessages.L1BridgeMessage(relayedMessage.MessageHash)
		if err != nil {
			return err
		} else if message == nil {
Hamdi Allam's avatar
Hamdi Allam committed
341 342
			log.Error("missing indexed legacy L1CrossDomainMessenger message", "tx_hash", relayedMessage.Event.TransactionHash.String())
			return fmt.Errorf("missing indexed L1CrossDomainMessager message. tx_hash = %s", relayedMessage.Event.TransactionHash.String())
Hamdi Allam's avatar
Hamdi Allam committed
343 344 345
		}

		if err := db.BridgeMessages.MarkRelayedL1BridgeMessage(relayedMessage.MessageHash, relayedMessage.Event.GUID); err != nil {
Hamdi Allam's avatar
Hamdi Allam committed
346
			log.Error("failed to relay cross domain message", "err", err)
Hamdi Allam's avatar
Hamdi Allam committed
347 348 349
			return err
		}
	}
Hamdi Allam's avatar
Hamdi Allam committed
350 351 352
	if len(crossDomainRelayedMessages) > 0 {
		metrics.RecordL2CrossDomainRelayedMessages(len(crossDomainRelayedMessages))
	}
Hamdi Allam's avatar
Hamdi Allam committed
353

354
	// (2) L2StandardBridge -- no-op for now as there's nothing actionable to do here besides
Hamdi Allam's avatar
Hamdi Allam committed
355 356 357
	// santiy checks which is not important for legacy code. Not worth the extra code pre-bedorck.
	// The message status is already tracked via the relayed bridge messed through the cross domain messenger.
	//  - NOTE: This means we dont increment metrics for finalized bridge transfers
Hamdi Allam's avatar
Hamdi Allam committed
358 359 360 361

	// a-ok!
	return nil
}