diff --git a/packages/contracts/contracts/optimistic-ethereum/OVM/bridge/messaging/OVM_L1CustomCrossDomainMessenger.sol b/packages/contracts/contracts/optimistic-ethereum/OVM/bridge/messaging/OVM_L1CustomCrossDomainMessenger.sol new file mode 100644 index 000000000000..d8072aaf834d --- /dev/null +++ b/packages/contracts/contracts/optimistic-ethereum/OVM/bridge/messaging/OVM_L1CustomCrossDomainMessenger.sol @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: MIT +pragma solidity >0.5.0 <0.8.0; +pragma experimental ABIEncoderV2; + +/* Library Imports */ +import { Lib_OVMCodec } from "../../../libraries/codec/Lib_OVMCodec.sol"; +import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressResolver.sol"; +import { Lib_AddressManager } from "../../../libraries/resolver/Lib_AddressManager.sol"; +import { Lib_SecureMerkleTrie } from "../../../libraries/trie/Lib_SecureMerkleTrie.sol"; + +/* Interface Imports */ +import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol"; +import { iOVM_CanonicalTransactionChain } from "../../../iOVM/chain/iOVM_CanonicalTransactionChain.sol"; +import { iOVM_StateCommitmentChain } from "../../../iOVM/chain/iOVM_StateCommitmentChain.sol"; + +/* Contract Imports */ +import { Abs_BaseCrossDomainMessenger } from "./Abs_BaseCrossDomainMessenger.sol"; + +/** + * @title OVM_L1CrossDomainMessenger + * @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages from L2 onto L1. + * In the event that a message sent from L1 to L2 is rejected for exceeding the L2 epoch gas limit, it can be resubmitted + * via this contract's replay function. + * + * Compiler used: solc + * Runtime target: EVM + */ +contract OVM_L1CrossDomainMessenger is iOVM_L1CrossDomainMessenger, Abs_BaseCrossDomainMessenger, Lib_AddressResolver { + + /*************** + * Constructor * + ***************/ + + /** + * Pass a default zero address to the address resolver. This will be updated when initialized. + */ + constructor() + Lib_AddressResolver(address(0)) + {} + + /** + * @param _libAddressManager Address of the Address Manager. + */ + function initialize( + address _libAddressManager + ) + public + { + require(address(libAddressManager) == address(0), "L1CrossDomainMessenger already intialized."); + libAddressManager = Lib_AddressManager(_libAddressManager); + xDomainMsgSender = DEFAULT_XDOMAIN_SENDER; + } + + + /********************** + * Function Modifiers * + **********************/ + + /** + * Modifier to enforce that, if configured, only the OVM_L2MessageRelayer contract may successfully call a method. + */ + modifier onlyRelayer() { + address relayer = resolve("OVM_L2MessageRelayer"); + if (relayer != address(0)) { + require( + msg.sender == relayer, + "Only OVM_L2MessageRelayer can relay L2-to-L1 messages." + ); + } + _; + } + + + /******************** + * Public Functions * + ********************/ + + /** + * Relays a cross domain message to a contract. + * @inheritdoc iOVM_L1CrossDomainMessenger + */ + function relayMessage( + address _target, + address _sender, + bytes memory _message, + uint256 _messageNonce, + L2MessageInclusionProof memory _proof + ) + override + public + onlyRelayer() + { + bytes memory xDomainCalldata = _getXDomainCalldata( + _target, + _sender, + _message, + _messageNonce + ); + + require( + _verifyXDomainMessage( + xDomainCalldata, + _proof + ) == true, + "Provided message could not be verified." + ); + + bytes32 xDomainCalldataHash = keccak256(xDomainCalldata); + + require( + successfulMessages[xDomainCalldataHash] == false, + "Provided message has already been received." + ); + + xDomainMsgSender = _sender; + (bool success, ) = _target.call(_message); + xDomainMsgSender = DEFAULT_XDOMAIN_SENDER; + + // Mark the message as received if the call was successful. Ensures that a message can be + // relayed multiple times in the case that the call reverted. + if (success == true) { + successfulMessages[xDomainCalldataHash] = true; + emit RelayedMessage(xDomainCalldataHash); + } + + // Store an identifier that can be used to prove that the given message was relayed by some + // user. Gives us an easy way to pay relayers for their work. + bytes32 relayId = keccak256( + abi.encodePacked( + xDomainCalldata, + msg.sender, + block.number + ) + ); + relayedMessages[relayId] = true; + } + + /** + * Replays a cross domain message to the target messenger. + * @inheritdoc iOVM_L1CrossDomainMessenger + */ + function replayMessage( + address _target, + address _sender, + bytes memory _message, + uint256 _messageNonce, + uint32 _gasLimit + ) + override + public + { + bytes memory xDomainCalldata = _getXDomainCalldata( + _target, + _sender, + _message, + _messageNonce + ); + + require( + sentMessages[keccak256(xDomainCalldata)] == true, + "Provided message has not already been sent." + ); + + _sendXDomainMessage(xDomainCalldata, _gasLimit); + } + + + /********************** + * Internal Functions * + **********************/ + + /** + * Verifies that the given message is valid. + * @param _xDomainCalldata Calldata to verify. + * @param _proof Inclusion proof for the message. + * @return Whether or not the provided message is valid. + */ + function _verifyXDomainMessage( + bytes memory _xDomainCalldata, + L2MessageInclusionProof memory _proof + ) + internal + view + returns ( + bool + ) + { + return ( + _verifyStateRootProof(_proof) + && _verifyStorageProof(_xDomainCalldata, _proof) + ); + } + + /** + * Verifies that the state root within an inclusion proof is valid. + * @param _proof Message inclusion proof. + * @return Whether or not the provided proof is valid. + */ + function _verifyStateRootProof( + L2MessageInclusionProof memory _proof + ) + internal + view + returns ( + bool + ) + { + iOVM_StateCommitmentChain ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain")); + + return ( + ovmStateCommitmentChain.verifyStateCommitment( + _proof.stateRoot, + _proof.stateRootBatchHeader, + _proof.stateRootProof + ) + ); + } + + /** + * Verifies that the storage proof within an inclusion proof is valid. + * @param _xDomainCalldata Encoded message calldata. + * @param _proof Message inclusion proof. + * @return Whether or not the provided proof is valid. + */ + function _verifyStorageProof( + bytes memory _xDomainCalldata, + L2MessageInclusionProof memory _proof + ) + internal + view + returns ( + bool + ) + { + bytes32 storageKey = keccak256( + abi.encodePacked( + keccak256( + abi.encodePacked( + _xDomainCalldata, + resolve("OVM_L2CrossDomainMessenger") + ) + ), + uint256(0) + ) + ); + + ( + bool exists, + bytes memory encodedMessagePassingAccount + ) = Lib_SecureMerkleTrie.get( + abi.encodePacked(0x4200000000000000000000000000000000000000), + _proof.stateTrieWitness, + _proof.stateRoot + ); + + require( + exists == true, + "Message passing predeploy has not been initialized or invalid proof provided." + ); + + Lib_OVMCodec.EVMAccount memory account = Lib_OVMCodec.decodeEVMAccount( + encodedMessagePassingAccount + ); + + return Lib_SecureMerkleTrie.verifyInclusionProof( + abi.encodePacked(storageKey), + abi.encodePacked(uint8(1)), + _proof.storageTrieWitness, + account.storageRoot + ); + } + + /** + * Sends a cross domain message. + * @param _message Message to send. + * @param _gasLimit OVM gas limit for the message. + */ + function _sendXDomainMessage( + bytes memory _message, + uint256 _gasLimit + ) + override + internal + { + revert("Sending via this messenger is disabled"); + } +} diff --git a/packages/contracts/deploy/017-OVM_L1CustomCrossDomainMessenger.deploy.ts b/packages/contracts/deploy/017-OVM_L1CustomCrossDomainMessenger.deploy.ts new file mode 100644 index 000000000000..a06e230b432c --- /dev/null +++ b/packages/contracts/deploy/017-OVM_L1CustomCrossDomainMessenger.deploy.ts @@ -0,0 +1,62 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { getDeployedContract } from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager', + { + signerOrProvider: deployer, + } + ) + + const result = await deploy('OVM_L1CustomCrossDomainMessenger', { + from: deployer, + args: [], + log: true, + }) + + if (!result.newlyDeployed) { + return + } + + const OVM_L1CustomCrossDomainMessenger = await getDeployedContract( + hre, + 'OVM_L1CustomCrossDomainMessenger', + { + signerOrProvider: deployer, + } + ) + + // NOTE: this initialization is *not* technically required (we only need to initialize the proxy) + // but it feels safer to initialize this anyway. Otherwise someone else could come along and + // initialize this. + await OVM_L1CustomCrossDomainMessenger.initialize(Lib_AddressManager.address) + + const libAddressManager = await OVM_L1CustomCrossDomainMessenger.libAddressManager() + if (libAddressManager !== Lib_AddressManager.address) { + throw new Error( + `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + + `OVM_L1CustomCrossDomainMessenger could not be succesfully initialized.\n` + + `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + + `Actual address after initialization: ${libAddressManager}\n` + + `This could indicate a compromised deployment.` + ) + } + + await Lib_AddressManager.setAddress( + 'OVM_L1CustomCrossDomainMessenger', + result.address + ) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_L1CustomCrossDomainMessenger'] + +export default deployFn diff --git a/packages/contracts/deploy/017-finalize.ts b/packages/contracts/deploy/018-finalize.ts similarity index 100% rename from packages/contracts/deploy/017-finalize.ts rename to packages/contracts/deploy/018-finalize.ts diff --git a/packages/omgx/alt_messenger/README.md b/packages/omgx/alt_messenger/README.md index 15d140b7d4b3..37b3d743eb2e 100644 --- a/packages/omgx/alt_messenger/README.md +++ b/packages/omgx/alt_messenger/README.md @@ -19,7 +19,6 @@ ADDRESS_MANAGER_ADDRESS=
L1_NODE_WEB3_URL= L2_NODE_WEB3_URL= L1_WALLET_KEY= -L1_MESSENGER_ADDRESS= L1_TARGET= ``` diff --git a/packages/omgx/alt_messenger/relayer_service/.env.example b/packages/omgx/alt_messenger/relayer_service/.env.example index e7cf1b8da304..b980fed73904 100644 --- a/packages/omgx/alt_messenger/relayer_service/.env.example +++ b/packages/omgx/alt_messenger/relayer_service/.env.example @@ -2,5 +2,4 @@ ADDRESS_MANAGER_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3 L1_NODE_WEB3_URL=http://localhost:9545 L2_NODE_WEB3_URL=http://localhost:8545 L1_WALLET_KEY=0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 -L1_MESSENGER_ADDRESS=0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf L1_TARGET=0x0 \ No newline at end of file diff --git a/packages/omgx/alt_messenger/relayer_service/Dockerfile.message_relayer b/packages/omgx/alt_messenger/relayer_service/Dockerfile.message_relayer new file mode 100644 index 000000000000..6abf38e120ad --- /dev/null +++ b/packages/omgx/alt_messenger/relayer_service/Dockerfile.message_relayer @@ -0,0 +1,24 @@ +FROM node:14-buster as base + +RUN apt-get update && apt-get install -y bash curl jq + +FROM base as build + +RUN apt-get update && apt-get install -y bash git python build-essential + +ADD . /opt/optimism-ts-services +RUN cd /opt/optimism-ts-services && yarn install && yarn build + +FROM base + +RUN apt-get update && apt-get install -y bash curl jq + +COPY --from=build /opt/optimism-ts-services /opt/optimism-ts-services + +COPY wait-for-l1-and-l2.sh /opt/ +RUN chmod +x /opt/wait-for-l1-and-l2.sh + +RUN ln -s /opt/optimism-ts-services/exec/run-message-relayer.js /usr/local/bin/ +RUN chmod +x /usr/local/bin/run-message-relayer.js + +ENTRYPOINT ["/opt/wait-for-l1-and-l2.sh", "run-message-relayer.js"] \ No newline at end of file diff --git a/packages/omgx/alt_messenger/relayer_service/src/exec/run.ts b/packages/omgx/alt_messenger/relayer_service/src/exec/run.ts index 75ea26bcd20d..b177cc58d35c 100644 --- a/packages/omgx/alt_messenger/relayer_service/src/exec/run.ts +++ b/packages/omgx/alt_messenger/relayer_service/src/exec/run.ts @@ -21,10 +21,6 @@ const main = async () => { 'address-manager-address', env.ADDRESS_MANAGER_ADDRESS ) - const L1_MESSENGER_ADDRESS = config.str( - 'l1-messenger-address', - env.L1_MESSENGER_ADDRESS - ) const L1_TARGET = config.str( 'l1-target', env.L1_TARGET @@ -72,9 +68,6 @@ const main = async () => { if (!ADDRESS_MANAGER_ADDRESS) { throw new Error('Must pass ADDRESS_MANAGER_ADDRESS') } - if (!L1_MESSENGER_ADDRESS) { - throw new Error('Must pass L1_MESSENGER_ADDRESS') - } if (!L1_TARGET) { throw new Error('Must pass L1_TARGET') } @@ -118,7 +111,6 @@ const main = async () => { l1RpcProvider: l1Provider, l2RpcProvider: l2Provider, addressManagerAddress: ADDRESS_MANAGER_ADDRESS, - l1MessengerAddress: L1_MESSENGER_ADDRESS, l1Target: L1_TARGET, l1Wallet: wallet, relayGasLimit: RELAY_GAS_LIMIT, diff --git a/packages/omgx/alt_messenger/relayer_service/src/service.ts b/packages/omgx/alt_messenger/relayer_service/src/service.ts index 0b0b174f0147..091f92af5da4 100644 --- a/packages/omgx/alt_messenger/relayer_service/src/service.ts +++ b/packages/omgx/alt_messenger/relayer_service/src/service.ts @@ -20,8 +20,6 @@ interface MessageRelayerOptions { // within this service. addressManagerAddress: string - l1MessengerAddress: string - l1Target: string // Wallet instance, used to sign and send the L1 relay transactions. @@ -113,9 +111,12 @@ export class MessageRelayerService extends BaseService { }) this.logger.info('Connecting to OVM_L1CrossDomainMessenger...') + const l1MessengerAddress = await this.state.Lib_AddressManager.getAddress( + 'OVM_L1CustomCrossDomainMessenger' + ) this.state.OVM_L1CrossDomainMessenger = loadContract( 'OVM_L1CrossDomainMessenger', - this.options.l1MessengerAddress, + l1MessengerAddress, this.options.l1RpcProvider, ) this.logger.info('Connected to OVM_L1CrossDomainMessenger', { diff --git a/packages/omgx/alt_messenger/relayer_service/wait-for-l1-and-l2.sh b/packages/omgx/alt_messenger/relayer_service/wait-for-l1-and-l2.sh new file mode 100755 index 000000000000..f8be30bf2b47 --- /dev/null +++ b/packages/omgx/alt_messenger/relayer_service/wait-for-l1-and-l2.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright Optimism PBC 2020 +# MIT License +# github.com/ethereum-optimism + +cmd="$@" +JSON='{"jsonrpc":"2.0","id":0,"method":"net_version","params":[]}' + +RETRIES=${RETRIES:-20} +until $(curl --silent --fail \ + --output /dev/null \ + -H "Content-Type: application/json" \ + --data "$JSON" "$L1_NODE_WEB3_URL"); do + sleep 1 + echo "Will wait $((RETRIES--)) more times for $L1_NODE_WEB3_URL to be up..." + + if [ "$RETRIES" -lt 0 ]; then + echo "Timeout waiting for layer one node at $L1_NODE_WEB3_URL" + exit 1 + fi +done +echo "Connected to L1 Node at $L1_NODE_WEB3_URL" + +RETRIES=${RETRIES:-30} +until $(curl --silent --fail \ + --output /dev/null \ + -H "Content-Type: application/json" \ + --data "$JSON" "$L2_NODE_WEB3_URL"); do + sleep 1 + echo "Will wait $((RETRIES--)) more times for $L2_NODE_WEB3_URL to be up..." + + if [ "$RETRIES" -lt 0 ]; then + echo "Timeout waiting for layer two node at $L2_NODE_WEB3_URL" + exit 1 + fi +done +echo "Connected to L2 Node at $L2_NODE_WEB3_URL" + +if [ ! -z "$DEPLOYER_HTTP" ]; then + RETRIES=${RETRIES:-20} + until $(curl --silent --fail \ + --output /dev/null \ + "$DEPLOYER_HTTP/addresses.json"); do + sleep 1 + echo "Will wait $((RETRIES--)) more times for $DEPLOYER_HTTP to be up..." + + if [ "$RETRIES" -lt 0 ]; then + echo "Timeout waiting for contract deployment" + exit 1 + fi + done + echo "Contracts are deployed" + ADDRESS_MANAGER_ADDRESS=$(curl --silent $DEPLOYER_HTTP/addresses.json | jq -r .AddressManager) + exec env \ + ADDRESS_MANAGER_ADDRESS=$ADDRESS_MANAGER_ADDRESS \ + L1_BLOCK_OFFSET=$L1_BLOCK_OFFSET \ + $cmd +else + exec $cmd +fi diff --git a/packages/omgx/wallet/deployment/local/addresses.json b/packages/omgx/wallet/deployment/local/addresses.json index cc9b5b76e792..4a0a8b6bca24 100644 --- a/packages/omgx/wallet/deployment/local/addresses.json +++ b/packages/omgx/wallet/deployment/local/addresses.json @@ -1,11 +1,12 @@ { - "L1LiquidityPool": "0xCcCF885722616E56Ad9A67C74E4b96CFe361FaAb", - "L2LiquidityPool": "0xEFA3B6C1203ED5fF8f4E1f6F7A09dCe529Fb9EbF", - "L1ERC20": "0xd898b4D61cA2b55754e90C3F9D6006d85eefe6Ee", - "L2DepositedERC20": "0x4F53A01556Dc6f120db9a1b4caE786D5f0b5792C", - "L1ERC20Gateway": "0xB569529B9C2c45FB18d9c7c3A67BDaf8A1F1Ee06", + "L1LiquidityPool": "0x6353d6c697cc36446EC727Ae032B518b7FbEc82d", + "L2LiquidityPool": "0x3e4CFaa8730092552d9425575E49bB542e329981", + "L1ERC20": "0x6C024eeE101AdB6b5d211947fD4B7f6182042978", + "L2DepositedERC20": "0x65F72DF8a668BC6272B059BB7F53ADc91066540C", + "L1ERC20Gateway": "0x3C38fd8D4e647b230D006d98793Fa3A0ec60bC41", "l1ETHGatewayAddress": "0x4F53A01556Dc6f120db9a1b4caE786D5f0b5792C", "l1MessengerAddress": "0xA6404B184Ad3f6F41b6472f02ba45f25C6A66d49", - "L2TokenPool": "0x34336b4Ff39B52E5D7879F827EB0e99Bd764947D", - "AtomicSwap": "0x9BD764a33bA117a6bC453422CCD459bc66668B45" + "L2TokenPool": "0xcD46d1D296466e7F2842A718576d49576fe76a9f", + "AtomicSwap": "0xB3FdF320A0bb4b9eBedf4726F0C9Bf49D1268cf9", + "L2ERC721": "0x5bD12f0B56C8973ac98446435E07Df8311Aa362c" } \ No newline at end of file diff --git a/packages/omgx/wallet/test/a_setup.spec.ts b/packages/omgx/wallet/test/a_setup.spec.ts index a96bd467c403..4a85c387083b 100644 --- a/packages/omgx/wallet/test/a_setup.spec.ts +++ b/packages/omgx/wallet/test/a_setup.spec.ts @@ -3,7 +3,7 @@ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; chai.use(chaiAsPromised); import { Contract, ContractFactory, BigNumber, utils } from 'ethers' -import { Direction } from './shared/watcher-utils' +import { Direction, Relayer } from './shared/watcher-utils' import L1ERC20Json from '../artifacts/contracts/L1ERC20.sol/L1ERC20.json' import L1ERC20GatewayJson from '../artifacts/contracts/L1ERC20Gateway.sol/L1ERC20Gateway.json' @@ -103,7 +103,7 @@ describe('System setup', async () => { L1LiquidityPool = await Factory__L1LiquidityPool.deploy( env.watcher.l1.messengerAddress, - "0x247ADeE8E350cBEB05aB73DE88Be07CFbD736b2E" + env.customWatcher.l1.messengerAddress, ) await L1LiquidityPool.deployTransaction.wait() console.log("L1LiquidityPool deployed to:", L1LiquidityPool.address) @@ -444,9 +444,10 @@ describe('System setup', async () => { fastExitAmount, L2DepositedERC20.address ), - Direction.L2ToL1 + Direction.L2ToL1, + Relayer.custom, ) - + const poolInfo = await L2LiquidityPool.poolInfo(L2DepositedERC20.address) expect(poolInfo.accOwnerReward).to.deep.eq(fastExitAmount.mul(15).div(1000)) diff --git a/packages/omgx/wallet/test/shared/env.ts b/packages/omgx/wallet/test/shared/env.ts index 183ac08782bf..e85fb163fac0 100644 --- a/packages/omgx/wallet/test/shared/env.ts +++ b/packages/omgx/wallet/test/shared/env.ts @@ -21,8 +21,10 @@ import { import { initWatcher, + initCustomWatcher, CrossDomainMessagePair, Direction, + Relayer, waitForXDomainTransaction, } from './watcher-utils' @@ -47,6 +49,7 @@ export class OptimismEnv { // The L1 <> L2 State watcher watcher: Watcher + customWatcher: Watcher // The wallets bobl1Wallet: Wallet @@ -66,6 +69,7 @@ export class OptimismEnv { this.L2ETHGateway = args.L2ETHGateway this.l2Messenger = args.l2Messenger this.watcher = args.watcher + this.customWatcher = args.customWatcher this.bobl1Wallet = args.bobl1Wallet this.bobl2Wallet = args.bobl2Wallet this.alicel1Wallet = args.alicel1Wallet @@ -80,6 +84,7 @@ export class OptimismEnv { const addressManager = getAddressManager(bobl1Wallet) const watcher = await initWatcher(l1Provider, l2Provider, addressManager) + const customWatcher = await initCustomWatcher(l1Provider, l2Provider, addressManager) const L1ETHGateway = await getL1ETHGateway(bobl1Wallet, addressManager) const L2ETHGateway = getL2ETHGateway(bobl2Wallet) @@ -111,7 +116,8 @@ export class OptimismEnv { l2Messenger, watcher, - + customWatcher, + bobl1Wallet, bobl2Wallet, alicel1Wallet, @@ -125,8 +131,9 @@ export class OptimismEnv { async waitForXDomainTransaction( tx: Promise | TransactionResponse, - direction: Direction + direction: Direction, + relayer: Relayer = Relayer.origin, ): Promise { - return waitForXDomainTransaction(this.watcher, tx, direction) + return waitForXDomainTransaction(relayer === Relayer.origin ? this.watcher : this.customWatcher, tx, direction) } } diff --git a/packages/omgx/wallet/test/shared/watcher-utils.ts b/packages/omgx/wallet/test/shared/watcher-utils.ts index 361e6a9c673d..08b8b6a3b3b7 100644 --- a/packages/omgx/wallet/test/shared/watcher-utils.ts +++ b/packages/omgx/wallet/test/shared/watcher-utils.ts @@ -26,6 +26,26 @@ export const initWatcher = async ( }) } +export const initCustomWatcher = async ( + l1Provider: JsonRpcProvider, + l2Provider: JsonRpcProvider, + AddressManager: Contract +) => { + + const l1CustomMessengerAddress = await AddressManager.getAddress('OVM_L1CustomCrossDomainMessenger') + + return new Watcher({ + l1: { + provider: l1Provider, + messengerAddress: l1CustomMessengerAddress, + }, + l2: { + provider: l2Provider, + messengerAddress: "0x4200000000000000000000000000000000000007", + }, + }) +} + export interface CrossDomainMessagePair { tx: Transaction receipt: TransactionReceipt @@ -37,10 +57,15 @@ export enum Direction { L2ToL1, } +export enum Relayer { + origin, + custom, +} + export const waitForXDomainTransaction = async ( watcher: Watcher, tx: Promise | TransactionResponse, - direction: Direction + direction: Direction, ): Promise => { // await it if needed