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