Starting on L2:
- Any account on L2 may call
OVM_L2CrossDomainMessenger.sendMessage()with the information for the L1 message (akaxDomainCalldata)- (ie.
_target,msg.sender,_message) - This data is hashed with the
messageNoncestorage variable, and the hash is store in thesentMessagesmapping (this is not actually used AFAIK) - The
messageNonceis then incremented.
- (ie.
- The
OVM_L2CrossDomainMessengerthen passes thexDomainCalldatatoOVM_L2ToL1MessagePasser.passMessageToL1()- the
xDomainCalldatais hashed withmsg.sender(ie.ovmCaller), and written to thesentMessagesmapping.
- the
Then on L1:
- The
Relayer(and only theRelayer) may callOVM_L1CrossDomainMessenger.relayMessage()providing the raw message inputs and an L2 inclusion proof.- The relayer checks the following things:
- in
_verifyStateRootProof():- checks that the fraud proof window has closed for the batch to which the transaction belongs
- checks that the batch is stored in the
OVM_ChainStorageContainer- (all state changing functions are
onlyOwnerprotected in theOVM_ChainStorageContainer)
- (all state changing functions are
- in
_verifyStorageProof():- checks the proof to confirm that the message data provided is in the
OVM_L2ToL1MessagePasser.sentMessagesmapping
- checks the proof to confirm that the message data provided is in the
- checks that this transaction has not already been written to the
successfulMessagesmapping.
- in
- The address of the L2 call is then written to the
xDomainMessageSenderstate var - the call is then executed
- if it succeeds it is added to the
successfulMessagesand cannot be relayed again - regardless of success, and entry is written to the
relayedMessagesmapping
- The relayer checks the following things:
Then the receiver (in this case SynthetixBridgeToOptimism):
- Checks that the caller is the
OVM_L1CrossDomainMessengerand that thexDomainMessageSenderis thesynthetixBridgeToBaseon L2.