diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index 84fe5018f8..f26f04748a 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -46,8 +46,8 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- - name: Restore node_modules
- uses: OffchainLabs/actions/node-modules/restore@main
+ - name: Install node_modules
+ uses: OffchainLabs/actions/node-modules/install@main
- name: Lint sdk
run: |
@@ -91,8 +91,8 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- - name: Restore node_modules
- uses: OffchainLabs/actions/node-modules/restore@main
+ - name: Install node_modules
+ uses: OffchainLabs/actions/node-modules/install@main
- run: yarn audit:ci
@@ -112,8 +112,8 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- - name: Restore node_modules
- uses: OffchainLabs/actions/node-modules/restore@main
+ - name: Install node_modules
+ uses: OffchainLabs/actions/node-modules/install@main
- name: Build
run: |
@@ -174,8 +174,8 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- - name: Restore node_modules
- uses: OffchainLabs/actions/node-modules/restore@main
+ - name: Install node_modules
+ uses: OffchainLabs/actions/node-modules/install@main
- name: Set up the local node
uses: OffchainLabs/actions/run-nitro-test-node@main
diff --git a/.gitignore b/.gitignore
index 037426b618..5182036e87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -244,9 +244,6 @@ instance/
# Scrapy stuff:
.scrapy
-# Sphinx documentation
-docs/_build/
-
# PyBuilder
target/
@@ -312,6 +309,5 @@ packages/arb-bridge-eth/password.txt
packages/issues
packages/**/issues
-docs
json_data
abi
diff --git a/README.md b/README.md
index 09dd971682..0a342a8f1c 100644
--- a/README.md
+++ b/README.md
@@ -1,137 +1,110 @@
# Arbitrum SDK
-TypeScript library for client-side interactions with Arbitrum. Arbitrum SDK provides common helper functionality as well as access to the underlying smart contract interfaces.
+[](https://badge.fury.io/js/@arbitrum%2Fsdk.svg)
+[](https://opensource.org/licenses/Apache-2.0)
-Below is an overview of the Arbitrum SDK functionality. See the [tutorials](https://github.com/OffchainLabs/arbitrum-tutorials) for further examples of how to use these classes.
+A TypeScript library for client-side interactions with Arbitrum. The Arbitrum SDK provides essential helper functionality and direct access to underlying smart contract interfaces, enabling developers to build powerful applications on the Arbitrum network.
-### Quickstart Recipes
+> [!IMPORTANT]
+>
+> This is the code and documentation for `@arbitrum/sdk` v4.
+>
+> If you're looking for v3, check out [this branch](https://github.com/OffchainLabs/arbitrum-sdk/tree/v3).
+>
+> If you're looking to migrate from v3 to v4, check out [this guide](./docs/2-migrate.mdx).
-- ##### Deposit Ether Into Arbitrum
+## Table of Contents
-```ts
-import { getL2Network, EthBridger } from '@arbitrum/sdk'
-
-const l2Network = await getL2Network(
- l2ChainID /** <-- chain id of target Arbitrum chain */
-)
-const ethBridger = new EthBridger(l2Network)
-
-const ethDepositTxResponse = await ethBridger.deposit({
- amount: utils.parseEther('23'),
- l1Signer: l1Signer /** <-- connected ethers-js Wallet */,
- l2Provider: l2Provider /** <--- ethers-js Provider */,
-})
+- [Arbitrum SDK](#arbitrum-sdk)
+ - [Table of Contents](#table-of-contents)
+ - [Overview](#overview)
+ - [Installation](#installation)
+ - [Key Features](#key-features)
+ - [Bridging Assets](#bridging-assets)
+ - [Cross-Chain Messages](#cross-chain-messages)
+ - [Network Configuration](#network-configuration)
+ - [Usage](#usage)
+ - [Running Integration Tests](#running-integration-tests)
+ - [Documentation](#documentation)
+ - [License](#license)
-const ethDepositTxReceipt = await ethDepositTxResponse.wait()
-
-/** check ethDepositTxReceipt.status */
-```
-
-- ##### Redeem an L1 to L2 Message
-
-```ts
-import { L1TransactionReceipt, L1ToL2MessageStatus } from '@arbitrum/sdk'
-
-const l1TxnReceipt = new L1TransactionReceipt(
- txnReceipt /** <-- ethers-js TransactionReceipt of an ethereum tx that triggered an L1 to L2 message (say depositting a token via a bridge) */
-)
-
-const l1ToL2Message = (
- await l1TxnReceipt.getL1ToL2Messages(
- l2Signer /** <-- connected ethers-js Wallet */
- )
-)[0]
-
-const res = await l1ToL2Message.waitForStatus()
-
-if (res.status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) {
- /** Message wasn't auto-redeemed; redeem it now: */
- const response = await l1ToL2Message.redeem()
- const receipt = await response.wait()
-} else if (res.status === L1ToL2MessageStatus.REDEEMED) {
- /** Message succesfully redeeemed */
-}
-```
+## Overview
-- ##### Check if sequencer has included a transaction in L1 data
+Arbitrum SDK simplifies the process of interacting with Arbitrum chains, offering a robust set of tools for asset bridging and cross-chain messaging.
-```ts
-import { L2TransactionReceipt } from '@arbitrum/sdk'
+## Installation
-const l2TxnReceipt = new L2TransactionReceipt(
- txnReceipt /** <-- ethers-js TransactionReceipt of an arbitrum tx */
-)
+```bash
+npm install @arbitrum/sdk
-/** Wait 3 minutes: */
-await new Promise(resolve => setTimeout(resolve, 1000 * 60 * 3000))
+# or
-// if dataIsOnL1, sequencer has posted it and it inherits full rollup/L1 security
-const dataIsOnL1 = await l2TxnReceipt.isDataAvailable(l2Provider, l1Provider)
+yarn add @arbitrum/sdk
```
-### Bridging assets
-
-Arbitrum SDK can be used to bridge assets to/from the rollup chain. The following asset bridgers are currently available:
-
-- EthBridger
-- Erc20Bridger
-
-All asset bridgers have the following methods:
+## Key Features
-- **deposit** - moves assets from the L1 to the L2
-- **depositEstimateGas** - estimates the gas required to do the deposit
-- **withdraw** - moves assets from the L2 to the L1
-- **withdrawEstimateGas** - estimates the gas required to do the withdrawal
- Which accept different parameters depending on the asset bridger type
+### Bridging Assets
-### Cross chain messages
+Arbitrum SDK facilitates the bridging of assets between an Arbitrum chain and its parent chain. Currently supported asset bridgers:
-When assets are moved by the L1 and L2 cross chain messages are sent. The lifecycles of these messages are encapsulated in the classes `L1ToL2Message` and `L2ToL1Message`. These objects are commonly created from the receipts of transactions that send cross chain messages. A cross chain message will eventually result in a transaction being executed on the destination chain, and these message classes provide the ability to wait for that finalizing transaction to occur.
+- `EthBridger`: For bridging ETH to and from an Arbitrum chain (L2 or L3)
+- `Erc20Bridger`: For bridging ERC-20 tokens to and from an Arbitrum chain (L2 or L3)
+- `EthL1L3Bridger`: For bridging ETH to an L3 directly from L1
+- `Erc20L1L3Bridger`: For bridging ERC-20 tokens to an L3 directly from L1
-### Networks
+### Cross-Chain Messages
-Arbitrum SDK comes pre-configured for Mainnet and Sepolia, and their Arbitrum counterparts. However, the networks functionality can be used to register networks for custom Arbitrum instances. Most of the classes in Arbitrum SDK depend on network objects so this must be configured before using other Arbitrum SDK functionality.
+Cross-chain communication is handled through `ParentToChildMessage` and `ChildToParentMessage` classes. These encapsulate the lifecycle of messages sent between chains, typically created from transaction receipts that initiate cross-chain messages.
-### Inbox tools
+### Network Configuration
-As part of normal operation the Arbitrum sequencer will send messages into the rollup chain. However, if the sequencer is unavailable and not posting batches, the inbox tools can be used to force the inclusion of transactions into the rollup chain.
+The SDK comes preconfigured for Arbitrum One, Arbitrum Nova and Arbitrum Sepolia. Custom Arbitrum networks can be registered using `registerCustomArbitrumNetwork`, which is required before utilizing other SDK features.
-### Utils
+## Usage
-- **EventFetcher** - A utility to provide typing for the fetching of events
-- **MultiCaller** - A utility for executing multiple calls as part of a single RPC request. This can be useful for reducing round trips.
-- **constants** - A list of useful Arbitrum related constants
+Here's a basic example of using the SDK to bridge ETH:
-### Run Integration tests
-
-1. First, make sure you have a Nitro test node running. Follow the instructions [here](https://docs.arbitrum.io/node-running/how-tos/local-dev-node).
+```ts
+import { ethers } from 'ethers'
+import { EthBridger, getArbitrumNetwork } from '@arbitrum/sdk'
-2. After the node has started up (that could take up to 20-30 mins), run `yarn gen:network`.
+async function bridgeEth(parentSigner: ethers.Signer, childChainId: number) {
+ const childNetwork = await getArbitrumNetwork(childChainId)
+ const ethBridger = new EthBridger(childNetwork)
-3. Once done, finally run `yarn test:integration` to run the integration tests.
+ const deposit = await ethBridger.deposit({
+ amount: ethers.utils.parseEther('0.1'),
+ parentSigner,
+ })
-Defaults to `Arbitrum Sepolia`, for custom network use `--network` flag.
+ const txReceipt = await deposit.wait()
+ console.log(`Deposit initiated: ${txReceipt.transactionHash}`)
+}
+```
-`Arbitrum Sepolia` expects env var `ARB_KEY` to be prefunded with at least 0.02 ETH, and env var `INFURA_KEY` to be set.
-(see `integration_test/config.ts`)
+For more detailed usage examples and API references, please refer to the [Arbitrum SDK documentation](https://docs.arbitrum.io/sdk).
-### Bridge A Standard Token
+## Running Integration Tests
-Bridging a new token to L2 (i.e., deploying a new token contract) through the standard gateway is done by simply depositing a token that hasn't yet been bridged. This repo includes a script to trigger this initial deposit/deployment:
+1. Set up a Nitro test node by following the instructions [here](https://docs.arbitrum.io/node-running/how-tos/local-dev-node).
+2. Copy `.env.example` to `.env` and update relevant environment variables.
+3. Generate the network configuration against your active Nitro test node:
-1. Clone `arbitrum-sdk`
+ ```sh
+ yarn gen:network
+ ```
-2. `yarn install` (from root)
+4. Execute the integration tests:
-3. Set `PRIVKEY` environment variable (you can use .env) to the key of the account from which you'll be deploying (account should have some balance of the token you're bridging).
+ ```sh
+ yarn test:integration
+ ```
-4. Set MAINNET_RPC environment variable to L1 RPC endpoint (i.e., https://mainnet.infura.io/v3/my-infura-key)
+## Documentation
-5. `yarn bridgeStandardToken`
+For comprehensive guides and API documentation, visit the [Arbitrum SDK Documentation](https://docs.arbitrum.io/sdk).
-Required CL params:
-`networkID`:number — Chain ID of L2 network
-`l1TokenAddress`:string — address of L1 token to be bridged
+## License
-Ex:
-`yarn bridgeStandardToken --networkID 421614 --l1TokenAddress 0xdf032bc4b9dc2782bb09352007d4c57b75160b15 --amount 3`
+Arbitrum SDK is released under the [Apache 2.0 License](LICENSE).
diff --git a/audit-ci.jsonc b/audit-ci.jsonc
index 3b1ff26409..7a87fa4a75 100644
--- a/audit-ci.jsonc
+++ b/audit-ci.jsonc
@@ -104,6 +104,15 @@
// Issue with sol2uml library that generates UML diagrams from Solidity code. Only used at build time.
// from: @offchainlabs/l1-l3-teleport-contracts>@arbitrum/nitro-contracts>sol2uml>axios
// from: @offchainlabs/l1-l3-teleport-contracts>@arbitrum/token-bridge-contracts>@arbitrum/nitro-contracts>sol2uml>axios
- "GHSA-wf5p-g6vw-rhxx"
+ "GHSA-wf5p-g6vw-rhxx",
+ // elliptic
+ // waiting for it to release a fix but low severity so we can ignore it
+ // from: @ethersproject/signing-key>elliptic
+ // https://github.com/advisories/GHSA-49q7-c7j4-3p7m
+ "GHSA-49q7-c7j4-3p7m",
+ // https://github.com/advisories/GHSA-977x-g7h5-7qgw
+ "GHSA-977x-g7h5-7qgw",
+ // https://github.com/advisories/GHSA-f7q4-pwc6-w24p
+ "GHSA-f7q4-pwc6-w24p"
]
}
diff --git a/docs/1-introduction.mdx b/docs/1-introduction.mdx
new file mode 100644
index 0000000000..7b53656af6
--- /dev/null
+++ b/docs/1-introduction.mdx
@@ -0,0 +1,198 @@
+# Introduction
+
+The Arbitrum SDK is a powerful TypeScript library that streamlines interactions with Arbitrum networks. It offers robust tools for bridging tokens and passing messages between networks through an intuitive interface to the underlying smart contracts.
+
+**Key Features**
+
+- Token Bridging: Effortlessly bridge tokens between Ethereum and Arbitrum.
+- Message Passing: Seamlessly pass messages across networks.
+- Contracts Interface: Leverage a strongly-typed interface for interacting with smart contracts.
+
+Below is an overview of the Arbitrum SDK functionality. See the [tutorials](https://github.com/OffchainLabs/arbitrum-tutorials) for more examples.
+
+## Getting Started
+
+Install dependencies
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+
+
+
+```sh
+npm install @arbitrum/sdk
+```
+
+
+
+
+```sh
+yarn add @arbitrum/sdk
+```
+
+
+
+
+```sh
+pnpm install @arbitrum/sdk
+```
+
+
+
+
+## Using the Arbitrum SDK
+
+### Bridging assets
+
+Arbitrum SDK can be used to bridge assets to or from an Arbitrum Network. The following asset bridgers are currently available:
+
+- [`EthBridger`](./reference/assetBridger/ethBridger.md)
+- [`Erc20Bridger`](./reference/assetBridger/erc20Bridger.md)
+
+All asset bridgers have the following methods which accept different parameters depending on the asset bridger type:
+
+- [`deposit`](./reference/assetBridger/assetBridger.md#deposit) - moves assets from the Parent to the Child chain
+- [`withdraw`](./reference/assetBridger/assetBridger.md#withdraw) - moves assets from the Child to the Parent chain
+
+#### Example ETH Deposit to Arbitrum One
+
+```ts
+import { getArbitrumNetwork, EthBridger } from '@arbitrum/sdk'
+
+// get the `@arbitrum/sdk` ArbitrumNetwork object using the chain id of the Arbitrum One chain
+const childNetwork = await getArbitrumNetwork(42161)
+const ethBridger = new EthBridger(childNetwork)
+
+const ethDepositTxResponse = await ethBridger.deposit({
+ amount: utils.parseEther('23'),
+ parentSigner, // an ethers v5 signer connected to mainnet ethereum
+ childProvider, // an ethers v5 provider connected to Arbitrum One
+})
+
+const ethDepositTxReceipt = await ethDepositTxResponse.wait()
+```
+
+[Learn more in the Eth Deposit tutorial](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/eth-deposit)
+
+#### Example ETH Withdrawal from Arbitrum One
+
+```ts
+import { getArbitrumNetwork, EthBridger } from '@arbitrum/sdk'
+
+// get the `@arbitrum/sdk` ArbitrumNetwork object using the chain id of the Arbitrum One chain
+const childNetwork = await getArbitrumNetwork(42161)
+const ethBridger = new EthBridger(childNetwork)
+
+const withdrawTx = await ethBridger.withdraw({
+ amount: utils.parseEther('23'),
+ childSigner, // an ethers v5 signer connected to Arbitrum One
+ destinationAddress: childWallet.address,
+})
+const withdrawRec = await withdrawTx.wait()
+```
+
+[Learn more in the Eth Withdraw tutorial](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/eth-withdraw)
+
+### Networks
+
+Arbitrum SDK comes pre-configured for Mainnet and Sepolia, and their Arbitrum counterparts. Any other networks that are not pre-configured **must** be registered before being used.
+
+#### Configuring Network
+
+To interact with a custom [`ArbitrumNetwork`](./reference/dataEntities/networks), you can register it using the [`registerCustomArbitrumNetwork`](./reference/dataEntities/networks.md#registerCustomArbitrumNetwork) function.
+
+```ts
+import { registerCustomArbitrumNetwork } from '@arbitrum/sdk'
+
+registerCustomArbitrumNetwork({
+ chainID: 123456,
+ name: 'Custom Arbitrum Network',
+})
+```
+
+### Cross chain messages
+
+When assets are moved by the Parent and Child cross chain messages are sent. The lifecycles of these messages are encapsulated in the classes [`ParentToChildMessage`](./reference/message/ParentToChildMessage) and [`ChildToParentMessage`](./reference/message/ParentToChildMessage). These objects are commonly created from the receipts of transactions that send cross chain messages. A cross chain message will eventually result in a transaction being executed on the destination chain, and these message classes provide the ability to wait for that finalizing transaction to occur.
+
+#### Redeem a Parent-to-Child Message
+
+```ts
+import {
+ ParentTransactionReceipt,
+ ParentToChildMessageStatus,
+} from '@arbitrum/sdk'
+
+const parentTxnReceipt = new ParentTransactionReceipt(
+ txnReceipt // ethers-js TransactionReceipt of an ethereum tx that triggered a Parent-to-Child message (say depositing a token via a bridge)
+)
+
+const parentToChildMessage = (
+ await parentTxnReceipt.getParentToChildMessages(
+ childSigner // connected ethers-js Wallet
+ )
+)[0]
+
+const res = await parentToChildMessage.waitForStatus()
+
+if (res.status === ParentToChildMessageStatus.Child) {
+ // Message wasn't auto-redeemed; redeem it now:
+ const response = await parentToChildMessage.redeem()
+ const receipt = await response.wait()
+} else if (res.status === ParentToChildMessageStatus.REDEEMED) {
+ // Message successfully redeemed
+}
+```
+
+[Learn more in the Redeem Failed Retryable Tickets tutorial](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/redeem-failed-retryable)
+
+### Inbox Tools
+
+As part of normal operation, the Arbitrum sequencer will send messages into the rollup chain. However, if the sequencer is unavailable and not posting batches, the inbox tools can be used to force the inclusion of transactions into the Arbitrum network.
+
+Here's how you can use the inbox tools to withdraw ether from Arbitrum One without waiting for the sequencer:
+
+```ts
+const childNetwork = await getArbitrumNetwork(await childWallet.getChainId())
+
+const inboxSdk = new InboxTools(parentWallet, childNetwork)
+const arbSys = ArbSys__factory.connect(ARB_SYS_ADDRESS, childProvider)
+const arbSysIface = arbSys.interface
+const childCalldata = arbSysIface.encodeFunctionData('withdrawEth', [
+ parentWallet.address,
+])
+
+const txChildRequest = {
+ data: childCalldata,
+ to: ARB_SYS_ADDRESS,
+ value: 1,
+}
+
+const childSignedTx = await inboxSdk.signChildTx(txChildRequest, childWallet)
+const childTxhash = ethers.utils.parseTransaction(childSignedTx).hash
+const resultsParent = await inboxSdk.sendChildSignedTx(childSignedTx)
+
+const inboxRec = await resultsParent.wait()
+```
+
+[Learn more in the Delayed Inbox tutorial](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/delayedInbox-l2msg).
+
+### Utils
+
+- [`EventFetcher`](./reference/utils/eventFetcher) - A utility to provide typing for the fetching of events
+- [`MultiCaller`](./reference/utils/multicall#multicaller) - A utility for executing multiple calls as part of a single RPC request. This can be useful for reducing round trips.
+- [`constants`](./reference/dataEntities/constants) - A list of useful Arbitrum related constants
+
+## Development
+
+### Run Integration tests
+
+1. Copy the `.env-sample` file to `.env` and update the values with your own.
+1. First, make sure you have a [Nitro test node](https://github.com/Offchainlabs/nitro-testnode) running. Follow the instructions [here](https://docs.arbitrum.io/node-running/how-tos/local-dev-node).
+1. After the node has started up (that could take up to 20-30 mins), run `yarn gen:network`.
+1. Once done, finally run `yarn test:integration` to run the integration tests.
+
+Defaults to `Arbitrum Sepolia`, for custom network use `--network` flag.
+
+`Arbitrum Sepolia` expects env var `ARB_KEY` to be prefunded with at least 0.02 ETH, and env var `INFURA_KEY` to be set.
+(see `integration_test/config.ts`)
diff --git a/docs/2-migrate.mdx b/docs/2-migrate.mdx
new file mode 100644
index 0000000000..6c65870c31
--- /dev/null
+++ b/docs/2-migrate.mdx
@@ -0,0 +1,198 @@
+# Migrating from v3 to v4
+
+## Introduction
+
+`@arbitrum/sdk` v4 introduces significant changes to improve support Orbit chains from Offchain Labs. This guide outlines the breaking changes to know before migrating your existing v3 code to v4.
+
+## Major Changes Overview
+
+1. Terminology change from L1/L2 to parent/child
+2. Network types and functions updated
+3. Updates to `AssetBridger` and `Erc20Bridger` classes
+4. Changes to Message classes
+
+## Detailed Changes
+
+### 1. Terminology change from L1/L2 to parent/child
+
+Most instances of "L1" and "L2" have been replaced with "parent" and "child" respectively. This change reflects the more general parent-child relationship between chains in the Arbitrum ecosystem.
+
+- In most circumstances, when referring to a parent-child relationship between chains, the terms "parent" and "child" are used.
+- Though, when referring explicitly to "L1", "L2", or "L3", those specific terms are still used.
+
+### 2. Network types and functions updated
+
+- The `L1Network` is no longer required to be registered before bridging.
+- Only Arbitrum networks need to be registered.
+- Arbitrum networks are defined as Arbitrum One, Arbitrum testnets, and any Orbit chain.
+- If you need a full list of Arbitrum networks, you can use the new [`getArbitrumNetworks`](./reference/dataEntities/networks#getArbitrumNetworks) function.
+- To list all of the children of a network, use the new [`getChildrenForNetwork`](./reference/dataEntities/networks#getChildrenForNetwork) function.
+
+| v3 Name | v4 Name |
+| --------------------- | -------------------------------------------------------------------------------------------------- |
+| `L2Network` | [`ArbitrumNetwork`](./reference/dataEntities/networks#arbitrumnetwork) |
+| `getL2Network` | [`getArbitrumNetwork`](./reference/dataEntities/networks#getArbitrumNetwork) |
+| `l2Networks` | [`getArbitrumNetworks`](./reference/dataEntities/networks#getArbitrumNetworks) |
+| `addCustomNetwork` | [`registerCustomArbitrumNetwork`](./reference/dataEntities/networks#registerCustomArbitrumNetwork) |
+| `Network` | *removed* |
+| `L1Network` | *removed* |
+| `getL1Network` | *removed* |
+| `getParentForNetwork` | *removed* |
+
+#### `ArbitrumNetwork` type
+
+`Network` type has been replaced with the [`ArbitrumNetwork`](./reference/dataEntities/networks#arbitrumnetwork) type and some properties have been removed or renamed.
+
+| v3 Name | v4 Name |
+| --------------------- | --------------- |
+| `chainID` | `chainId` |
+| `partnerChainID` | `parentChainId` |
+| `explorerUrl` | *removed* |
+| `isArbitrum` | *removed* |
+| `partnerChainIDs` | *removed* |
+| `nitroGenesisBlock` | *removed* |
+| `nitroGenesisL1Block` | *removed* |
+| `depositTimeout` | *removed* |
+| `blockTime` | *removed* |
+
+#### `TokenBridge` type
+
+The `TokenBridge` type within the[`ArbitrumNetwork`](./reference/dataEntities/networks#arbitrumnetwork) object has been updated.
+
+| v3 Name | v4 Name |
+| ----------------- | --------------------- |
+| `l1CustomGateway` | `parentCustomGateway` |
+| `l1ERC20Gateway` | `parentErc20Gateway` |
+| `l1GatewayRouter` | `parentGatewayRouter` |
+| `l1MultiCall` | `parentMultiCall` |
+| `l1ProxyAdmin` | `parentProxyAdmin` |
+| `l1Weth` | `parentWeth` |
+| `l1WethGateway` | `parentWethGateway` |
+| `l2CustomGateway` | `childCustomGateway` |
+| `l2ERC20Gateway` | `childErc20Gateway` |
+| `l2GatewayRouter` | `childGatewayRouter` |
+| `l2Multicall` | `childMultiCall` |
+| `l2ProxyAdmin` | `childProxyAdmin` |
+| `l2Weth` | `childWeth` |
+| `l2WethGateway` | `childWethGateway` |
+
+### 3. Updates to `AssetBridger` and `Erc20Bridger` classes
+
+#### [`AssetBridger`](./reference/assetBridger/assetBridger.md) Class Methods
+
+The [`AssetBridger`](./reference/assetBridger/assetBridger.md) class methods and properties have been renamed to reflect the new parent-child terminology.
+
+| v3 Name | v4 Name |
+| ---------------- | -------------------- |
+| `l2Network` | `childNetwork` |
+| `checkL1Network` | `checkParentNetwork` |
+| `checkL2Network` | `checkChildNetwork` |
+
+#### [`AssetBridger`](./reference/assetBridger/assetBridger.md) Class Method Parameters
+
+The objects passed to the class methods of classes that inherit from [`AssetBridger`](./reference/assetBridger/assetBridger.md) ([`EthBridger`](./reference/assetBridger/ethBridger.md) and [`Erc20Bridger`](./reference/assetBridger/erc20Bridger.md)) have been renamed.
+
+| v3 Name | v4 Name |
+| ---------------- | -------------------- |
+| `erc20L1Address` | `erc20ParentAddress` |
+| `l1Provider` | `parentProvider` |
+| `l2Provider` | `childProvider` |
+| `l1Signer` | `parentSigner` |
+| `l2Signer` | `childSigner` |
+
+#### [`Erc20Bridger`](./reference/assetBridger/erc20Bridger.md) Class Methods
+
+| v3 Name | v4 Name |
+| ----------------------- | --------------------------- |
+| `getL1GatewayAddress` | `getParentGatewayAddress` |
+| `getL2GatewayAddress` | `getChildGatewayAddress` |
+| `getL2WithdrawalEvents` | `getWithdrawalEvents` |
+| `getL1TokenContract` | `getParentTokenContract` |
+| `getL1ERC20Address` | `getParentErc20Address` |
+| `getL2TokenContract` | `getChildTokenContract` |
+| `getL2ERC20Address` | `getChildErc20Address` |
+| `l1TokenIsDisabled` | `isDepositDisabled` |
+| `l1Provider` | `parentProvider` |
+| `getL1GatewaySetEvents` | `getParentGatewaySetEvents` |
+| `getL2GatewaySetEvents` | `getChildGatewaySetEvents` |
+
+#### [`Erc20L1L3Bridger`](./reference/assetBridger/l1l3Bridger.md) Class Methods
+
+| v3 Name | v4 Name |
+| ------------------- | ------------------- |
+| `getL2ERC20Address` | `getL2Erc20Address` |
+| `getL3ERC20Address` | `getL3Erc20Address` |
+
+### 4. Changes to Message classes
+
+Message classes have been renamed and their methods updated:
+
+| v3 Name | v4 Name |
+| ----------------------------- | ----------------------------------------- |
+| `L1TransactionReceipt` | `ParentTransactionReceipt` |
+| `L1ContractTransaction` | `ParentContractTransaction` |
+| `L1ToL2Message` | `ParentToChildMessage` |
+| `L1ToL2MessageWriter` | `ParentToChildMessageWriter` |
+| `L1ToL2MessageReader` | `ParentToChildMessageReader` |
+| `L1ToL2MessageReaderClassic` | `ParentToChildMessageReaderClassic` |
+| `L1ToL2MessageStatus` | `ParentToChildMessageStatus` |
+| `L1ToL2MessageGasEstimator` | `ParentToChildMessageGasEstimator` |
+| `L2TransactionReceipt` | `ChildTransactionReceipt` |
+| `L2ContractTransaction` | `ChildContractTransaction` |
+| `L2ToL1Message` | `ChildToParentMessage` |
+| `L2ToL1MessageWriter` | `ChildToParentMessageWriter` |
+| `L2ToL1MessageReader` | `ChildToParentMessageReader` |
+| `L2ToL1MessageStatus` | `ChildToParentMessageStatus` |
+| `EthDepositStatus` | `EthDepositMessageStatus` |
+| `EthDepositMessageWaitResult` | `EthDepositMessageWaitForStatusResult` |
+| `L1ToL2MessageWaitResult` | `ParentToChildMessageWaitForStatusResult` |
+
+#### `ChildToParentMessageClassic`
+
+| v3 Name | v4 Name |
+| ----------------- | ------------------------ |
+| `getL2ToL1Events` | `getChildToParentEvents` |
+
+#### `ChildToParentChainMessageNitro`
+
+| v3 Name | v4 Name |
+| ----------------- | ------------------------ |
+| `getL2ToL1Events` | `getChildToParentEvents` |
+
+#### `ChildTransactionReceipt`
+
+| v3 Name | v4 Name |
+| ------------------- | -------------------------- |
+| `getL2ToL1Events` | `getChildToParentEvents` |
+| `getL2ToL1Messages` | `getChildToParentMessages` |
+
+#### `ParentToChildMessage`
+
+| v3 Name | v4 Name |
+| ------------------ | ------------------------- |
+| `EthDepositStatus` | `EthDepositMessageStatus` |
+
+#### `ParentToChildMessageStatus`
+
+| v3 Name | v4 Name |
+| ----------------------- | -------------------------- |
+| `FUNDS_DEPOSITED_ON_L2` | `FUNDS_DEPOSITED_ON_CHILD` |
+
+#### `ParentTransactionReceipt`
+
+| v3 Name | v4 Name |
+| -------------------------- | --------------------------------- |
+| `getL1ToL2MessagesClassic` | `getParentToChildMessagesClassic` |
+| `getL1ToL2Messages` | `getParentToChildMessages` |
+
+#### `ParentEthDepositTransactionReceipt`
+
+| v3 Name | v4 Name |
+| ----------- | -------------------------------- |
+| `waitForL2` | `waitForChildTransactionReceipt` |
+
+#### `ParentContractCallTransactionReceipt`
+
+| v3 Name | v4 Name |
+| ----------- | -------------------------------- |
+| `waitForL2` | `waitForChildTransactionReceipt` |
diff --git a/package.json b/package.json
index 2a23ff7ef4..6153ca94b3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@arbitrum/sdk",
- "version": "3.7.0",
+ "version": "4.0.1",
"description": "Typescript library client-side interactions with Arbitrum",
"author": "Offchain Labs, Inc.",
"license": "Apache-2.0",
@@ -38,8 +38,6 @@
"lint": "eslint .",
"format": "prettier './**/*.{js,json,md,ts,yml}' '!./src/lib/abi' --write && yarn run lint --fix",
"clean:compile": "ts-node scripts/cleanCompileContracts.ts",
- "generate_docs": "typedoc --options typedoc_md.js && node scripts/postProcessDocs.js",
- "generate_docs_site": "typedoc",
"checkRetryable": "ts-node scripts/checkRetryableStatus.ts",
"redeemRetryable": "ts-node scripts/redeemRetryable.ts",
"setStandard": "ts-node scripts/setStandardGateways.ts",
@@ -86,8 +84,6 @@
"ts-node": "^10.2.1",
"tslint": "^6.1.3",
"typechain": "7.0.0",
- "typedoc": "^0.25.7",
- "typedoc-plugin-markdown": "^3.17.1",
"typescript": "^4.9.5",
"yargs": "^17.3.1"
},
diff --git a/scripts/cancelRetryable.ts b/scripts/cancelRetryable.ts
index b4623c1aab..939a341f35 100644
--- a/scripts/cancelRetryable.ts
+++ b/scripts/cancelRetryable.ts
@@ -20,7 +20,7 @@ import { ContractReceipt } from '@ethersproject/contracts'
import { instantiateBridge } from './instantiate_bridge'
import args from './getCLargs'
-import { L1TransactionReceipt } from '../src/lib/message/L1Transaction'
+import { L1TransactionReceipt } from '../src/lib/message/ParentTransaction'
if (!args.txid) {
throw new Error('Include txid (--txid 0xmytxid)')
diff --git a/scripts/deployStandard.ts b/scripts/deployStandard.ts
index addf09a074..0fb68cdc5a 100644
--- a/scripts/deployStandard.ts
+++ b/scripts/deployStandard.ts
@@ -26,7 +26,7 @@ const main = async () => {
)
const l1Provider = l1Signer.provider!
const l2Provider = l2Signer.provider!
- const gatewayAddress = await erc20Bridger.getL1GatewayAddress(
+ const gatewayAddress = await erc20Bridger.getParentGatewayAddress(
l1TokenAddress,
l1Provider
)
@@ -50,7 +50,7 @@ const main = async () => {
}
/** Check if disabled */
- const isDisabled = await erc20Bridger.l1TokenIsDisabled(
+ const isDisabled = await erc20Bridger.isDepositDisabled(
l1TokenAddress,
l1Provider
)
@@ -102,7 +102,7 @@ const main = async () => {
}
/* check token not yet deployed */
- const l2TokenAddress = await erc20Bridger.getL2ERC20Address(
+ const l2TokenAddress = await erc20Bridger.getChildErc20Address(
l1TokenAddress,
l1Provider
)
diff --git a/scripts/genNetwork.ts b/scripts/genNetwork.ts
index c704ee622c..f991bc2660 100644
--- a/scripts/genNetwork.ts
+++ b/scripts/genNetwork.ts
@@ -2,10 +2,14 @@ import * as dotenv from 'dotenv'
dotenv.config()
import { execSync } from 'child_process'
import * as fs from 'fs'
-import { L2Network } from '../src'
-import { ARB_MINIMUM_BLOCK_TIME_IN_SECONDS } from '../src/lib/dataEntities/constants'
+
import { IERC20Bridge__factory } from '../src/lib/abi/factories/IERC20Bridge__factory'
import { ethers } from 'ethers'
+import {
+ L2Network,
+ ArbitrumNetwork,
+ mapL2NetworkToArbitrumNetwork,
+} from '../src/lib/dataEntities/networks'
const isTestingOrbitChains = process.env.ORBIT_TEST === '1'
@@ -39,24 +43,29 @@ async function patchNetworks(
l2Network: L2Network,
l3Network: L2Network | undefined,
l2Provider: ethers.providers.Provider | undefined
-) {
- // we need to add partnerChainIDs to the L2 network
- l2Network.partnerChainIDs = l3Network ? [l3Network.chainID] : []
- l2Network.blockTime = ARB_MINIMUM_BLOCK_TIME_IN_SECONDS
+): Promise<{
+ patchedL2Network: ArbitrumNetwork
+ patchedL3Network?: ArbitrumNetwork
+}> {
+ const patchedL2Network = mapL2NetworkToArbitrumNetwork(l2Network)
// native token for l3
if (l3Network && l2Provider) {
- l3Network.partnerChainIDs = []
- l3Network.blockTime = ARB_MINIMUM_BLOCK_TIME_IN_SECONDS
+ const patchedL3Network = mapL2NetworkToArbitrumNetwork(l3Network)
+
try {
- l3Network.nativeToken = await IERC20Bridge__factory.connect(
+ patchedL3Network.nativeToken = await IERC20Bridge__factory.connect(
l3Network.ethBridge.bridge,
l2Provider
).nativeToken()
} catch (e) {
// l3 network doesn't have a native token
}
+
+ return { patchedL2Network, patchedL3Network }
}
+
+ return { patchedL2Network }
}
async function main() {
@@ -65,18 +74,26 @@ async function main() {
let output = getLocalNetworksFromContainer('l1l2')
if (isTestingOrbitChains) {
+ // When running with L3 active, the container calls the L3 network L2 so we rename it here
const { l2Network: l3Network } = getLocalNetworksFromContainer('l2l3')
- await patchNetworks(
+ const { patchedL2Network, patchedL3Network } = await patchNetworks(
output.l2Network,
l3Network,
new ethers.providers.JsonRpcProvider(process.env['ARB_URL'])
)
+
output = {
- l1Network: output.l2Network,
- l2Network: l3Network,
+ l2Network: patchedL2Network,
+ l3Network: patchedL3Network,
}
} else {
- await patchNetworks(output.l2Network, undefined, undefined)
+ const { patchedL2Network } = await patchNetworks(
+ output.l2Network,
+ undefined,
+ undefined
+ )
+
+ output.l2Network = patchedL2Network
}
fs.writeFileSync('localNetwork.json', JSON.stringify(output, null, 2))
diff --git a/scripts/instantiate_bridge.ts b/scripts/instantiate_bridge.ts
index 25bd767ad2..747a81e8b6 100644
--- a/scripts/instantiate_bridge.ts
+++ b/scripts/instantiate_bridge.ts
@@ -23,14 +23,11 @@ import dotenv from 'dotenv'
import args from './getCLargs'
import { EthBridger, InboxTools, Erc20Bridger } from '../src'
import {
- l1Networks,
- l2Networks,
- L1Network,
- L2Network,
+ ArbitrumNetwork,
+ getArbitrumNetwork,
} from '../src/lib/dataEntities/networks'
import { Signer } from 'ethers'
import { AdminErc20Bridger } from '../src/lib/assetBridger/erc20Bridger'
-import { isDefined } from '../src/lib/utils/lib'
dotenv.config()
@@ -39,19 +36,18 @@ const ethKey = process.env['ETH_KEY'] as string
const defaultNetworkId = 421614
-export const instantiateBridge = (
+export const instantiateBridge = async (
l1PkParam?: string,
l2PkParam?: string
-): {
- l1Network: L1Network
- l2Network: L2Network
+): Promise<{
+ l2Network: ArbitrumNetwork
l1Signer: Signer
l2Signer: Signer
erc20Bridger: Erc20Bridger
ethBridger: EthBridger
adminErc20Bridger: AdminErc20Bridger
inboxTools: InboxTools
-} => {
+}> => {
if (!l1PkParam && !ethKey) {
throw new Error('need ARB_KEY var')
}
@@ -68,23 +64,8 @@ export const instantiateBridge = (
l2NetworkID = defaultNetworkId
}
- const isL1 = isDefined(l1Networks[l2NetworkID])
- const isL2 = isDefined(l2Networks[l2NetworkID])
- if (!isL1 && !isL2) {
- throw new Error(`Unrecognized network ID: ${l2NetworkID}`)
- }
- if (!isL2) {
- throw new Error(`Tests must specify an L2 network ID: ${l2NetworkID}`)
- }
-
- const l2Network = l2Networks[l2NetworkID]
- const l1Network = l1Networks[l2Network.partnerChainID]
- if (!l1Network) {
- throw new Error(
- `Unrecognised partner chain id: ${l2Network.partnerChainID}`
- )
- }
+ const l2Network = await getArbitrumNetwork(l2NetworkID)
const l1Rpc = (() => {
if (l2NetworkID === 42161) return process.env['MAINNET_RPC'] as string
@@ -140,7 +121,6 @@ export const instantiateBridge = (
const inboxTools = new InboxTools(l1Signer, l2Network)
return {
- l1Network,
l2Network,
l1Signer,
l2Signer,
diff --git a/scripts/lib.ts b/scripts/lib.ts
index 4fe83cc892..4b0191f90e 100644
--- a/scripts/lib.ts
+++ b/scripts/lib.ts
@@ -19,8 +19,8 @@
import { ContractReceipt } from '@ethersproject/contracts'
import { ERC20__factory } from '../src/lib/abi/factories/ERC20__factory'
-import { L1ToL2MessageStatus } from '../src/lib/message/L1ToL2Message'
-import { L1TransactionReceipt } from '../src/lib/message/L1Transaction'
+import { L1ToL2MessageStatus } from '../src/lib/message/ParentToChildMessage'
+import { L1TransactionReceipt } from '../src/lib/message/ParentTransaction'
import { testSetup } from '../scripts/testSetup'
export const setStandardGateWays = async (
@@ -39,9 +39,10 @@ export const setGateWays = async (
type: 'standard' | 'arbCustom',
overrideGateways: string[] = []
): Promise => {
- const { adminErc20Bridger, l1Signer, l2Network, l2Signer } = await testSetup()
- const l1Provider = l1Signer.provider!
- const l2Provider = l2Signer.provider!
+ const { adminErc20Bridger, parentSigner, childChain, childSigner } =
+ await testSetup()
+ const parentProvider = parentSigner.provider!
+ const childProvider = childSigner.provider!
if (tokens.length === 0) {
throw new Error('Include some tokens to set')
}
@@ -55,7 +56,7 @@ export const setGateWays = async (
for (const tokenAddress of tokens) {
try {
- const token = await ERC20__factory.connect(tokenAddress, l1Provider)
+ const token = await ERC20__factory.connect(tokenAddress, parentProvider)
console.warn('calling name for ', tokenAddress)
const symbol = await token.symbol()
@@ -85,17 +86,17 @@ export const setGateWays = async (
if (overrideGateways.length > 0) {
return overrideGateways
} else if (type === 'standard') {
- return tokens.map(() => l2Network.tokenBridge.l1ERC20Gateway)
+ return tokens.map(() => childChain.tokenBridge.parentErc20Gateway)
} else if (type === 'arbCustom') {
- return tokens.map(() => l2Network.tokenBridge.l1CustomGateway)
+ return tokens.map(() => childChain.tokenBridge.parentCustomGateway)
} else {
throw new Error('Unhandled else case')
}
})()
const res = await adminErc20Bridger.setGateways(
- l1Signer,
- l2Provider,
+ parentSigner,
+ childProvider,
gateways.map((g, i) => ({
tokenAddr: tokens[i],
gatewayAddr: gateways[i],
@@ -110,7 +111,7 @@ export const setGateWays = async (
}
console.log('redeeming retryable ticket:')
- const l2Tx = (await rec.getL1ToL2Messages(l2Signer))[0]
+ const l2Tx = (await rec.getParentToChildMessages(childSigner))[0]
if (!l2Tx) throw new Error('No l1 to l2 message found.')
const messageRes = await l2Tx.waitForStatus()
if (messageRes.status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) {
@@ -123,13 +124,13 @@ export const setGateWays = async (
}
export const checkRetryableStatus = async (l1Hash: string): Promise => {
- const { l1Signer, l2Signer } = await testSetup()
- const l1Provider = l1Signer.provider!
- const l2Provider = l2Signer.provider!
- const rec = await l1Provider.getTransactionReceipt(l1Hash)
+ const { parentSigner, childSigner } = await testSetup()
+ const parentProvider = parentSigner.provider!
+ const childProvider = childSigner.provider!
+ const rec = await parentProvider.getTransactionReceipt(l1Hash)
if (!rec) throw new Error('L1 tx not found!')
- const messages = await new L1TransactionReceipt(rec).getL1ToL2Messages(
- l2Provider
+ const messages = await new L1TransactionReceipt(rec).getParentToChildMessages(
+ childProvider
)
for (const message of messages) {
diff --git a/scripts/redeemRetryable.ts b/scripts/redeemRetryable.ts
index deedb45f5d..b79cd89f0e 100644
--- a/scripts/redeemRetryable.ts
+++ b/scripts/redeemRetryable.ts
@@ -20,7 +20,7 @@ import { ContractReceipt } from '@ethersproject/contracts'
import { testSetup } from '../scripts/testSetup'
import args from './getCLargs'
-import { L1TransactionReceipt } from '../src/lib/message/L1Transaction'
+import { L1TransactionReceipt } from '../src/lib/message/ParentTransaction'
import { L1ToL2MessageStatus, L1ToL2MessageWriter } from '../src'
import { fundL2 } from '../integration_test/testHelpers'
@@ -35,14 +35,14 @@ if (!l1Txn) {
}
;(async () => {
- const { l1Signer, l2Signer } = await testSetup()
+ const { parentSigner, childSigner } = await testSetup()
// TODO: Should use the PRIVKEY envvar signer directly
- fundL2(l2Signer)
- const l1Provider = l1Signer.provider!
+ fundL2(childSigner)
+ const l1Provider = parentSigner.provider!
const l1Receipt = new L1TransactionReceipt(
await l1Provider.getTransactionReceipt(l1Txn)
)
- const l1ToL2Message = await l1Receipt.getL1ToL2Message(l2Signer)
+ const l1ToL2Message = await l1Receipt.getL1ToL2Message(childSigner)
if (l1ToL2Message instanceof L1ToL2MessageWriter) {
const redeemStatus = (await l1ToL2Message.waitForStatus()).status
if (redeemStatus == L1ToL2MessageStatus.REDEEMED) {
diff --git a/scripts/sendL2SignedMsg.ts b/scripts/sendL2SignedMsg.ts
index 10ac03e9e7..08ccc8966f 100644
--- a/scripts/sendL2SignedMsg.ts
+++ b/scripts/sendL2SignedMsg.ts
@@ -18,19 +18,19 @@
import { BigNumber } from 'ethers'
import { InboxTools } from '../src/lib/inbox/inbox'
-import { getL2Network } from '../src/lib/dataEntities/networks'
+import { getArbitrumNetwork } from '../src/lib/dataEntities/networks'
import { testSetup } from '../scripts/testSetup'
const sendSignedMsg = async () => {
const { l1Deployer, l2Deployer } = await testSetup()
- const l2Network = await getL2Network(await l2Deployer.getChainId())
+ const l2Network = await getArbitrumNetwork(await l2Deployer.getChainId())
const inbox = new InboxTools(l1Deployer, l2Network)
const message = {
to: await l2Deployer.getAddress(),
value: BigNumber.from(0),
data: '0x12',
}
- const signedTx = await inbox.signL2Tx(message, l2Deployer)
- await inbox.sendL2SignedTx(signedTx)
+ const signedTx = await inbox.signChildChainTx(message, l2Deployer)
+ await inbox.sendChildChainSignedTx(signedTx)
}
sendSignedMsg()
diff --git a/scripts/testSetup.ts b/scripts/testSetup.ts
index b16cbc8b6c..10bc2c68ba 100644
--- a/scripts/testSetup.ts
+++ b/scripts/testSetup.ts
@@ -23,11 +23,11 @@ import dotenv from 'dotenv'
import { EthBridger, InboxTools, Erc20Bridger } from '../src'
import {
- L1Network,
- L2Network,
- getL1Network,
- getL2Network,
- addCustomNetwork,
+ ArbitrumNetwork,
+ getArbitrumNetwork,
+ registerCustomArbitrumNetwork,
+ TokenBridge,
+ assertArbitrumNetworkHasTokenBridge,
} from '../src/lib/dataEntities/networks'
import { Signer } from 'ethers'
import { AdminErc20Bridger } from '../src/lib/assetBridger/erc20Bridger'
@@ -35,11 +35,11 @@ import * as path from 'path'
import * as fs from 'fs'
import { ArbSdkError } from '../src/lib/dataEntities/errors'
import {
- approveL1CustomFeeToken,
- fundL1CustomFeeToken,
- isL2NetworkWithCustomFeeToken,
+ approveParentCustomFeeToken,
+ fundParentCustomFeeToken,
+ isArbitrumNetworkWithCustomFeeToken,
} from '../tests/integration/custom-fee-token/customFeeTokenTestHelpers'
-import { fundL1 } from '../tests/integration/testHelpers'
+import { fundParentSigner } from '../tests/integration/testHelpers'
dotenv.config()
@@ -72,114 +72,84 @@ export const getSigner = (provider: JsonRpcProvider, key?: string) => {
}
export const testSetup = async (): Promise<{
- l1Network: L1Network | L2Network
- l2Network: L2Network
- l1Signer: Signer
- l2Signer: Signer
- l1Provider: Provider
- l2Provider: Provider
+ childChain: ArbitrumNetwork & {
+ tokenBridge: TokenBridge
+ }
+ parentSigner: Signer
+ childSigner: Signer
+ parentProvider: Provider
+ childProvider: Provider
erc20Bridger: Erc20Bridger
ethBridger: EthBridger
adminErc20Bridger: AdminErc20Bridger
inboxTools: InboxTools
- l1Deployer: Signer
- l2Deployer: Signer
+ parentDeployer: Signer
+ childDeployer: Signer
}> => {
const ethProvider = new JsonRpcProvider(config.ethUrl)
const arbProvider = new JsonRpcProvider(config.arbUrl)
- const l1Deployer = getSigner(ethProvider, config.ethKey)
- const l2Deployer = getSigner(arbProvider, config.arbKey)
+ const parentDeployer = getSigner(ethProvider, config.ethKey)
+ const childDeployer = getSigner(arbProvider, config.arbKey)
const seed = Wallet.createRandom()
- const l1Signer = seed.connect(ethProvider)
- const l2Signer = seed.connect(arbProvider)
+ const parentSigner = seed.connect(ethProvider)
+ const childSigner = seed.connect(arbProvider)
+
+ let setChildChain: ArbitrumNetwork
- let setL1Network: L1Network | L2Network, setL2Network: L2Network
try {
- const l1Network = isTestingOrbitChains
- ? await getL2Network(l1Deployer)
- : await getL1Network(l1Deployer)
- const l2Network = await getL2Network(l2Deployer)
- setL1Network = l1Network
- setL2Network = l2Network
+ const l2Network = await getArbitrumNetwork(childDeployer)
+ setChildChain = l2Network
} catch (err) {
+ const localNetworks = getLocalNetworksFromFile()
// the networks havent been added yet
-
// check if theres an existing network available
- const localNetworkFile = getLocalNetworksFromFile()
-
- const { l1Network, l2Network } = localNetworkFile
-
- if (isTestingOrbitChains) {
- const _l1Network = l1Network as L2Network
- const ethLocal: L1Network = {
- blockTime: 10,
- chainID: _l1Network.partnerChainID,
- explorerUrl: '',
- isCustom: true,
- name: 'EthLocal',
- partnerChainIDs: [_l1Network.chainID],
- isArbitrum: false,
- }
-
- addCustomNetwork({
- customL1Network: ethLocal,
- customL2Network: _l1Network,
- })
-
- addCustomNetwork({
- customL2Network: l2Network,
- })
-
- setL1Network = l1Network
- setL2Network = l2Network
- } else {
- addCustomNetwork({
- customL1Network: l1Network as L1Network,
- customL2Network: l2Network,
- })
-
- setL1Network = l1Network
- setL2Network = l2Network
- }
+ const childChain = (
+ isTestingOrbitChains ? localNetworks.l3Network : localNetworks.l2Network
+ ) as ArbitrumNetwork
+ setChildChain = registerCustomArbitrumNetwork(childChain)
}
- const erc20Bridger = new Erc20Bridger(setL2Network)
- const adminErc20Bridger = new AdminErc20Bridger(setL2Network)
- const ethBridger = new EthBridger(setL2Network)
- const inboxTools = new InboxTools(l1Signer, setL2Network)
+ assertArbitrumNetworkHasTokenBridge(setChildChain)
+
+ const erc20Bridger = new Erc20Bridger(setChildChain)
+ const adminErc20Bridger = new AdminErc20Bridger(setChildChain)
+ const ethBridger = new EthBridger(setChildChain)
+ const inboxTools = new InboxTools(parentSigner, setChildChain)
- if (isL2NetworkWithCustomFeeToken()) {
- await fundL1(l1Signer)
- await fundL1CustomFeeToken(l1Signer)
- await approveL1CustomFeeToken(l1Signer)
+ if (isArbitrumNetworkWithCustomFeeToken()) {
+ await fundParentSigner(parentSigner)
+ await fundParentCustomFeeToken(parentSigner)
+ await approveParentCustomFeeToken(parentSigner)
}
return {
- l1Signer,
- l2Signer,
- l1Provider: ethProvider,
- l2Provider: arbProvider,
- l1Network: setL1Network,
- l2Network: setL2Network,
+ parentSigner,
+ childSigner,
+ parentProvider: ethProvider,
+ childProvider: arbProvider,
+ childChain: setChildChain,
erc20Bridger,
adminErc20Bridger,
ethBridger,
inboxTools,
- l1Deployer,
- l2Deployer,
+ parentDeployer,
+ childDeployer,
}
}
export function getLocalNetworksFromFile(): {
- l1Network: L1Network | L2Network
- l2Network: L2Network
+ l2Network: ArbitrumNetwork
+ l3Network?: ArbitrumNetwork
} {
const pathToLocalNetworkFile = path.join(__dirname, '..', 'localNetwork.json')
if (!fs.existsSync(pathToLocalNetworkFile)) {
throw new ArbSdkError('localNetwork.json not found, must gen:network first')
}
const localNetworksFile = fs.readFileSync(pathToLocalNetworkFile, 'utf8')
- return JSON.parse(localNetworksFile)
+ const localL2: ArbitrumNetwork = JSON.parse(localNetworksFile).l2Network
+ const localL3: ArbitrumNetwork = JSON.parse(localNetworksFile).l3Network
+
+ return { l2Network: localL2, l3Network: localL3 }
}
diff --git a/scripts/upgrade_weth.ts b/scripts/upgrade_weth.ts
index eb0e645cfd..efbb69c386 100644
--- a/scripts/upgrade_weth.ts
+++ b/scripts/upgrade_weth.ts
@@ -32,7 +32,7 @@ const main = async () => {
console.log('aeWeth logic deployed to ', logicAddress)
const connectedProxy = TransparentUpgradeableProxy__factory.connect(
- l2Network.tokenBridge.l2Weth,
+ l2Network.tokenBridge.childWeth,
l2Signer
)
const upgradeRes = await connectedProxy.upgradeTo(logicAddress)
@@ -45,13 +45,13 @@ const main = async () => {
// const { bridge, l2Network } = await instantiateBridge()
// const { l2Signer } = bridge.l2Bridge
-// const aeWeth = AeWETH__factory.connect(l2Network.tokenBridge.l2Weth, l2Signer)
+// const aeWeth = AeWETH__factory.connect(l2Network.tokenBridge.childWeth, l2Signer)
// const res = await aeWeth.initialize(
// 'Wrapped Ether',
// 'WETH',
// 18,
-// l2Network.tokenBridge.l2WethGateway,
-// l2Network.tokenBridge.l1Weth
+// l2Network.tokenBridge.childWethGateway,
+// l2Network.tokenBridge.parentWeth
// )
// const rec = await res.wait()
diff --git a/src/index.ts b/src/index.ts
index 2fb3fb9756..fc75ca783a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -17,53 +17,81 @@
'use strict'
export {
- Erc20L1L3Bridger,
EthL1L3Bridger,
+ EthL1L3DepositStatus,
+ EthL1L3DepositRequestParams,
+ Erc20L1L3Bridger,
+ Erc20L1L3DepositStatus,
+ Erc20L1L3DepositRequestParams,
+ Erc20L1L3DepositRequestRetryableOverrides,
+ GetL1L3DepositStatusParams,
} from './lib/assetBridger/l1l3Bridger'
export { EthBridger } from './lib/assetBridger/ethBridger'
export { Erc20Bridger } from './lib/assetBridger/erc20Bridger'
export {
- L2TransactionReceipt,
- L2ContractTransaction,
-} from './lib/message/L2Transaction'
+ ChildTransactionReceipt,
+ ChildContractTransaction,
+} from './lib/message/ChildTransaction'
export {
- L2ToL1Message,
- L2ToL1MessageWriter,
- L2ToL1MessageReader,
-} from './lib/message/L2ToL1Message'
+ ChildToParentMessage,
+ ChildToParentMessageWriter,
+ ChildToParentMessageReader,
+ ChildToParentMessageReaderOrWriter,
+ ChildToParentTransactionEvent,
+} from './lib/message/ChildToParentMessage'
export {
- L1ContractTransaction,
- L1TransactionReceipt,
-} from './lib/message/L1Transaction'
+ ParentEthDepositTransaction,
+ ParentEthDepositTransactionReceipt,
+ ParentContractCallTransaction,
+ ParentContractCallTransactionReceipt,
+ ParentContractTransaction,
+ ParentTransactionReceipt,
+} from './lib/message/ParentTransaction'
export {
- L1ToL2MessageStatus,
- EthDepositStatus,
- L1ToL2Message,
- L1ToL2MessageReader,
- L1ToL2MessageReaderClassic,
- L1ToL2MessageWriter,
-} from './lib/message/L1ToL2Message'
-export { L1ToL2MessageGasEstimator } from './lib/message/L1ToL2MessageGasEstimator'
+ EthDepositMessage,
+ EthDepositMessageStatus,
+ EthDepositMessageWaitForStatusResult,
+ ParentToChildMessage,
+ ParentToChildMessageReader,
+ ParentToChildMessageReaderClassic,
+ ParentToChildMessageWriter,
+ ParentToChildMessageStatus,
+ ParentToChildMessageWaitForStatusResult,
+} from './lib/message/ParentToChildMessage'
+export { ParentToChildMessageGasEstimator } from './lib/message/ParentToChildMessageGasEstimator'
export { argSerializerConstructor } from './lib/utils/byte_serialize_params'
export { CallInput, MultiCaller } from './lib/utils/multicall'
export {
- L1Networks,
- L2Networks,
- L1Network,
+ ArbitrumNetwork,
+ getArbitrumNetwork,
+ getArbitrumNetworks,
+ ArbitrumNetworkInformationFromRollup,
+ getArbitrumNetworkInformationFromRollup,
+ getChildrenForNetwork,
+ registerCustomArbitrumNetwork,
+ // deprecated, but here for backwards compatibility
L2Network,
- getL1Network,
- getL2Network,
- addCustomNetwork,
- addDefaultLocalNetwork,
+ L2NetworkTokenBridge,
+ mapL2NetworkToArbitrumNetwork,
+ mapL2NetworkTokenBridgeToTokenBridge,
} from './lib/dataEntities/networks'
export { InboxTools } from './lib/inbox/inbox'
export { EventFetcher } from './lib/utils/eventFetcher'
export { ArbitrumProvider } from './lib/utils/arbProvider'
export * as constants from './lib/dataEntities/constants'
-export { L2ToL1MessageStatus } from './lib/dataEntities/message'
+export {
+ ChildToParentMessageStatus,
+ RetryableMessageParams,
+} from './lib/dataEntities/message'
export {
RetryableData,
RetryableDataTools,
} from './lib/dataEntities/retryableData'
-
+export { EventArgs } from './lib/dataEntities/event'
export { Address } from './lib/dataEntities/address'
+export {
+ ParentToChildTransactionRequest,
+ isParentToChildTransactionRequest,
+ ChildToParentTransactionRequest,
+ isChildToParentTransactionRequest,
+} from './lib/dataEntities/transactionRequest'
diff --git a/src/lib/assetBridger/assetBridger.ts b/src/lib/assetBridger/assetBridger.ts
index f6eeb77389..6ef1d549d1 100644
--- a/src/lib/assetBridger/assetBridger.ts
+++ b/src/lib/assetBridger/assetBridger.ts
@@ -18,54 +18,50 @@
import { constants } from 'ethers'
-import { L1ContractTransaction } from '../message/L1Transaction'
-import { L2ContractTransaction } from '../message/L2Transaction'
+import { ParentContractTransaction } from '../message/ParentTransaction'
+import { ChildContractTransaction } from '../message/ChildTransaction'
-import {
- L1Network,
- L2Network,
- getParentForNetwork,
-} from '../dataEntities/networks'
+import { ArbitrumNetwork } from '../dataEntities/networks'
import {
SignerOrProvider,
SignerProviderUtils,
} from '../dataEntities/signerOrProvider'
/**
- * Base for bridging assets from l1 to l2 and back
+ * Base for bridging assets from parent-to-child and back
*/
export abstract class AssetBridger {
- /**
- * Parent chain for the given Arbitrum chain, can be an L1 or an L2
- */
- public readonly l1Network: L1Network | L2Network
-
/**
* In case of a chain that uses ETH as its native/gas token, this is either `undefined` or the zero address
*
- * In case of a chain that uses an ERC-20 token from the parent chain as its native/gas token, this is the address of said token on the parent chain
+ * In case of a chain that uses an ERC-20 token from the parent network as its native/gas token, this is the address of said token on the parent network
*/
public readonly nativeToken?: string
- public constructor(public readonly l2Network: L2Network) {
- this.l1Network = getParentForNetwork(l2Network)
- this.nativeToken = l2Network.nativeToken
+ public constructor(public readonly childNetwork: ArbitrumNetwork) {
+ this.nativeToken = childNetwork.nativeToken
}
/**
- * Check the signer/provider matches the l1Network, throws if not
+ * Check the signer/provider matches the parent network, throws if not
* @param sop
*/
- protected async checkL1Network(sop: SignerOrProvider): Promise {
- await SignerProviderUtils.checkNetworkMatches(sop, this.l1Network.chainID)
+ protected async checkParentNetwork(sop: SignerOrProvider): Promise {
+ await SignerProviderUtils.checkNetworkMatches(
+ sop,
+ this.childNetwork.parentChainId
+ )
}
/**
- * Check the signer/provider matches the l2Network, throws if not
+ * Check the signer/provider matches the child network, throws if not
* @param sop
*/
- protected async checkL2Network(sop: SignerOrProvider): Promise {
- await SignerProviderUtils.checkNetworkMatches(sop, this.l2Network.chainID)
+ protected async checkChildNetwork(sop: SignerOrProvider): Promise {
+ await SignerProviderUtils.checkNetworkMatches(
+ sop,
+ this.childNetwork.chainId
+ )
}
/**
@@ -77,16 +73,18 @@ export abstract class AssetBridger {
}
/**
- * Transfer assets from L1 to L2
+ * Transfer assets from parent-to-child
* @param params
*/
- public abstract deposit(params: DepositParams): Promise
+ public abstract deposit(
+ params: DepositParams
+ ): Promise
/**
- * Transfer assets from L2 to L1
+ * Transfer assets from child-to-parent
* @param params
*/
public abstract withdraw(
params: WithdrawParams
- ): Promise
+ ): Promise
}
diff --git a/src/lib/assetBridger/erc20Bridger.ts b/src/lib/assetBridger/erc20Bridger.ts
index ec30990365..5ce5210710 100644
--- a/src/lib/assetBridger/erc20Bridger.ts
+++ b/src/lib/assetBridger/erc20Bridger.ts
@@ -42,47 +42,53 @@ import { WithdrawalInitiatedEvent } from '../abi/L2ArbitrumGateway'
import { GatewaySetEvent } from '../abi/L1GatewayRouter'
import {
GasOverrides,
- L1ToL2MessageGasEstimator,
-} from '../message/L1ToL2MessageGasEstimator'
+ ParentToChildMessageGasEstimator,
+} from '../message/ParentToChildMessageGasEstimator'
import { SignerProviderUtils } from '../dataEntities/signerOrProvider'
-import { L2Network, getL2Network } from '../dataEntities/networks'
+import {
+ ArbitrumNetwork,
+ TokenBridge,
+ assertArbitrumNetworkHasTokenBridge,
+ getArbitrumNetwork,
+} from '../dataEntities/networks'
import { ArbSdkError, MissingProviderArbSdkError } from '../dataEntities/errors'
import { DISABLED_GATEWAY } from '../dataEntities/constants'
import { EventFetcher } from '../utils/eventFetcher'
import { EthDepositParams, EthWithdrawParams } from './ethBridger'
import { AssetBridger } from './assetBridger'
import {
- L1ContractCallTransaction,
- L1ContractTransaction,
- L1TransactionReceipt,
-} from '../message/L1Transaction'
+ ParentContractCallTransaction,
+ ParentContractTransaction,
+ ParentTransactionReceipt,
+} from '../message/ParentTransaction'
import {
- L2ContractTransaction,
- L2TransactionReceipt,
-} from '../message/L2Transaction'
+ ChildContractTransaction,
+ ChildTransactionReceipt,
+} from '../message/ChildTransaction'
import {
- isL1ToL2TransactionRequest,
- isL2ToL1TransactionRequest,
- L1ToL2TransactionRequest,
- L2ToL1TransactionRequest,
+ isParentToChildTransactionRequest,
+ isChildToParentTransactionRequest,
+ ChildToParentTransactionRequest,
+ ParentToChildTransactionRequest,
} from '../dataEntities/transactionRequest'
import { defaultAbiCoder } from 'ethers/lib/utils'
import { OmitTyped, RequiredPick } from '../utils/types'
import { RetryableDataTools } from '../dataEntities/retryableData'
import { EventArgs } from '../dataEntities/event'
-import { L1ToL2MessageGasParams } from '../message/L1ToL2MessageCreator'
import {
getNativeTokenDecimals,
isArbitrumChain,
scaleToNativeTokenDecimals,
} from '../utils/lib'
+import { ParentToChildMessageGasParams } from '../message/ParentToChildMessageCreator'
import { L2ERC20Gateway__factory } from '../abi/factories/L2ERC20Gateway__factory'
+import { getErc20ParentAddressFromParentToChildTxRequest } from '../utils/calldata'
export interface TokenApproveParams {
/**
- * L1 address of the ERC20 token contract
+ * Parent network address of the ERC20 token contract
*/
- erc20L1Address: string
+ erc20ParentAddress: string
/**
* Amount to approve. Defaults to max int.
*/
@@ -95,15 +101,15 @@ export interface TokenApproveParams {
export interface Erc20DepositParams extends EthDepositParams {
/**
- * An L2 provider
+ * A child provider
*/
- l2Provider: Provider
+ childProvider: Provider
/**
- * L1 address of the token ERC20 contract
+ * Parent network address of the token ERC20 contract
*/
- erc20L1Address: string
+ erc20ParentAddress: string
/**
- * L2 address of the entity receiving the funds. Defaults to the l1FromAddress
+ * Child network address of the entity receiving the funds. Defaults to the l1FromAddress
*/
destinationAddress?: string
/**
@@ -130,40 +136,44 @@ export interface Erc20DepositParams extends EthDepositParams {
export interface Erc20WithdrawParams extends EthWithdrawParams {
/**
- * L1 address of the token ERC20 contract
+ * Parent network address of the token ERC20 contract
*/
- erc20l1Address: string
+ erc20ParentAddress: string
}
-export type L1ToL2TxReqAndSignerProvider = L1ToL2TransactionRequest & {
- l1Signer: Signer
- overrides?: Overrides
-}
+export type ParentToChildTxReqAndSignerProvider =
+ ParentToChildTransactionRequest & {
+ parentSigner: Signer
+ childProvider: Provider
+ overrides?: Overrides
+ }
-export type L2ToL1TxReqAndSigner = L2ToL1TransactionRequest & {
- l2Signer: Signer
+export type ChildToParentTxReqAndSigner = ChildToParentTransactionRequest & {
+ childSigner: Signer
overrides?: Overrides
}
-type SignerTokenApproveParams = TokenApproveParams & { l1Signer: Signer }
-type ProviderTokenApproveParams = TokenApproveParams & { l1Provider: Provider }
+type SignerTokenApproveParams = TokenApproveParams & { parentSigner: Signer }
+type ProviderTokenApproveParams = TokenApproveParams & {
+ parentProvider: Provider
+}
export type ApproveParamsOrTxRequest =
| SignerTokenApproveParams
| {
txRequest: Required>
- l1Signer: Signer
+ parentSigner: Signer
overrides?: Overrides
}
/**
- * The deposit request takes the same args as the actual deposit. Except we dont require a signer object
+ * The deposit request takes the same args as the actual deposit. Except we don't require a signer object
* only a provider
*/
type DepositRequest = OmitTyped<
Erc20DepositParams,
- 'overrides' | 'l1Signer'
+ 'overrides' | 'parentSigner'
> & {
- l1Provider: Provider
+ parentProvider: Provider
/**
* Address that is depositing the assets
*/
@@ -176,69 +186,75 @@ type DefaultedDepositRequest = RequiredPick<
>
/**
- * Bridger for moving ERC20 tokens back and forth between L1 to L2
+ * Bridger for moving ERC20 tokens back and forth between parent-to-child
*/
export class Erc20Bridger extends AssetBridger<
- Erc20DepositParams | L1ToL2TxReqAndSignerProvider,
- OmitTyped | L2ToL1TransactionRequest
+ Erc20DepositParams | ParentToChildTxReqAndSignerProvider,
+ OmitTyped | ChildToParentTransactionRequest
> {
public static MAX_APPROVAL: BigNumber = MaxUint256
public static MIN_CUSTOM_DEPOSIT_GAS_LIMIT = BigNumber.from(275000)
+ public readonly childNetwork: ArbitrumNetwork & {
+ tokenBridge: TokenBridge
+ }
+
/**
- * Bridger for moving ERC20 tokens back and forth between L1 to L2
+ * Bridger for moving ERC20 tokens back and forth between parent-to-child
*/
- public constructor(l2Network: L2Network) {
- super(l2Network)
+ public constructor(childNetwork: ArbitrumNetwork) {
+ super(childNetwork)
+ assertArbitrumNetworkHasTokenBridge(childNetwork)
+ this.childNetwork = childNetwork
}
/**
- * Instantiates a new Erc20Bridger from an L2 Provider
- * @param l2Provider
+ * Instantiates a new Erc20Bridger from a child provider
+ * @param childProvider
* @returns
*/
- public static async fromProvider(l2Provider: Provider) {
- return new Erc20Bridger(await getL2Network(l2Provider))
+ public static async fromProvider(childProvider: Provider) {
+ return new Erc20Bridger(await getArbitrumNetwork(childProvider))
}
/**
- * Get the address of the l1 gateway for this token
- * @param erc20L1Address
- * @param l1Provider
+ * Get the address of the parent gateway for this token
+ * @param erc20ParentAddress
+ * @param parentProvider
* @returns
*/
- public async getL1GatewayAddress(
- erc20L1Address: string,
- l1Provider: Provider
+ public async getParentGatewayAddress(
+ erc20ParentAddress: string,
+ parentProvider: Provider
): Promise {
- await this.checkL1Network(l1Provider)
+ await this.checkParentNetwork(parentProvider)
return await L1GatewayRouter__factory.connect(
- this.l2Network.tokenBridge.l1GatewayRouter,
- l1Provider
- ).getGateway(erc20L1Address)
+ this.childNetwork.tokenBridge.parentGatewayRouter,
+ parentProvider
+ ).getGateway(erc20ParentAddress)
}
/**
- * Get the address of the l2 gateway for this token
- * @param erc20L1Address
- * @param l2Provider
+ * Get the address of the child gateway for this token
+ * @param erc20ParentAddress
+ * @param childProvider
* @returns
*/
- public async getL2GatewayAddress(
- erc20L1Address: string,
- l2Provider: Provider
+ public async getChildGatewayAddress(
+ erc20ParentAddress: string,
+ childProvider: Provider
): Promise {
- await this.checkL2Network(l2Provider)
+ await this.checkChildNetwork(childProvider)
return await L2GatewayRouter__factory.connect(
- this.l2Network.tokenBridge.l2GatewayRouter,
- l2Provider
- ).getGateway(erc20L1Address)
+ this.childNetwork.tokenBridge.childGatewayRouter,
+ childProvider
+ ).getGateway(erc20ParentAddress)
}
/**
- * Creates a transaction request for approving the custom gas token to be spent by the relevant gateway on the parent chain
+ * Creates a transaction request for approving the custom gas token to be spent by the relevant gateway on the parent network
* @param params
*/
public async getApproveGasTokenRequest(
@@ -254,7 +270,7 @@ export class Erc20Bridger extends AssetBridger<
}
/**
- * Approves the custom gas token to be spent by the relevant gateway on the parent chain
+ * Approves the custom gas token to be spent by the relevant gateway on the parent network
* @param params
*/
public async approveGasToken(
@@ -264,16 +280,18 @@ export class Erc20Bridger extends AssetBridger<
throw new Error('chain uses ETH as its native/gas token')
}
- await this.checkL1Network(params.l1Signer)
+ await this.checkParentNetwork(params.parentSigner)
const approveGasTokenRequest = this.isApproveParams(params)
? await this.getApproveGasTokenRequest({
...params,
- l1Provider: SignerProviderUtils.getProviderOrThrow(params.l1Signer),
+ parentProvider: SignerProviderUtils.getProviderOrThrow(
+ params.parentSigner
+ ),
})
: params.txRequest
- return params.l1Signer.sendTransaction({
+ return params.parentSigner.sendTransaction({
...approveGasTokenRequest,
...params.overrides,
})
@@ -289,9 +307,9 @@ export class Erc20Bridger extends AssetBridger<
params: ProviderTokenApproveParams
): Promise>> {
// you approve tokens to the gateway that the router will use
- const gatewayAddress = await this.getL1GatewayAddress(
- params.erc20L1Address,
- SignerProviderUtils.getProviderOrThrow(params.l1Provider)
+ const gatewayAddress = await this.getParentGatewayAddress(
+ params.erc20ParentAddress,
+ SignerProviderUtils.getProviderOrThrow(params.parentProvider)
)
const iErc20Interface = ERC20__factory.createInterface()
@@ -301,7 +319,7 @@ export class Erc20Bridger extends AssetBridger<
])
return {
- to: params.erc20L1Address,
+ to: params.erc20ParentAddress,
data,
value: BigNumber.from(0),
}
@@ -310,7 +328,7 @@ export class Erc20Bridger extends AssetBridger<
protected isApproveParams(
params: ApproveParamsOrTxRequest
): params is SignerTokenApproveParams {
- return (params as SignerTokenApproveParams).erc20L1Address != undefined
+ return (params as SignerTokenApproveParams).erc20ParentAddress != undefined
}
/**
@@ -321,46 +339,48 @@ export class Erc20Bridger extends AssetBridger<
public async approveToken(
params: ApproveParamsOrTxRequest
): Promise {
- await this.checkL1Network(params.l1Signer)
+ await this.checkParentNetwork(params.parentSigner)
const approveRequest = this.isApproveParams(params)
? await this.getApproveTokenRequest({
...params,
- l1Provider: SignerProviderUtils.getProviderOrThrow(params.l1Signer),
+ parentProvider: SignerProviderUtils.getProviderOrThrow(
+ params.parentSigner
+ ),
})
: params.txRequest
- return await params.l1Signer.sendTransaction({
+ return await params.parentSigner.sendTransaction({
...approveRequest,
...params.overrides,
})
}
/**
- * Get the L2 events created by a withdrawal
- * @param l2Provider
+ * Get the child network events created by a withdrawal
+ * @param childProvider
* @param gatewayAddress
- * @param l1TokenAddress
+ * @param parentTokenAddress
* @param fromAddress
* @param filter
* @returns
*/
- public async getL2WithdrawalEvents(
- l2Provider: Provider,
+ public async getWithdrawalEvents(
+ childProvider: Provider,
gatewayAddress: string,
filter: { fromBlock: BlockTag; toBlock: BlockTag },
- l1TokenAddress?: string,
+ parentTokenAddress?: string,
fromAddress?: string,
toAddress?: string
): Promise<(EventArgs & { txHash: string })[]> {
- await this.checkL2Network(l2Provider)
+ await this.checkChildNetwork(childProvider)
- const eventFetcher = new EventFetcher(l2Provider)
+ const eventFetcher = new EventFetcher(childProvider)
const events = (
await eventFetcher.getEvents(
L2ArbitrumGateway__factory,
contract =>
contract.filters.WithdrawalInitiated(
- null, // l1Token
+ null, // parentToken
fromAddress || null, // _from
toAddress || null // _to
),
@@ -368,11 +388,11 @@ export class Erc20Bridger extends AssetBridger<
)
).map(a => ({ txHash: a.transactionHash, ...a.event }))
- return l1TokenAddress
+ return parentTokenAddress
? events.filter(
log =>
log.l1Token.toLocaleLowerCase() ===
- l1TokenAddress.toLocaleLowerCase()
+ parentTokenAddress.toLocaleLowerCase()
)
: events
}
@@ -380,17 +400,17 @@ export class Erc20Bridger extends AssetBridger<
/**
* Does the provided address look like a weth gateway
* @param potentialWethGatewayAddress
- * @param l1Provider
+ * @param parentProvider
* @returns
*/
private async looksLikeWethGateway(
potentialWethGatewayAddress: string,
- l1Provider: Provider
+ parentProvider: Provider
) {
try {
const potentialWethGateway = L1WethGateway__factory.connect(
potentialWethGatewayAddress,
- l1Provider
+ parentProvider
)
await potentialWethGateway.callStatic.l1Weth()
return true
@@ -410,17 +430,17 @@ export class Erc20Bridger extends AssetBridger<
/**
* Is this a known or unknown WETH gateway
* @param gatewayAddress
- * @param l1Provider
+ * @param parentProvider
* @returns
*/
private async isWethGateway(
gatewayAddress: string,
- l1Provider: Provider
+ parentProvider: Provider
): Promise {
- const wethAddress = this.l2Network.tokenBridge.l1WethGateway
- if (this.l2Network.isCustom) {
+ const wethAddress = this.childNetwork.tokenBridge.parentWethGateway
+ if (this.childNetwork.isCustom) {
// For custom network, we do an ad-hoc check to see if it's a WETH gateway
- if (await this.looksLikeWethGateway(gatewayAddress, l1Provider)) {
+ if (await this.looksLikeWethGateway(gatewayAddress, parentProvider)) {
return true
}
// ...otherwise we directly check it against the config file
@@ -431,115 +451,125 @@ export class Erc20Bridger extends AssetBridger<
}
/**
- * Get the L2 token contract at the provided address
- * Note: This function just returns a typed ethers object for the provided address, it doesnt
+ * Get the child network token contract at the provided address
+ * Note: This function just returns a typed ethers object for the provided address, it doesn't
* check the underlying form of the contract bytecode to see if it's an erc20, and doesn't ensure the validity
* of any of the underlying functions on that contract.
- * @param l2Provider
- * @param l2TokenAddr
+ * @param childProvider
+ * @param childTokenAddr
* @returns
*/
- public getL2TokenContract(
- l2Provider: Provider,
- l2TokenAddr: string
+ public getChildTokenContract(
+ childProvider: Provider,
+ childTokenAddr: string
): L2GatewayToken {
- return L2GatewayToken__factory.connect(l2TokenAddr, l2Provider)
+ return L2GatewayToken__factory.connect(childTokenAddr, childProvider)
}
/**
- * Get the L1 token contract at the provided address
+ * Get the parent token contract at the provided address
* Note: This function just returns a typed ethers object for the provided address, it doesnt
* check the underlying form of the contract bytecode to see if it's an erc20, and doesn't ensure the validity
* of any of the underlying functions on that contract.
- * @param l1Provider
- * @param l1TokenAddr
+ * @param parentProvider
+ * @param parentTokenAddr
* @returns
*/
- public getL1TokenContract(l1Provider: Provider, l1TokenAddr: string): ERC20 {
- return ERC20__factory.connect(l1TokenAddr, l1Provider)
+ public getParentTokenContract(
+ parentProvider: Provider,
+ parentTokenAddr: string
+ ): ERC20 {
+ return ERC20__factory.connect(parentTokenAddr, parentProvider)
}
/**
- * Get the corresponding L2 for the provided L1 token
- * @param erc20L1Address
- * @param l1Provider
+ * Get the corresponding child network token address for the provided parent network token
+ * @param erc20ParentAddress
+ * @param parentProvider
* @returns
*/
- public async getL2ERC20Address(
- erc20L1Address: string,
- l1Provider: Provider
+ public async getChildErc20Address(
+ erc20ParentAddress: string,
+ parentProvider: Provider
): Promise {
- await this.checkL1Network(l1Provider)
+ await this.checkParentNetwork(parentProvider)
- const l1GatewayRouter = L1GatewayRouter__factory.connect(
- this.l2Network.tokenBridge.l1GatewayRouter,
- l1Provider
+ const parentGatewayRouter = L1GatewayRouter__factory.connect(
+ this.childNetwork.tokenBridge.parentGatewayRouter,
+ parentProvider
)
- return await l1GatewayRouter.functions
- .calculateL2TokenAddress(erc20L1Address)
+ return await parentGatewayRouter.functions
+ .calculateL2TokenAddress(erc20ParentAddress)
.then(([res]) => res)
}
/**
- * Get the corresponding L1 for the provided L2 token
- * Validates the returned address against the l2 router to ensure it is correctly mapped to the provided erc20L2Address
- * @param erc20L2Address
- * @param l2Provider
+ * Get the corresponding parent network address for the provided child network token
+ * Validates the returned address against the child network router to ensure it is correctly mapped to the provided erc20ChildChainAddress
+ * @param erc20ChildChainAddress
+ * @param childProvider
* @returns
*/
- public async getL1ERC20Address(
- erc20L2Address: string,
- l2Provider: Provider
+ public async getParentErc20Address(
+ erc20ChildChainAddress: string,
+ childProvider: Provider
): Promise {
- await this.checkL2Network(l2Provider)
+ await this.checkChildNetwork(childProvider)
- // L2 WETH contract doesn't have the l1Address method on it
+ // child network WETH contract doesn't have the parentAddress method on it
if (
- erc20L2Address.toLowerCase() ===
- this.l2Network.tokenBridge.l2Weth.toLowerCase()
+ erc20ChildChainAddress.toLowerCase() ===
+ this.childNetwork.tokenBridge.childWeth.toLowerCase()
) {
- return this.l2Network.tokenBridge.l1Weth
+ return this.childNetwork.tokenBridge.parentWeth
}
- const arbERC20 = L2GatewayToken__factory.connect(erc20L2Address, l2Provider)
- const l1Address = await arbERC20.functions.l1Address().then(([res]) => res)
+ const arbERC20 = L2GatewayToken__factory.connect(
+ erc20ChildChainAddress,
+ childProvider
+ )
+ const parentAddress = await arbERC20.functions
+ .l1Address()
+ .then(([res]) => res)
- // check that this l1 address is indeed registered to this l2 token
- const l2GatewayRouter = L2GatewayRouter__factory.connect(
- this.l2Network.tokenBridge.l2GatewayRouter,
- l2Provider
+ // check that this l1 address is indeed registered to this child token
+ const childGatewayRouter = L2GatewayRouter__factory.connect(
+ this.childNetwork.tokenBridge.childGatewayRouter,
+ childProvider
)
- const l2Address = await l2GatewayRouter.calculateL2TokenAddress(l1Address)
- if (l2Address.toLowerCase() !== erc20L2Address.toLowerCase()) {
+ const childAddress = await childGatewayRouter.calculateL2TokenAddress(
+ parentAddress
+ )
+ if (childAddress.toLowerCase() !== erc20ChildChainAddress.toLowerCase()) {
throw new ArbSdkError(
- `Unexpected l1 address. L1 address from token is not registered to the provided l2 address. ${l1Address} ${l2Address} ${erc20L2Address}`
+ `Unexpected parent address. Parent address from token is not registered to the provided child address. ${parentAddress} ${childAddress} ${erc20ChildChainAddress}`
)
}
- return l1Address
+ return parentAddress
}
/**
* Whether the token has been disabled on the router
- * @param l1TokenAddress
- * @param l1Provider
+ * @param parentTokenAddress
+ * @param parentProvider
* @returns
*/
- public async l1TokenIsDisabled(
- l1TokenAddress: string,
- l1Provider: Provider
+ public async isDepositDisabled(
+ parentTokenAddress: string,
+ parentProvider: Provider
): Promise {
- await this.checkL1Network(l1Provider)
+ await this.checkParentNetwork(parentProvider)
- const l1GatewayRouter = L1GatewayRouter__factory.connect(
- this.l2Network.tokenBridge.l1GatewayRouter,
- l1Provider
+ const parentGatewayRouter = L1GatewayRouter__factory.connect(
+ this.childNetwork.tokenBridge.parentGatewayRouter,
+ parentProvider
)
return (
- (await l1GatewayRouter.l1TokenToGateway(l1TokenAddress)) ===
+ (await parentGatewayRouter.l1TokenToGateway(parentTokenAddress)) ===
DISABLED_GATEWAY
)
}
@@ -561,7 +591,7 @@ export class Erc20Bridger extends AssetBridger<
* @returns
*/
private getDepositRequestCallValue(
- depositParams: OmitTyped
+ depositParams: OmitTyped
) {
// the call value should be zero when paying with a custom gas token,
// as the fee amount is packed inside the last parameter (`data`) of the call to `outboundTransfer`, see `getDepositRequestOutboundTransferInnerData`
@@ -569,9 +599,9 @@ export class Erc20Bridger extends AssetBridger<
return constants.Zero
}
- // we dont include the l2 call value for token deposits because
+ // we dont include the child call value for token deposits because
// they either have 0 call value, or their call value is withdrawn from
- // a contract by the gateway (weth). So in both of these cases the l2 call value
+ // a contract by the gateway (weth). So in both of these cases the child call value
// is not actually deposited in the value field
return depositParams.gasLimit
.mul(depositParams.maxFeePerGas)
@@ -584,7 +614,7 @@ export class Erc20Bridger extends AssetBridger<
* @returns
*/
private getDepositRequestOutboundTransferInnerData(
- depositParams: OmitTyped,
+ depositParams: OmitTyped,
decimals: number
) {
if (!this.nativeTokenIsEth) {
@@ -624,27 +654,28 @@ export class Erc20Bridger extends AssetBridger<
*/
public async getDepositRequest(
params: DepositRequest
- ): Promise {
- await this.checkL1Network(params.l1Provider)
- await this.checkL2Network(params.l2Provider)
+ ): Promise {
+ await this.checkParentNetwork(params.parentProvider)
+ await this.checkChildNetwork(params.childProvider)
const defaultedParams = this.applyDefaults(params)
const {
amount,
destinationAddress,
- erc20L1Address,
- l1Provider,
- l2Provider,
+ erc20ParentAddress,
+ parentProvider,
+ childProvider,
retryableGasOverrides,
} = defaultedParams
- const l1GatewayAddress = await this.getL1GatewayAddress(
- erc20L1Address,
- l1Provider
+ const parentGatewayAddress = await this.getParentGatewayAddress(
+ erc20ParentAddress,
+ parentProvider
)
let tokenGasOverrides: GasOverrides | undefined = retryableGasOverrides
-
// we also add a hardcoded minimum gas limit for custom gateway deposits
- if (l1GatewayAddress === this.l2Network.tokenBridge.l1CustomGateway) {
+ if (
+ parentGatewayAddress === this.childNetwork.tokenBridge.parentCustomGateway
+ ) {
if (!tokenGasOverrides) tokenGasOverrides = {}
if (!tokenGasOverrides.gasLimit) tokenGasOverrides.gasLimit = {}
if (!tokenGasOverrides.gasLimit.min) {
@@ -654,12 +685,12 @@ export class Erc20Bridger extends AssetBridger<
}
const decimals = await getNativeTokenDecimals({
- l1Provider,
- l2Network: this.l2Network,
+ parentProvider,
+ childNetwork: this.childNetwork,
})
const depositFunc = (
- depositParams: OmitTyped
+ depositParams: OmitTyped
) => {
depositParams.maxSubmissionCost =
params.maxSubmissionCost || depositParams.maxSubmissionCost
@@ -673,7 +704,7 @@ export class Erc20Bridger extends AssetBridger<
const functionData =
defaultedParams.excessFeeRefundAddress !== defaultedParams.from
? iGatewayRouter.encodeFunctionData('outboundTransferCustomRefund', [
- erc20L1Address,
+ erc20ParentAddress,
defaultedParams.excessFeeRefundAddress,
destinationAddress,
amount,
@@ -682,7 +713,7 @@ export class Erc20Bridger extends AssetBridger<
innerData,
])
: iGatewayRouter.encodeFunctionData('outboundTransfer', [
- erc20L1Address,
+ erc20ParentAddress,
destinationAddress,
amount,
depositParams.gasLimit,
@@ -692,22 +723,22 @@ export class Erc20Bridger extends AssetBridger<
return {
data: functionData,
- to: this.l2Network.tokenBridge.l1GatewayRouter,
+ to: this.childNetwork.tokenBridge.parentGatewayRouter,
from: defaultedParams.from,
value: this.getDepositRequestCallValue(depositParams),
}
}
- const gasEstimator = new L1ToL2MessageGasEstimator(l2Provider)
+ const gasEstimator = new ParentToChildMessageGasEstimator(childProvider)
const estimates = await gasEstimator.populateFunctionParams(
depositFunc,
- l1Provider,
+ parentProvider,
tokenGasOverrides
)
return {
txRequest: {
- to: this.l2Network.tokenBridge.l1GatewayRouter,
+ to: this.childNetwork.tokenBridge.parentGatewayRouter,
data: estimates.data,
value: estimates.value,
from: params.from,
@@ -719,10 +750,10 @@ export class Erc20Bridger extends AssetBridger<
isValid: async () => {
const reEstimates = await gasEstimator.populateFunctionParams(
depositFunc,
- l1Provider,
+ parentProvider,
tokenGasOverrides
)
- return L1ToL2MessageGasEstimator.isValid(
+ return ParentToChildMessageGasEstimator.isValid(
estimates.estimates,
reEstimates.estimates
)
@@ -731,39 +762,60 @@ export class Erc20Bridger extends AssetBridger<
}
/**
- * Execute a token deposit from L1 to L2
+ * Execute a token deposit from parent to child network
* @param params
* @returns
*/
public async deposit(
- params: Erc20DepositParams | L1ToL2TxReqAndSignerProvider
- ): Promise {
- await this.checkL1Network(params.l1Signer)
+ params: Erc20DepositParams | ParentToChildTxReqAndSignerProvider
+ ): Promise {
+ await this.checkParentNetwork(params.parentSigner)
// Although the types prevent should alert callers that value is not
// a valid override, it is possible that they pass it in anyway as it's a common override
// We do a safety check here
if ((params.overrides as PayableOverrides | undefined)?.value) {
throw new ArbSdkError(
- 'L1 call value should be set through l1CallValue param'
+ 'Parent call value should be set through `l1CallValue` param'
+ )
+ }
+
+ const parentProvider = SignerProviderUtils.getProviderOrThrow(
+ params.parentSigner
+ )
+
+ const erc20ParentAddress = isParentToChildTransactionRequest(params)
+ ? getErc20ParentAddressFromParentToChildTxRequest(params)
+ : params.erc20ParentAddress
+
+ const isRegistered = await this.isRegistered({
+ erc20ParentAddress,
+ parentProvider,
+ childProvider: params.childProvider,
+ })
+
+ if (!isRegistered) {
+ const parentChainId = (await parentProvider.getNetwork()).chainId
+
+ throw new Error(
+ `Token ${erc20ParentAddress} on chain ${parentChainId} is not registered on the gateways`
)
}
- const l1Provider = SignerProviderUtils.getProviderOrThrow(params.l1Signer)
- const tokenDeposit = isL1ToL2TransactionRequest(params)
+ const tokenDeposit = isParentToChildTransactionRequest(params)
? params
: await this.getDepositRequest({
...params,
- l1Provider,
- from: await params.l1Signer.getAddress(),
+ parentProvider,
+ from: await params.parentSigner.getAddress(),
})
- const tx = await params.l1Signer.sendTransaction({
+ const tx = await params.parentSigner.sendTransaction({
...tokenDeposit.txRequest,
...params.overrides,
})
- return L1TransactionReceipt.monkeyPatchContractCallWait(tx)
+ return ParentTransactionReceipt.monkeyPatchContractCallWait(tx)
}
/**
@@ -773,7 +825,7 @@ export class Erc20Bridger extends AssetBridger<
*/
public async getWithdrawalRequest(
params: Erc20WithdrawParams
- ): Promise {
+ ): Promise {
const to = params.destinationAddress
const routerInterface = L2GatewayRouter__factory.createInterface()
@@ -788,7 +840,7 @@ export class Erc20Bridger extends AssetBridger<
): string
}
).encodeFunctionData('outboundTransfer(address,address,uint256,bytes)', [
- params.erc20l1Address,
+ params.erc20ParentAddress,
to,
params.amount,
'0x',
@@ -797,13 +849,13 @@ export class Erc20Bridger extends AssetBridger<
return {
txRequest: {
data: functionData,
- to: this.l2Network.tokenBridge.l2GatewayRouter,
+ to: this.childNetwork.tokenBridge.childGatewayRouter,
value: BigNumber.from(0),
from: params.from,
},
// todo: do proper estimation
- estimateL1GasLimit: async (l1Provider: Provider) => {
- if (await isArbitrumChain(l1Provider)) {
+ estimateParentGasLimit: async (parentProvider: Provider) => {
+ if (await isArbitrumChain(parentProvider)) {
// values for L3 are dependent on the L1 base fee, so hardcoding can never be accurate
// however, this is only an estimate used for display, so should be good enough
//
@@ -811,14 +863,17 @@ export class Erc20Bridger extends AssetBridger<
return BigNumber.from(8_000_000)
}
- const l1GatewayAddress = await this.getL1GatewayAddress(
- params.erc20l1Address,
- l1Provider
+ const parentGatewayAddress = await this.getParentGatewayAddress(
+ params.erc20ParentAddress,
+ parentProvider
)
- // The WETH gateway is the only deposit that requires callvalue in the L2 user-tx (i.e., the recently un-wrapped ETH)
+ // The WETH gateway is the only deposit that requires callvalue in the Child user-tx (i.e., the recently un-wrapped ETH)
// Here we check if this is a WETH deposit, and include the callvalue for the gas estimate query if so
- const isWeth = await this.isWethGateway(l1GatewayAddress, l1Provider)
+ const isWeth = await this.isWethGateway(
+ parentGatewayAddress,
+ parentProvider
+ )
// measured 157421 - add some padding
return isWeth ? BigNumber.from(190000) : BigNumber.from(160000)
@@ -827,86 +882,83 @@ export class Erc20Bridger extends AssetBridger<
}
/**
- * Withdraw tokens from L2 to L1
+ * Withdraw tokens from child to parent network
* @param params
* @returns
*/
public async withdraw(
params:
- | (OmitTyped & { l2Signer: Signer })
- | L2ToL1TxReqAndSigner
- ): Promise {
- if (!SignerProviderUtils.signerHasProvider(params.l2Signer)) {
- throw new MissingProviderArbSdkError('l2Signer')
+ | (OmitTyped & { childSigner: Signer })
+ | ChildToParentTxReqAndSigner
+ ): Promise {
+ if (!SignerProviderUtils.signerHasProvider(params.childSigner)) {
+ throw new MissingProviderArbSdkError('childSigner')
}
- await this.checkL2Network(params.l2Signer)
+ await this.checkChildNetwork(params.childSigner)
- const withdrawalRequest = isL2ToL1TransactionRequest<
- OmitTyped & { l2Signer: Signer }
+ const withdrawalRequest = isChildToParentTransactionRequest<
+ OmitTyped & { childSigner: Signer }
>(params)
? params
: await this.getWithdrawalRequest({
...params,
- from: await params.l2Signer.getAddress(),
+ from: await params.childSigner.getAddress(),
})
- const tx = await params.l2Signer.sendTransaction({
+ const tx = await params.childSigner.sendTransaction({
...withdrawalRequest.txRequest,
...params.overrides,
})
- return L2TransactionReceipt.monkeyPatchWait(tx)
+ return ChildTransactionReceipt.monkeyPatchWait(tx)
}
/**
* Checks if the token has been properly registered on both gateways. Mostly useful for tokens that use a custom gateway.
- * @param erc20L1Address
- * @param l1Provider
- * @param l2Provider
+ *
+ * @param {Object} params
+ * @param {string} params.erc20ParentAddress
+ * @param {Provider} params.parentProvider
+ * @param {Provider} params.childProvider
* @returns
*/
public async isRegistered({
- erc20L1Address,
- l1Provider,
- l2Provider,
+ erc20ParentAddress,
+ parentProvider,
+ childProvider,
}: {
- erc20L1Address: string
- l1Provider: Provider
- l2Provider: Provider
+ erc20ParentAddress: string
+ parentProvider: Provider
+ childProvider: Provider
}) {
- const l1StandardGatewayAddressFromChainConfig =
- this.l2Network.tokenBridge.l1ERC20Gateway
+ const parentStandardGatewayAddressFromChainConfig =
+ this.childNetwork.tokenBridge.parentErc20Gateway
- const l1GatewayAddressFromL1GatewayRouter = await this.getL1GatewayAddress(
- erc20L1Address,
- l1Provider
- )
+ const parentGatewayAddressFromParentGatewayRouter =
+ await this.getParentGatewayAddress(erc20ParentAddress, parentProvider)
// token uses standard gateway; no need to check further
if (
- l1StandardGatewayAddressFromChainConfig.toLowerCase() ===
- l1GatewayAddressFromL1GatewayRouter.toLowerCase()
+ parentStandardGatewayAddressFromChainConfig.toLowerCase() ===
+ parentGatewayAddressFromParentGatewayRouter.toLowerCase()
) {
return true
}
- const tokenL2AddressFromL1GatewayRouter = await this.getL2ERC20Address(
- erc20L1Address,
- l1Provider
- )
+ const childTokenAddressFromParentGatewayRouter =
+ await this.getChildErc20Address(erc20ParentAddress, parentProvider)
- const l2GatewayAddressFromL2Router = await this.getL2GatewayAddress(
- erc20L1Address,
- l2Provider
- )
+ const childGatewayAddressFromChildRouter =
+ await this.getChildGatewayAddress(erc20ParentAddress, childProvider)
- const l2AddressFromL2Gateway = await L2ERC20Gateway__factory.connect(
- l2GatewayAddressFromL2Router,
- l2Provider
- ).calculateL2TokenAddress(erc20L1Address)
+ const childTokenAddressFromChildGateway =
+ await L2ERC20Gateway__factory.connect(
+ childGatewayAddressFromChildRouter,
+ childProvider
+ ).calculateL2TokenAddress(erc20ParentAddress)
return (
- tokenL2AddressFromL1GatewayRouter.toLowerCase() ===
- l2AddressFromL2Gateway.toLowerCase()
+ childTokenAddressFromParentGatewayRouter.toLowerCase() ===
+ childTokenAddressFromChildGateway.toLowerCase()
)
}
}
@@ -936,7 +988,7 @@ export class AdminErc20Bridger extends Erc20Bridger {
const iErc20Interface = ERC20__factory.createInterface()
const data = iErc20Interface.encodeFunctionData('approve', [
- params.erc20L1Address,
+ params.erc20ParentAddress,
params.amount || Erc20Bridger.MAX_APPROVAL,
])
@@ -954,16 +1006,18 @@ export class AdminErc20Bridger extends Erc20Bridger {
throw new Error('chain uses ETH as its native/gas token')
}
- await this.checkL1Network(params.l1Signer)
+ await this.checkParentNetwork(params.parentSigner)
const approveGasTokenRequest = this.isApproveParams(params)
? this.getApproveGasTokenForCustomTokenRegistrationRequest({
...params,
- l1Provider: SignerProviderUtils.getProviderOrThrow(params.l1Signer),
+ parentProvider: SignerProviderUtils.getProviderOrThrow(
+ params.parentSigner
+ ),
})
: params.txRequest
- return params.l1Signer.sendTransaction({
+ return params.parentSigner.sendTransaction({
...approveGasTokenRequest,
...params.overrides,
})
@@ -972,78 +1026,85 @@ export class AdminErc20Bridger extends Erc20Bridger {
/**
* Register a custom token on the Arbitrum bridge
* See https://developer.offchainlabs.com/docs/bridging_assets#the-arbitrum-generic-custom-gateway for more details
- * @param l1TokenAddress Address of the already deployed l1 token. Must inherit from https://developer.offchainlabs.com/docs/sol_contract_docs/md_docs/arb-bridge-peripherals/tokenbridge/ethereum/icustomtoken.
- * @param l2TokenAddress Address of the already deployed l2 token. Must inherit from https://developer.offchainlabs.com/docs/sol_contract_docs/md_docs/arb-bridge-peripherals/tokenbridge/arbitrum/iarbtoken.
- * @param l1Signer The signer with the rights to call registerTokenOnL2 on the l1 token
- * @param l2Provider Arbitrum rpc provider
+ * @param parentTokenAddress Address of the already deployed parent token. Must inherit from https://developer.offchainlabs.com/docs/sol_contract_docs/md_docs/arb-bridge-peripherals/tokenbridge/ethereum/icustomtoken.
+ * @param childTokenAddress Address of the already deployed child token. Must inherit from https://developer.offchainlabs.com/docs/sol_contract_docs/md_docs/arb-bridge-peripherals/tokenbridge/arbitrum/iarbtoken.
+ * @param parentSigner The signer with the rights to call `registerTokenOnL2` on the parent token
+ * @param childProvider Arbitrum rpc provider
* @returns
*/
public async registerCustomToken(
- l1TokenAddress: string,
- l2TokenAddress: string,
- l1Signer: Signer,
- l2Provider: Provider
- ): Promise {
- if (!SignerProviderUtils.signerHasProvider(l1Signer)) {
- throw new MissingProviderArbSdkError('l1Signer')
+ parentTokenAddress: string,
+ childTokenAddress: string,
+ parentSigner: Signer,
+ childProvider: Provider
+ ): Promise {
+ if (!SignerProviderUtils.signerHasProvider(parentSigner)) {
+ throw new MissingProviderArbSdkError('parentSigner')
}
- await this.checkL1Network(l1Signer)
- await this.checkL2Network(l2Provider)
+ await this.checkParentNetwork(parentSigner)
+ await this.checkChildNetwork(childProvider)
- const l1Provider = l1Signer.provider!
- const l1SenderAddress = await l1Signer.getAddress()
+ const parentProvider = parentSigner.provider!
+ const parentSenderAddress = await parentSigner.getAddress()
- const l1Token = ICustomToken__factory.connect(l1TokenAddress, l1Signer)
- const l2Token = IArbToken__factory.connect(l2TokenAddress, l2Provider)
+ const parentToken = ICustomToken__factory.connect(
+ parentTokenAddress,
+ parentSigner
+ )
+ const childToken = IArbToken__factory.connect(
+ childTokenAddress,
+ childProvider
+ )
// sanity checks
- await l1Token.deployed()
- await l2Token.deployed()
+ await parentToken.deployed()
+ await childToken.deployed()
if (!this.nativeTokenIsEth) {
const nativeTokenContract = ERC20__factory.connect(
this.nativeToken!,
- l1Provider
+ parentProvider
)
const allowance = await nativeTokenContract.allowance(
- l1SenderAddress,
- l1Token.address
+ parentSenderAddress,
+ parentToken.address
)
- const maxFeePerGasOnL2 = (await l2Provider.getFeeData()).maxFeePerGas
- const maxFeePerGasOnL2WithBuffer = this.percentIncrease(
- maxFeePerGasOnL2!,
+ const maxFeePerGasOnChild = (await childProvider.getFeeData())
+ .maxFeePerGas
+ const maxFeePerGasOnChildWithBuffer = this.percentIncrease(
+ maxFeePerGasOnChild!,
BigNumber.from(500)
)
// hardcode gas limit to 60k
const estimatedGasFee = BigNumber.from(60_000).mul(
- maxFeePerGasOnL2WithBuffer
+ maxFeePerGasOnChildWithBuffer
)
if (allowance.lt(estimatedGasFee)) {
throw new Error(
- `Insufficient allowance. Please increase spending for: owner - ${l1SenderAddress}, spender - ${l1Token.address}.`
+ `Insufficient allowance. Please increase spending for: owner - ${parentSenderAddress}, spender - ${parentToken.address}.`
)
}
}
- const l1AddressFromL2 = await l2Token.l1Address()
- if (l1AddressFromL2 !== l1TokenAddress) {
+ const parentAddressFromChild = await childToken.l1Address()
+ if (parentAddressFromChild !== parentTokenAddress) {
throw new ArbSdkError(
- `L2 token does not have l1 address set. Set address: ${l1AddressFromL2}, expected address: ${l1TokenAddress}.`
+ `child token does not have parent address set. Set address: ${parentAddressFromChild}, expected address: ${parentTokenAddress}.`
)
}
const nativeTokenDecimals = await getNativeTokenDecimals({
- l1Provider,
- l2Network: this.l2Network,
+ parentProvider,
+ childNetwork: this.childNetwork,
})
type GasParams = {
maxSubmissionCost: BigNumber
gasLimit: BigNumber
}
- const from = await l1Signer.getAddress()
+ const from = await parentSigner.getAddress()
const encodeFuncData = (
setTokenGas: GasParams,
setGatewayGas: GasParams,
@@ -1064,37 +1125,40 @@ export class AdminErc20Bridger extends Erc20Bridger {
.mul(doubleFeePerGas)
.add(setGatewayGas.maxSubmissionCost)
- const data = l1Token.interface.encodeFunctionData('registerTokenOnL2', [
- l2TokenAddress,
- setTokenGas.maxSubmissionCost,
- setGatewayGas.maxSubmissionCost,
- setTokenGas.gasLimit,
- setGatewayGas.gasLimit,
- doubleFeePerGas,
- scaleToNativeTokenDecimals({
- amount: setTokenDeposit,
- decimals: nativeTokenDecimals,
- }),
- scaleToNativeTokenDecimals({
- amount: setGatewayDeposit,
- decimals: nativeTokenDecimals,
- }),
- l1SenderAddress,
- ])
+ const data = parentToken.interface.encodeFunctionData(
+ 'registerTokenOnL2',
+ [
+ parentTokenAddress,
+ setTokenGas.maxSubmissionCost,
+ setGatewayGas.maxSubmissionCost,
+ setTokenGas.gasLimit,
+ setGatewayGas.gasLimit,
+ doubleFeePerGas,
+ scaleToNativeTokenDecimals({
+ amount: setTokenDeposit,
+ decimals: nativeTokenDecimals,
+ }),
+ scaleToNativeTokenDecimals({
+ amount: setGatewayDeposit,
+ decimals: nativeTokenDecimals,
+ }),
+ parentSenderAddress,
+ ]
+ )
return {
data,
value: this.nativeTokenIsEth
? setTokenDeposit.add(setGatewayDeposit)
: BigNumber.from(0),
- to: l1Token.address,
+ to: parentToken.address,
from,
}
}
- const gEstimator = new L1ToL2MessageGasEstimator(l2Provider)
+ const gEstimator = new ParentToChildMessageGasEstimator(childProvider)
const setTokenEstimates2 = await gEstimator.populateFunctionParams(
- (params: OmitTyped) =>
+ (params: OmitTyped) =>
encodeFuncData(
{
gasLimit: params.gasLimit,
@@ -1106,11 +1170,11 @@ export class AdminErc20Bridger extends Erc20Bridger {
},
params.maxFeePerGas
),
- l1Provider
+ parentProvider
)
const setGatewayEstimates2 = await gEstimator.populateFunctionParams(
- (params: OmitTyped) =>
+ (params: OmitTyped) =>
encodeFuncData(
{
gasLimit: setTokenEstimates2.estimates.gasLimit,
@@ -1122,103 +1186,107 @@ export class AdminErc20Bridger extends Erc20Bridger {
},
params.maxFeePerGas
),
- l1Provider
+ parentProvider
)
- const registerTx = await l1Signer.sendTransaction({
- to: l1Token.address,
+ const registerTx = await parentSigner.sendTransaction({
+ to: parentToken.address,
data: setGatewayEstimates2.data,
value: setGatewayEstimates2.value,
})
- return L1TransactionReceipt.monkeyPatchWait(registerTx)
+ return ParentTransactionReceipt.monkeyPatchWait(registerTx)
}
/**
- * Get all the gateway set events on the L1 gateway router
- * @param l1Provider
- * @param customNetworkL1GatewayRouter
- * @returns
+ * Get all the gateway set events on the Parent gateway router
+ * @param parentProvider The provider for the parent network
+ * @param filter An object containing fromBlock and toBlock to filter events
+ * @returns An array of GatewaySetEvent event arguments
*/
- public async getL1GatewaySetEvents(
- l1Provider: Provider,
+ public async getParentGatewaySetEvents(
+ parentProvider: Provider,
filter: { fromBlock: BlockTag; toBlock: BlockTag }
): Promise[]> {
- await this.checkL1Network(l1Provider)
+ await this.checkParentNetwork(parentProvider)
- const l1GatewayRouterAddress = this.l2Network.tokenBridge.l1GatewayRouter
- const eventFetcher = new EventFetcher(l1Provider)
+ const parentGatewayRouterAddress =
+ this.childNetwork.tokenBridge.parentGatewayRouter
+ const eventFetcher = new EventFetcher(parentProvider)
return (
await eventFetcher.getEvents(
L1GatewayRouter__factory,
t => t.filters.GatewaySet(),
- { ...filter, address: l1GatewayRouterAddress }
+ { ...filter, address: parentGatewayRouterAddress }
)
).map(a => a.event)
}
/**
- * Get all the gateway set events on the L2 gateway router
- * @param l1Provider
- * @param customNetworkL1GatewayRouter
- * @returns
+ * Get all the gateway set events on the child gateway router
+ * @param childProvider The provider for the child network
+ * @param filter An object containing fromBlock and toBlock to filter events
+ * @param customNetworkChildGatewayRouter Optional address of the custom network child gateway router
+ * @returns An array of GatewaySetEvent event arguments
+ * @throws {ArbSdkError} If the network is custom and customNetworkChildGatewayRouter is not provided
*/
- public async getL2GatewaySetEvents(
- l2Provider: Provider,
+ public async getChildGatewaySetEvents(
+ childProvider: Provider,
filter: { fromBlock: BlockTag; toBlock: BlockTag },
- customNetworkL2GatewayRouter?: string
+ customNetworkChildGatewayRouter?: string
): Promise[]> {
- if (this.l2Network.isCustom && !customNetworkL2GatewayRouter) {
+ if (this.childNetwork.isCustom && !customNetworkChildGatewayRouter) {
throw new ArbSdkError(
- 'Must supply customNetworkL2GatewayRouter for custom network '
+ 'Must supply customNetworkChildGatewayRouter for custom network '
)
}
- await this.checkL2Network(l2Provider)
+ await this.checkChildNetwork(childProvider)
- const l2GatewayRouterAddress =
- customNetworkL2GatewayRouter || this.l2Network.tokenBridge.l2GatewayRouter
+ const childGatewayRouterAddress =
+ customNetworkChildGatewayRouter ||
+ this.childNetwork.tokenBridge.childGatewayRouter
- const eventFetcher = new EventFetcher(l2Provider)
+ const eventFetcher = new EventFetcher(childProvider)
return (
await eventFetcher.getEvents(
L2GatewayRouter__factory,
t => t.filters.GatewaySet(),
- { ...filter, address: l2GatewayRouterAddress }
+ { ...filter, address: childGatewayRouterAddress }
)
).map(a => a.event)
}
/**
* Register the provided token addresses against the provided gateways
- * @param l1Signer
- * @param l2Provider
+ * @param parentSigner
+ * @param childProvider
* @param tokenGateways
* @returns
*/
public async setGateways(
- l1Signer: Signer,
- l2Provider: Provider,
+ parentSigner: Signer,
+ childProvider: Provider,
tokenGateways: TokenAndGateway[],
options?: GasOverrides
- ): Promise {
- if (!SignerProviderUtils.signerHasProvider(l1Signer)) {
- throw new MissingProviderArbSdkError('l1Signer')
+ ): Promise {
+ if (!SignerProviderUtils.signerHasProvider(parentSigner)) {
+ throw new MissingProviderArbSdkError('parentSigner')
}
- await this.checkL1Network(l1Signer)
- await this.checkL2Network(l2Provider)
+ await this.checkParentNetwork(parentSigner)
+ await this.checkChildNetwork(childProvider)
- const from = await l1Signer.getAddress()
+ const from = await parentSigner.getAddress()
- const l1GatewayRouter = L1GatewayRouter__factory.connect(
- this.l2Network.tokenBridge.l1GatewayRouter,
- l1Signer
+ const parentGatewayRouter = L1GatewayRouter__factory.connect(
+ this.childNetwork.tokenBridge.parentGatewayRouter,
+ parentSigner
)
const setGatewaysFunc = (
- params: OmitTyped
+ params: OmitTyped
) => {
return {
- data: l1GatewayRouter.interface.encodeFunctionData('setGateways', [
+ data: parentGatewayRouter.interface.encodeFunctionData('setGateways', [
tokenGateways.map(tG => tG.tokenAddr),
tokenGateways.map(tG => tG.gatewayAddr),
params.gasLimit,
@@ -1229,22 +1297,22 @@ export class AdminErc20Bridger extends Erc20Bridger {
value: params.gasLimit
.mul(params.maxFeePerGas)
.add(params.maxSubmissionCost),
- to: l1GatewayRouter.address,
+ to: parentGatewayRouter.address,
}
}
- const gEstimator = new L1ToL2MessageGasEstimator(l2Provider)
+ const gEstimator = new ParentToChildMessageGasEstimator(childProvider)
const estimates = await gEstimator.populateFunctionParams(
setGatewaysFunc,
- l1Signer.provider,
+ parentSigner.provider,
options
)
- const res = await l1Signer.sendTransaction({
+ const res = await parentSigner.sendTransaction({
to: estimates.to,
data: estimates.data,
value: estimates.estimates.deposit,
})
- return L1TransactionReceipt.monkeyPatchContractCallWait(res)
+ return ParentTransactionReceipt.monkeyPatchContractCallWait(res)
}
}
diff --git a/src/lib/assetBridger/ethBridger.ts b/src/lib/assetBridger/ethBridger.ts
index ad44c8cdd1..4f6c03bbfd 100644
--- a/src/lib/assetBridger/ethBridger.ts
+++ b/src/lib/assetBridger/ethBridger.ts
@@ -27,26 +27,26 @@ import { ArbSys__factory } from '../abi/factories/ArbSys__factory'
import { ARB_SYS_ADDRESS } from '../dataEntities/constants'
import { AssetBridger } from './assetBridger'
import {
- L1EthDepositTransaction,
- L1ContractCallTransaction,
- L1TransactionReceipt,
-} from '../message/L1Transaction'
+ ParentEthDepositTransaction,
+ ParentContractCallTransaction,
+ ParentTransactionReceipt,
+} from '../message/ParentTransaction'
import {
- L2ContractTransaction,
- L2TransactionReceipt,
-} from '../message/L2Transaction'
-import { L1ToL2MessageCreator } from '../message/L1ToL2MessageCreator'
-import { GasOverrides } from '../message/L1ToL2MessageGasEstimator'
+ ChildContractTransaction,
+ ChildTransactionReceipt,
+} from '../message/ChildTransaction'
+import { ParentToChildMessageCreator } from '../message/ParentToChildMessageCreator'
+import { GasOverrides } from '../message/ParentToChildMessageGasEstimator'
import {
- isL1ToL2TransactionRequest,
- isL2ToL1TransactionRequest,
- L1ToL2TransactionRequest,
- L2ToL1TransactionRequest,
+ isParentToChildTransactionRequest,
+ isChildToParentTransactionRequest,
+ ParentToChildTransactionRequest,
+ ChildToParentTransactionRequest,
} from '../dataEntities/transactionRequest'
import { OmitTyped } from '../utils/types'
import { SignerProviderUtils } from '../dataEntities/signerOrProvider'
import { MissingProviderArbSdkError } from '../dataEntities/errors'
-import { getL2Network } from '../dataEntities/networks'
+import { getArbitrumNetwork } from '../dataEntities/networks'
import { ERC20__factory } from '../abi/factories/ERC20__factory'
import {
getNativeTokenDecimals,
@@ -80,8 +80,8 @@ export type ApproveGasTokenParamsOrTxRequest =
| ApproveGasTokenParams
| ApproveGasTokenTxRequest
-type WithL1Signer = T & {
- l1Signer: Signer
+type WithParentSigner = T & {
+ parentSigner: Signer
}
export interface EthWithdrawParams {
@@ -90,7 +90,7 @@ export interface EthWithdrawParams {
*/
amount: BigNumber
/**
- * The L1 address to receive the value.
+ * The parent network address to receive the value.
*/
destinationAddress: string
/**
@@ -105,9 +105,9 @@ export interface EthWithdrawParams {
export type EthDepositParams = {
/**
- * The L1 provider or signer
+ * Parent network provider or signer
*/
- l1Signer: Signer
+ parentSigner: Signer
/**
* The amount of ETH or tokens to be deposited
*/
@@ -120,11 +120,11 @@ export type EthDepositParams = {
export type EthDepositToParams = EthDepositParams & {
/**
- * An L2 provider
+ * Child network provider
*/
- l2Provider: Provider
+ childProvider: Provider
/**
- * L2 address of the entity receiving the funds
+ * Child network address of the entity receiving the funds
*/
destinationAddress: string
/**
@@ -133,29 +133,29 @@ export type EthDepositToParams = EthDepositParams & {
retryableGasOverrides?: GasOverrides
}
-export type L1ToL2TxReqAndSigner = L1ToL2TransactionRequest & {
- l1Signer: Signer
+export type ParentToChildTxReqAndSigner = ParentToChildTransactionRequest & {
+ parentSigner: Signer
overrides?: Overrides
}
-export type L2ToL1TxReqAndSigner = L2ToL1TransactionRequest & {
- l2Signer: Signer
+export type ChildToParentTxReqAndSigner = ChildToParentTransactionRequest & {
+ childSigner: Signer
overrides?: Overrides
}
type EthDepositRequestParams = OmitTyped<
EthDepositParams,
- 'overrides' | 'l1Signer'
+ 'overrides' | 'parentSigner'
> & { from: string }
type EthDepositToRequestParams = OmitTyped<
EthDepositToParams,
- 'overrides' | 'l1Signer'
+ 'overrides' | 'parentSigner'
> & {
/**
- * The L1 provider
+ * Parent network provider
*/
- l1Provider: Provider
+ parentProvider: Provider
/**
* Address that is depositing the ETH
*/
@@ -163,19 +163,19 @@ type EthDepositToRequestParams = OmitTyped<
}
/**
- * Bridger for moving ETH back and forth between L1 to L2
+ * Bridger for moving either ETH or custom gas tokens back and forth between parent and child networks
*/
export class EthBridger extends AssetBridger<
- EthDepositParams | EthDepositToParams | L1ToL2TxReqAndSigner,
- EthWithdrawParams | L2ToL1TxReqAndSigner
+ EthDepositParams | EthDepositToParams | ParentToChildTxReqAndSigner,
+ EthWithdrawParams | ChildToParentTxReqAndSigner
> {
/**
- * Instantiates a new EthBridger from an L2 Provider
- * @param l2Provider
+ * Instantiates a new EthBridger from a child network Provider
+ * @param childProvider
* @returns
*/
- public static async fromProvider(l2Provider: Provider) {
- return new EthBridger(await getL2Network(l2Provider))
+ public static async fromProvider(childProvider: Provider) {
+ return new EthBridger(await getArbitrumNetwork(childProvider))
}
/**
@@ -184,12 +184,12 @@ export class EthBridger extends AssetBridger<
*/
private isApproveGasTokenParams(
params: ApproveGasTokenParamsOrTxRequest
- ): params is WithL1Signer {
+ ): params is WithParentSigner {
return typeof (params as ApproveGasTokenTxRequest).txRequest === 'undefined'
}
/**
- * Creates a transaction request for approving the custom gas token to be spent by the inbox on the parent chain
+ * Creates a transaction request for approving the custom gas token to be spent by the inbox on the parent network
* @param params
*/
public getApproveGasTokenRequest(
@@ -203,7 +203,7 @@ export class EthBridger extends AssetBridger<
'approve',
[
// spender
- this.l2Network.ethBridge.inbox,
+ this.childNetwork.ethBridge.inbox,
// value
params?.amount ?? constants.MaxUint256,
]
@@ -217,11 +217,11 @@ export class EthBridger extends AssetBridger<
}
/**
- * Approves the custom gas token to be spent by the Inbox on the parent chain.
+ * Approves the custom gas token to be spent by the Inbox on the parent network.
* @param params
*/
public async approveGasToken(
- params: WithL1Signer
+ params: WithParentSigner
) {
if (this.nativeTokenIsEth) {
throw new Error('chain uses ETH as its native/gas token')
@@ -231,7 +231,7 @@ export class EthBridger extends AssetBridger<
? this.getApproveGasTokenRequest(params)
: params.txRequest
- return params.l1Signer.sendTransaction({
+ return params.parentSigner.sendTransaction({
...approveGasTokenRequest,
...params.overrides,
})
@@ -271,10 +271,10 @@ export class EthBridger extends AssetBridger<
*/
public async getDepositRequest(
params: EthDepositRequestParams
- ): Promise> {
+ ): Promise> {
return {
txRequest: {
- to: this.l2Network.ethBridge.inbox,
+ to: this.childNetwork.ethBridge.inbox,
value: this.nativeTokenIsEth ? params.amount : 0,
data: this.getDepositRequestData(params),
from: params.from,
@@ -284,41 +284,41 @@ export class EthBridger extends AssetBridger<
}
/**
- * Deposit ETH from L1 onto L2
+ * Deposit ETH from Parent onto Child network
* @param params
* @returns
*/
public async deposit(
- params: EthDepositParams | L1ToL2TxReqAndSigner
- ): Promise {
- await this.checkL1Network(params.l1Signer)
+ params: EthDepositParams | ParentToChildTxReqAndSigner
+ ): Promise {
+ await this.checkParentNetwork(params.parentSigner)
- const ethDeposit = isL1ToL2TransactionRequest(params)
+ const ethDeposit = isParentToChildTransactionRequest(params)
? params
: await this.getDepositRequest({
...params,
- from: await params.l1Signer.getAddress(),
+ from: await params.parentSigner.getAddress(),
})
- const tx = await params.l1Signer.sendTransaction({
+ const tx = await params.parentSigner.sendTransaction({
...ethDeposit.txRequest,
...params.overrides,
})
- return L1TransactionReceipt.monkeyPatchEthDepositWait(tx)
+ return ParentTransactionReceipt.monkeyPatchEthDepositWait(tx)
}
/**
- * Get a transaction request for an ETH deposit to a different L2 address using Retryables
+ * Get a transaction request for an ETH deposit to a different child network address using Retryables
* @param params
* @returns
*/
public async getDepositToRequest(
params: EthDepositToRequestParams
- ): Promise {
+ ): Promise {
const decimals = await getNativeTokenDecimals({
- l1Provider: params.l1Provider,
- l2Network: this.l2Network,
+ parentProvider: params.parentProvider,
+ childNetwork: this.childNetwork,
})
const amountToBeMintedOnChildChain = nativeTokenDecimalsTo18Decimals({
@@ -337,43 +337,45 @@ export class EthBridger extends AssetBridger<
// Gas overrides can be passed in the parameters
const gasOverrides = params.retryableGasOverrides || undefined
- return L1ToL2MessageCreator.getTicketCreationRequest(
+ return ParentToChildMessageCreator.getTicketCreationRequest(
requestParams,
- params.l1Provider,
- params.l2Provider,
+ params.parentProvider,
+ params.childProvider,
gasOverrides
)
}
/**
- * Deposit ETH from L1 onto a different L2 address
+ * Deposit ETH from parent network onto a different child network address
* @param params
* @returns
*/
public async depositTo(
params:
| EthDepositToParams
- | (L1ToL2TxReqAndSigner & { l2Provider: Provider })
- ): Promise {
- await this.checkL1Network(params.l1Signer)
- await this.checkL2Network(params.l2Provider)
+ | (ParentToChildTxReqAndSigner & { childProvider: Provider })
+ ): Promise {
+ await this.checkParentNetwork(params.parentSigner)
+ await this.checkChildNetwork(params.childProvider)
- const retryableTicketRequest = isL1ToL2TransactionRequest(params)
+ const retryableTicketRequest = isParentToChildTransactionRequest(params)
? params
: await this.getDepositToRequest({
...params,
- from: await params.l1Signer.getAddress(),
- l1Provider: params.l1Signer.provider!,
+ from: await params.parentSigner.getAddress(),
+ parentProvider: params.parentSigner.provider!,
})
- const l1ToL2MessageCreator = new L1ToL2MessageCreator(params.l1Signer)
+ const parentToChildMessageCreator = new ParentToChildMessageCreator(
+ params.parentSigner
+ )
- const tx = await l1ToL2MessageCreator.createRetryableTicket(
+ const tx = await parentToChildMessageCreator.createRetryableTicket(
retryableTicketRequest,
- params.l2Provider
+ params.childProvider
)
- return L1TransactionReceipt.monkeyPatchContractCallWait(tx)
+ return ParentTransactionReceipt.monkeyPatchContractCallWait(tx)
}
/**
@@ -383,7 +385,7 @@ export class EthBridger extends AssetBridger<
*/
public async getWithdrawalRequest(
params: EthWithdrawParams
- ): Promise {
+ ): Promise {
const iArbSys = ArbSys__factory.createInterface()
const functionData = iArbSys.encodeFunctionData('withdrawEth', [
params.destinationAddress,
@@ -397,8 +399,8 @@ export class EthBridger extends AssetBridger<
from: params.from,
},
// todo: do proper estimation
- estimateL1GasLimit: async (l1Provider: Provider) => {
- if (await isArbitrumChain(l1Provider)) {
+ estimateParentGasLimit: async (parentProvider: Provider) => {
+ if (await isArbitrumChain(parentProvider)) {
// values for L3 are dependent on the L1 base fee, so hardcoding can never be accurate
// however, this is only an estimate used for display, so should be good enough
//
@@ -413,28 +415,30 @@ export class EthBridger extends AssetBridger<
}
/**
- * Withdraw ETH from L2 onto L1
+ * Withdraw ETH from child network onto parent network
* @param params
* @returns
*/
public async withdraw(
- params: (EthWithdrawParams & { l2Signer: Signer }) | L2ToL1TxReqAndSigner
- ): Promise {
- if (!SignerProviderUtils.signerHasProvider(params.l2Signer)) {
- throw new MissingProviderArbSdkError('l2Signer')
+ params:
+ | (EthWithdrawParams & { childSigner: Signer })
+ | ChildToParentTxReqAndSigner
+ ): Promise {
+ if (!SignerProviderUtils.signerHasProvider(params.childSigner)) {
+ throw new MissingProviderArbSdkError('childSigner')
}
- await this.checkL2Network(params.l2Signer)
+ await this.checkChildNetwork(params.childSigner)
- const request = isL2ToL1TransactionRequest<
- EthWithdrawParams & { l2Signer: Signer }
+ const request = isChildToParentTransactionRequest<
+ EthWithdrawParams & { childSigner: Signer }
>(params)
? params
: await this.getWithdrawalRequest(params)
- const tx = await params.l2Signer.sendTransaction({
+ const tx = await params.childSigner.sendTransaction({
...request.txRequest,
...params.overrides,
})
- return L2TransactionReceipt.monkeyPatchWait(tx)
+ return ChildTransactionReceipt.monkeyPatchWait(tx)
}
}
diff --git a/src/lib/assetBridger/l1l3Bridger.ts b/src/lib/assetBridger/l1l3Bridger.ts
index 3e2c28ae0f..b71912c312 100644
--- a/src/lib/assetBridger/l1l3Bridger.ts
+++ b/src/lib/assetBridger/l1l3Bridger.ts
@@ -18,33 +18,32 @@ import { IL1Teleporter__factory } from '../abi/factories/IL1Teleporter__factory'
import { Address } from '../dataEntities/address'
import { ArbSdkError } from '../dataEntities/errors'
import {
- L1Network,
- L2Network,
+ ArbitrumNetwork,
Teleporter,
- l1Networks,
- l2Networks,
+ assertArbitrumNetworkHasTokenBridge,
+ getArbitrumNetworks,
} from '../dataEntities/networks'
import {
SignerOrProvider,
SignerProviderUtils,
} from '../dataEntities/signerOrProvider'
-import { L1ToL2TransactionRequest } from '../dataEntities/transactionRequest'
+import { ParentToChildTransactionRequest } from '../dataEntities/transactionRequest'
import {
- L1ToL2MessageReader,
- L1ToL2MessageStatus,
-} from '../message/L1ToL2Message'
-import { L1ToL2MessageCreator } from '../message/L1ToL2MessageCreator'
+ ParentToChildMessageReader,
+ ParentToChildMessageStatus,
+} from '../message/ParentToChildMessage'
+import { ParentToChildMessageCreator } from '../message/ParentToChildMessageCreator'
import {
GasOverrides,
- L1ToL2MessageGasEstimator,
+ ParentToChildMessageGasEstimator,
PercentIncrease,
-} from '../message/L1ToL2MessageGasEstimator'
+} from '../message/ParentToChildMessageGasEstimator'
import {
- L1ContractCallTransaction,
- L1ContractCallTransactionReceipt,
- L1EthDepositTransactionReceipt,
- L1TransactionReceipt,
-} from '../message/L1Transaction'
+ ParentContractCallTransaction,
+ ParentContractCallTransactionReceipt,
+ ParentEthDepositTransactionReceipt,
+ ParentTransactionReceipt,
+} from '../message/ParentTransaction'
import { Erc20Bridger } from './erc20Bridger'
import { Inbox__factory } from '../abi/factories/Inbox__factory'
import { OmitTyped } from '../utils/types'
@@ -111,7 +110,7 @@ export type TokenApproveParams = {
amount?: BigNumber
}
-export type Erc20DepositRequestRetryableOverrides = {
+export type Erc20L1L3DepositRequestRetryableOverrides = {
/**
* Optional L1 gas price override. Used to estimate submission fees.
*/
@@ -142,7 +141,7 @@ export type Erc20DepositRequestRetryableOverrides = {
l2l3TokenBridgeRetryableGas?: TeleporterRetryableGasOverride
}
-export type Erc20DepositRequestParams = {
+export type Erc20L1L3DepositRequestParams = {
/**
* Address of L1 token
*/
@@ -174,43 +173,43 @@ export type Erc20DepositRequestParams = {
/**
* Optional overrides for retryable gas parameters
*/
- retryableOverrides?: Erc20DepositRequestRetryableOverrides
+ retryableOverrides?: Erc20L1L3DepositRequestRetryableOverrides
}
export type TxReference =
| { txHash: string }
- | { tx: L1ContractCallTransaction }
- | { txReceipt: L1ContractCallTransactionReceipt }
+ | { tx: ParentContractCallTransaction }
+ | { txReceipt: ParentContractCallTransactionReceipt }
-export type GetDepositStatusParams = {
+export type GetL1L3DepositStatusParams = {
l1Provider: Provider
l2Provider: Provider
l3Provider: Provider
} & TxReference
-export type Erc20DepositStatus = {
+export type Erc20L1L3DepositStatus = {
/**
* L1 to L2 token bridge message
*/
- l1l2TokenBridgeRetryable: L1ToL2MessageReader
+ l1l2TokenBridgeRetryable: ParentToChildMessageReader
/**
* L1 to L2 fee token bridge message
*/
- l1l2GasTokenBridgeRetryable: L1ToL2MessageReader | undefined
+ l1l2GasTokenBridgeRetryable: ParentToChildMessageReader | undefined
/**
* L2ForwarderFactory message
*/
- l2ForwarderFactoryRetryable: L1ToL2MessageReader
+ l2ForwarderFactoryRetryable: ParentToChildMessageReader
/**
* L2 to L3 token bridge message
*/
- l2l3TokenBridgeRetryable: L1ToL2MessageReader | undefined
+ l2l3TokenBridgeRetryable: ParentToChildMessageReader | undefined
/**
* Indicates that the L2ForwarderFactory call was front ran by another teleportation.
*
* This is true if:
* - l1l2TokenBridgeRetryable status is REDEEMED; AND
- * - l2ForwarderFactoryRetryable status is FUNDS_DEPOSITED_ON_L2; AND
+ * - l2ForwarderFactoryRetryable status is FUNDS_DEPOSITED_ON_CHILD; AND
* - L2Forwarder token balance is 0
*
* The first teleportation with l2ForwarderFactoryRetryable redemption *after* this teleportation's l1l2TokenBridgeRetryable redemption
@@ -225,7 +224,7 @@ export type Erc20DepositStatus = {
completed: boolean
}
-export type EthDepositRequestParams = {
+export type EthL1L3DepositRequestParams = {
/**
* Amount of ETH to send to L3
*/
@@ -256,15 +255,15 @@ export type EthDepositRequestParams = {
l3TicketGasOverrides?: Omit
}
-export type EthDepositStatus = {
+export type EthL1L3DepositStatus = {
/**
* L1 to L2 message
*/
- l2Retryable: L1ToL2MessageReader
+ l2Retryable: ParentToChildMessageReader
/**
* L2 to L3 message
*/
- l3Retryable: L1ToL2MessageReader | undefined
+ l3Retryable: ParentToChildMessageReader | undefined
/**
* Whether the teleportation has completed
*/
@@ -275,31 +274,27 @@ export type EthDepositStatus = {
* Base functionality for L1 to L3 bridging.
*/
class BaseL1L3Bridger {
- public readonly l1Network: L1Network
- public readonly l2Network: L2Network
- public readonly l3Network: L2Network
+ public readonly l1Network: { chainId: number }
+ public readonly l2Network: ArbitrumNetwork
+ public readonly l3Network: ArbitrumNetwork
public readonly defaultGasPricePercentIncrease: BigNumber =
BigNumber.from(500)
public readonly defaultGasLimitPercentIncrease: BigNumber =
BigNumber.from(100)
- constructor(l3Network: L2Network) {
- const l2Network = l2Networks[l3Network.partnerChainID]
- if (!l2Network) {
- throw new ArbSdkError(
- `Unknown l2 network chain id: ${l3Network.partnerChainID}`
- )
- }
+ constructor(l3Network: ArbitrumNetwork) {
+ const l2Network = getArbitrumNetworks().find(
+ network => network.chainId === l3Network.parentChainId
+ )
- const l1Network = l1Networks[l2Network.partnerChainID]
- if (!l1Network) {
+ if (!l2Network) {
throw new ArbSdkError(
- `Unknown l1 network chain id: ${l2Network.partnerChainID}`
+ `Unknown arbitrum network chain id: ${l3Network.parentChainId}`
)
}
- this.l1Network = l1Network
+ this.l1Network = { chainId: l2Network.parentChainId }
this.l2Network = l2Network
this.l3Network = l3Network
}
@@ -309,7 +304,7 @@ class BaseL1L3Bridger {
* @param sop
*/
protected async _checkL1Network(sop: SignerOrProvider): Promise {
- await SignerProviderUtils.checkNetworkMatches(sop, this.l1Network.chainID)
+ await SignerProviderUtils.checkNetworkMatches(sop, this.l1Network.chainId)
}
/**
@@ -317,7 +312,7 @@ class BaseL1L3Bridger {
* @param sop
*/
protected async _checkL2Network(sop: SignerOrProvider): Promise {
- await SignerProviderUtils.checkNetworkMatches(sop, this.l2Network.chainID)
+ await SignerProviderUtils.checkNetworkMatches(sop, this.l2Network.chainId)
}
/**
@@ -325,7 +320,7 @@ class BaseL1L3Bridger {
* @param sop
*/
protected async _checkL3Network(sop: SignerOrProvider): Promise {
- await SignerProviderUtils.checkNetworkMatches(sop, this.l3Network.chainID)
+ await SignerProviderUtils.checkNetworkMatches(sop, this.l3Network.chainId)
}
protected _percentIncrease(num: BigNumber, increase: BigNumber): BigNumber {
@@ -345,12 +340,12 @@ class BaseL1L3Bridger {
protected async _getTxFromTxRef(
txRef: TxReference,
provider: Provider
- ): Promise {
+ ): Promise {
if ('tx' in txRef) {
return txRef.tx
}
- return L1TransactionReceipt.monkeyPatchContractCallWait(
+ return ParentTransactionReceipt.monkeyPatchContractCallWait(
await provider.getTransaction(this._getTxHashFromTxRef(txRef))
)
}
@@ -358,12 +353,12 @@ class BaseL1L3Bridger {
protected async _getTxReceiptFromTxRef(
txRef: TxReference,
provider: Provider
- ): Promise {
+ ): Promise {
if ('txReceipt' in txRef) {
return txRef.txReceipt
}
- return new L1ContractCallTransactionReceipt(
+ return new ParentContractCallTransactionReceipt(
await provider.getTransactionReceipt(this._getTxHashFromTxRef(txRef))
)
}
@@ -410,7 +405,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
*/
protected _l1FeeTokenAddress: string | undefined
- public constructor(l3Network: L2Network) {
+ public constructor(l3Network: ArbitrumNetwork) {
super(l3Network)
if (!this.l2Network.teleporter) {
@@ -449,7 +444,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
let l1FeeTokenAddress: string | undefined
try {
- l1FeeTokenAddress = await this.l2Erc20Bridger.getL1ERC20Address(
+ l1FeeTokenAddress = await this.l2Erc20Bridger.getParentErc20Address(
this.l2GasTokenAddress,
l2Provider
)
@@ -510,23 +505,23 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
/**
* Get the corresponding L2 token address for the provided L1 token
*/
- public getL2ERC20Address(
+ public getL2Erc20Address(
erc20L1Address: string,
l1Provider: Provider
): Promise {
- return this.l2Erc20Bridger.getL2ERC20Address(erc20L1Address, l1Provider)
+ return this.l2Erc20Bridger.getChildErc20Address(erc20L1Address, l1Provider)
}
/**
* Get the corresponding L3 token address for the provided L1 token
*/
- public async getL3ERC20Address(
+ public async getL3Erc20Address(
erc20L1Address: string,
l1Provider: Provider,
l2Provider: Provider
): Promise {
- return this.l3Erc20Bridger.getL2ERC20Address(
- await this.getL2ERC20Address(erc20L1Address, l1Provider),
+ return this.l3Erc20Bridger.getChildErc20Address(
+ await this.getL2Erc20Address(erc20L1Address, l1Provider),
l2Provider
)
}
@@ -538,7 +533,10 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
erc20L1Address: string,
l1Provider: Provider
): Promise {
- return this.l2Erc20Bridger.getL1GatewayAddress(erc20L1Address, l1Provider)
+ return this.l2Erc20Bridger.getParentGatewayAddress(
+ erc20L1Address,
+ l1Provider
+ )
}
/**
@@ -549,8 +547,8 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
l1Provider: Provider,
l2Provider: Provider
): Promise {
- const l2Token = await this.getL2ERC20Address(erc20L1Address, l1Provider)
- return this.l3Erc20Bridger.getL1GatewayAddress(l2Token, l2Provider)
+ const l2Token = await this.getL2Erc20Address(erc20L1Address, l1Provider)
+ return this.l3Erc20Bridger.getParentGatewayAddress(l2Token, l2Provider)
}
/**
@@ -596,7 +594,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
l1TokenAddress: string,
l1Provider: Provider
): Promise {
- return this.l2Erc20Bridger.l1TokenIsDisabled(l1TokenAddress, l1Provider)
+ return this.l2Erc20Bridger.isDepositDisabled(l1TokenAddress, l1Provider)
}
/**
@@ -606,7 +604,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
l2TokenAddress: string,
l2Provider: Provider
): Promise {
- return this.l3Erc20Bridger.l1TokenIsDisabled(l2TokenAddress, l2Provider)
+ return this.l3Erc20Bridger.isDepositDisabled(l2TokenAddress, l2Provider)
}
/**
@@ -621,9 +619,9 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
const chainId = (await l1OrL2Provider.getNetwork()).chainId
let predictor
- if (chainId === this.l1Network.chainID) {
+ if (chainId === this.l1Network.chainId) {
predictor = this.teleporter.l1Teleporter
- } else if (chainId === this.l2Network.chainID) {
+ } else if (chainId === this.l2Network.chainId) {
predictor = this.teleporter.l2ForwarderFactory
} else {
throw new ArbSdkError(`Unknown chain id: ${chainId}`)
@@ -732,7 +730,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
* Also returns the amount of fee tokens required for teleportation.
*/
public async getDepositRequest(
- params: Erc20DepositRequestParams &
+ params: Erc20L1L3DepositRequestParams &
(
| {
from: string
@@ -741,6 +739,8 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
| { l1Signer: Signer }
)
): Promise {
+ assertArbitrumNetworkHasTokenBridge(this.l2Network)
+ assertArbitrumNetworkHasTokenBridge(this.l3Network)
const l1Provider =
'l1Provider' in params ? params.l1Provider : params.l1Signer.provider!
@@ -772,12 +772,12 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
> = {
l1Token: params.erc20L1Address,
l3FeeTokenL1Addr: l1FeeToken,
- l1l2Router: this.l2Network.tokenBridge.l1GatewayRouter,
+ l1l2Router: this.l2Network.tokenBridge.parentGatewayRouter,
l2l3RouterOrInbox:
l1FeeToken &&
getAddress(params.erc20L1Address) === getAddress(l1FeeToken)
? this.l3Network.ethBridge.inbox
- : this.l3Network.tokenBridge.l1GatewayRouter,
+ : this.l3Network.tokenBridge.parentGatewayRouter,
to: params.destinationAddress || from,
amount: params.amount,
}
@@ -810,12 +810,12 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
*/
public async deposit(
params:
- | (Erc20DepositRequestParams & {
+ | (Erc20L1L3DepositRequestParams & {
l1Signer: Signer
overrides?: PayableOverrides
})
| TxRequestParams
- ): Promise {
+ ): Promise {
await this._checkL1Network(params.l1Signer)
const depositRequest =
@@ -828,7 +828,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
...params.overrides,
})
- return L1TransactionReceipt.monkeyPatchContractCallWait(tx)
+ return ParentTransactionReceipt.monkeyPatchContractCallWait(tx)
}
/**
@@ -876,8 +876,8 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
* Can provide either the txHash, the tx, or the txReceipt
*/
public async getDepositStatus(
- params: GetDepositStatusParams
- ): Promise {
+ params: GetL1L3DepositStatusParams
+ ): Promise {
await this._checkL1Network(params.l1Provider)
await this._checkL2Network(params.l2Provider)
await this._checkL3Network(params.l3Provider)
@@ -896,11 +896,11 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
await partialResult.l2ForwarderFactoryRetryable.getSuccessfulRedeem()
const l2l3Message =
- factoryRedeem.status === L1ToL2MessageStatus.REDEEMED
+ factoryRedeem.status === ParentToChildMessageStatus.REDEEMED
? (
- await new L1TransactionReceipt(
- factoryRedeem.l2TxReceipt
- ).getL1ToL2Messages(params.l3Provider)
+ await new ParentTransactionReceipt(
+ factoryRedeem.childTxReceipt
+ ).getParentToChildMessages(params.l3Provider)
)[0]
: undefined
@@ -912,8 +912,9 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
const l1l2TokenBridgeRetryableStatus =
await partialResult.l1l2TokenBridgeRetryable.status()
if (
- l1l2TokenBridgeRetryableStatus === L1ToL2MessageStatus.REDEEMED &&
- factoryRedeem.status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2
+ l1l2TokenBridgeRetryableStatus === ParentToChildMessageStatus.REDEEMED &&
+ factoryRedeem.status ===
+ ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHILD
) {
// decoding the factory call is the most reliable way to get the owner and other parameters
const decodedFactoryCall = this._decodeCallForwarderCalldata(
@@ -941,7 +942,8 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
...partialResult,
l2l3TokenBridgeRetryable: l2l3Message,
l2ForwarderFactoryRetryableFrontRan,
- completed: (await l2l3Message?.status()) === L1ToL2MessageStatus.REDEEMED,
+ completed:
+ (await l2l3Message?.status()) === ParentToChildMessageStatus.REDEEMED,
}
}
@@ -995,7 +997,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
'0x'
)
- const estimates = await new L1ToL2MessageGasEstimator(
+ const estimates = await new ParentToChildMessageGasEstimator(
params.childProvider
).estimateAll(
{
@@ -1027,6 +1029,8 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
l1Provider: Provider
l2Provider: Provider
}): Promise {
+ assertArbitrumNetworkHasTokenBridge(this.l2Network)
+
const parentGatewayAddress = await this.getL1L2GatewayAddress(
params.l1Token,
params.l1Provider
@@ -1042,7 +1046,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
amount: BigNumber.from(params.amount),
isWeth:
getAddress(parentGatewayAddress) ===
- getAddress(this.l2Network.tokenBridge.l1WethGateway),
+ getAddress(this.l2Network.tokenBridge.parentWethGateway),
})
}
@@ -1057,6 +1061,8 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
l1Provider: Provider
l2Provider: Provider
}): Promise {
+ assertArbitrumNetworkHasTokenBridge(this.l2Network)
+
if (params.l3FeeTokenL1Addr === this.skipL1GasTokenMagic) {
return {
gasLimit: BigNumber.from(0),
@@ -1078,7 +1084,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
amount: params.feeTokenAmount,
isWeth:
getAddress(parentGatewayAddress) ===
- getAddress(this.l2Network.tokenBridge.l1WethGateway),
+ getAddress(this.l2Network.tokenBridge.parentWethGateway),
})
}
@@ -1119,6 +1125,8 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
l3Provider: Provider
l2ForwarderAddress: string
}): Promise {
+ assertArbitrumNetworkHasTokenBridge(this.l3Network)
+
const teleportationType = this.teleportationType(
params.partialTeleportParams
)
@@ -1133,7 +1141,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
}
} else if (teleportationType === TeleportationType.OnlyGasToken) {
// we are bridging the fee token to l3, this will not go through the l2l3 token bridge, instead it's just a regular retryable
- const estimate = await new L1ToL2MessageGasEstimator(
+ const estimate = await new ParentToChildMessageGasEstimator(
params.l3Provider
).estimateAll(
{
@@ -1164,7 +1172,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
parentProvider: params.l2Provider,
childProvider: params.l3Provider,
parentGasPrice: params.l2GasPrice,
- parentErc20Address: await this.getL2ERC20Address(
+ parentErc20Address: await this.getL2Erc20Address(
params.partialTeleportParams.l1Token,
params.l1Provider
),
@@ -1174,7 +1182,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
amount: BigNumber.from(params.partialTeleportParams.amount),
isWeth:
getAddress(parentGatewayAddress) ===
- getAddress(this.l3Network.tokenBridge.l1WethGateway),
+ getAddress(this.l3Network.tokenBridge.parentWethGateway),
})
}
}
@@ -1188,7 +1196,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
IL1Teleporter.TeleportParamsStruct,
'gasParams'
>,
- retryableOverrides: Erc20DepositRequestRetryableOverrides,
+ retryableOverrides: Erc20L1L3DepositRequestRetryableOverrides,
l1Provider: Provider,
l2Provider: Provider,
l3Provider: Provider
@@ -1403,15 +1411,15 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
}
protected async _getL1ToL2Messages(
- l1TxReceipt: L1ContractCallTransactionReceipt,
+ l1TxReceipt: ParentContractCallTransactionReceipt,
l2Provider: Provider
) {
- const l1l2Messages = await l1TxReceipt.getL1ToL2Messages(l2Provider)
+ const l1l2Messages = await l1TxReceipt.getParentToChildMessages(l2Provider)
let partialResult: {
- l1l2TokenBridgeRetryable: L1ToL2MessageReader
- l1l2GasTokenBridgeRetryable: L1ToL2MessageReader | undefined
- l2ForwarderFactoryRetryable: L1ToL2MessageReader
+ l1l2TokenBridgeRetryable: ParentToChildMessageReader
+ l1l2GasTokenBridgeRetryable: ParentToChildMessageReader | undefined
+ l2ForwarderFactoryRetryable: ParentToChildMessageReader
}
if (l1l2Messages.length === 2) {
@@ -1436,7 +1444,7 @@ export class Erc20L1L3Bridger extends BaseL1L3Bridger {
* Bridge ETH from L1 to L3 using a double retryable ticket
*/
export class EthL1L3Bridger extends BaseL1L3Bridger {
- constructor(l3Network: L2Network) {
+ constructor(l3Network: ArbitrumNetwork) {
super(l3Network)
if (
@@ -1453,7 +1461,7 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
* Get a tx request to deposit ETH to L3 via a double retryable ticket
*/
public async getDepositRequest(
- params: EthDepositRequestParams &
+ params: EthL1L3DepositRequestParams &
(
| {
from: string
@@ -1461,7 +1469,7 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
}
| { l1Signer: Signer }
)
- ): Promise {
+ ): Promise {
const l1Provider =
'l1Provider' in params ? params.l1Provider : params.l1Signer.provider!
await this._checkL1Network(l1Provider)
@@ -1474,33 +1482,35 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
const l3DestinationAddress = params.destinationAddress || from
const l2RefundAddress = params.l2RefundAddress || from
- const l3TicketRequest = await L1ToL2MessageCreator.getTicketCreationRequest(
- {
- to: l3DestinationAddress,
- data: '0x',
- from: new Address(from).applyAlias().value,
- l2CallValue: BigNumber.from(params.amount),
- excessFeeRefundAddress: l3DestinationAddress,
- callValueRefundAddress: l3DestinationAddress,
- },
- params.l2Provider,
- params.l3Provider,
- params.l3TicketGasOverrides
- )
+ const l3TicketRequest =
+ await ParentToChildMessageCreator.getTicketCreationRequest(
+ {
+ to: l3DestinationAddress,
+ data: '0x',
+ from: new Address(from).applyAlias().value,
+ l2CallValue: BigNumber.from(params.amount),
+ excessFeeRefundAddress: l3DestinationAddress,
+ callValueRefundAddress: l3DestinationAddress,
+ },
+ params.l2Provider,
+ params.l3Provider,
+ params.l3TicketGasOverrides
+ )
- const l2TicketRequest = await L1ToL2MessageCreator.getTicketCreationRequest(
- {
- from,
- to: l3TicketRequest.txRequest.to,
- l2CallValue: BigNumber.from(l3TicketRequest.txRequest.value),
- data: ethers.utils.hexlify(l3TicketRequest.txRequest.data),
- excessFeeRefundAddress: l2RefundAddress,
- callValueRefundAddress: l2RefundAddress,
- },
- l1Provider,
- params.l2Provider,
- params.l2TicketGasOverrides
- )
+ const l2TicketRequest =
+ await ParentToChildMessageCreator.getTicketCreationRequest(
+ {
+ from,
+ to: l3TicketRequest.txRequest.to,
+ l2CallValue: BigNumber.from(l3TicketRequest.txRequest.value),
+ data: ethers.utils.hexlify(l3TicketRequest.txRequest.data),
+ excessFeeRefundAddress: l2RefundAddress,
+ callValueRefundAddress: l2RefundAddress,
+ },
+ l1Provider,
+ params.l2Provider,
+ params.l2TicketGasOverrides
+ )
return l2TicketRequest
}
@@ -1510,12 +1520,12 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
*/
public async deposit(
params:
- | (EthDepositRequestParams & {
+ | (EthL1L3DepositRequestParams & {
l1Signer: Signer
overrides?: PayableOverrides
})
| TxRequestParams
- ): Promise {
+ ): Promise {
await this._checkL1Network(params.l1Signer)
const depositRequest =
@@ -1528,7 +1538,7 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
...params.overrides,
})
- return L1TransactionReceipt.monkeyPatchContractCallWait(tx)
+ return ParentTransactionReceipt.monkeyPatchContractCallWait(tx)
}
/**
@@ -1562,11 +1572,11 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
* Get the status of a deposit given an L1 tx receipt. Does not check if the tx is actually a deposit tx.
*
* @return Information regarding each step of the deposit
- * and `EthDepositStatus.completed` which indicates whether the deposit has fully completed.
+ * and `EthL1L3DepositStatus.completed` which indicates whether the deposit has fully completed.
*/
public async getDepositStatus(
- params: GetDepositStatusParams
- ): Promise {
+ params: GetL1L3DepositStatusParams
+ ): Promise {
await this._checkL1Network(params.l1Provider)
await this._checkL2Network(params.l2Provider)
await this._checkL3Network(params.l3Provider)
@@ -1577,11 +1587,11 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
)
const l1l2Message = (
- await l1TxReceipt.getL1ToL2Messages(params.l2Provider)
+ await l1TxReceipt.getParentToChildMessages(params.l2Provider)
)[0]
const l1l2Redeem = await l1l2Message.getSuccessfulRedeem()
- if (l1l2Redeem.status != L1ToL2MessageStatus.REDEEMED) {
+ if (l1l2Redeem.status != ParentToChildMessageStatus.REDEEMED) {
return {
l2Retryable: l1l2Message,
l3Retryable: undefined,
@@ -1590,9 +1600,9 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
}
const l2l3Message = (
- await new L1EthDepositTransactionReceipt(
- l1l2Redeem.l2TxReceipt
- ).getL1ToL2Messages(params.l3Provider)
+ await new ParentEthDepositTransactionReceipt(
+ l1l2Redeem.childTxReceipt
+ ).getParentToChildMessages(params.l3Provider)
)[0]
if (l2l3Message === undefined) {
@@ -1602,7 +1612,8 @@ export class EthL1L3Bridger extends BaseL1L3Bridger {
return {
l2Retryable: l1l2Message,
l3Retryable: l2l3Message,
- completed: (await l2l3Message.status()) === L1ToL2MessageStatus.REDEEMED,
+ completed:
+ (await l2l3Message.status()) === ParentToChildMessageStatus.REDEEMED,
}
}
diff --git a/src/lib/dataEntities/constants.ts b/src/lib/dataEntities/constants.ts
index 4fea86d645..ce055b9fc2 100644
--- a/src/lib/dataEntities/constants.ts
+++ b/src/lib/dataEntities/constants.ts
@@ -52,3 +52,27 @@ export const DISABLED_GATEWAY = '0x0000000000000000000000000000000000000001'
export const CUSTOM_TOKEN_IS_ENABLED = 42161
export const SEVEN_DAYS_IN_SECONDS = 7 * 24 * 60 * 60
+
+/**
+ * How long to wait (in milliseconds) for a deposit to arrive before timing out a request.
+ *
+ * Finalisation on mainnet can be up to 2 epochs = 64 blocks.
+ * We add 10 minutes for the system to create and redeem the ticket, plus some extra buffer of time.
+ *
+ * Total timeout: 30 minutes.
+ */
+export const DEFAULT_DEPOSIT_TIMEOUT = 30 * 60 * 1000
+
+/**
+ * The L1 block at which Nitro was activated for Arbitrum One.
+ *
+ * @see https://etherscan.io/block/15447158
+ */
+export const ARB1_NITRO_GENESIS_L1_BLOCK = 15447158
+
+/**
+ * The L2 block at which Nitro was activated for Arbitrum One.
+ *
+ * @see https://arbiscan.io/block/22207817
+ */
+export const ARB1_NITRO_GENESIS_L2_BLOCK = 22207817
diff --git a/src/lib/dataEntities/message.ts b/src/lib/dataEntities/message.ts
index 46633d4573..ca274d9d7a 100644
--- a/src/lib/dataEntities/message.ts
+++ b/src/lib/dataEntities/message.ts
@@ -53,7 +53,7 @@ export enum InboxMessageKind {
L2MessageType_signedTx = 4,
}
-export enum L2ToL1MessageStatus {
+export enum ChildToParentMessageStatus {
/**
* ArbSys.sendTxToL1 called, but assertion not yet confirmed
*/
diff --git a/src/lib/dataEntities/networks.ts b/src/lib/dataEntities/networks.ts
index 5ae7834b41..1b3744f27e 100644
--- a/src/lib/dataEntities/networks.ts
+++ b/src/lib/dataEntities/networks.ts
@@ -14,65 +14,66 @@
* limitations under the License.
*/
/* eslint-env node */
-'use strict'
+;('use strict')
+
+import { Provider } from '@ethersproject/abstract-provider'
import { SignerOrProvider, SignerProviderUtils } from './signerOrProvider'
import { ArbSdkError } from '../dataEntities/errors'
-import {
- SEVEN_DAYS_IN_SECONDS,
- ARB_MINIMUM_BLOCK_TIME_IN_SECONDS,
-} from './constants'
+import { ARB1_NITRO_GENESIS_L2_BLOCK } from './constants'
import { RollupAdminLogic__factory } from '../abi/factories/RollupAdminLogic__factory'
+import { Prettify } from '../utils/types'
-export interface Network {
- chainID: number
+/**
+ * Represents an Arbitrum chain, e.g. Arbitrum One, Arbitrum Sepolia, or an L3 chain.
+ */
+export interface ArbitrumNetwork {
+ /**
+ * Name of the chain.
+ */
name: string
- explorerUrl: string
- gif?: string
- isCustom: boolean
/**
- * Minimum possible block time for the chain (in seconds).
+ * Id of the chain.
*/
- blockTime: number
+ chainId: number
/**
- * Chain ids of children chains, i.e. chains that settle to this chain.
+ * Chain id of the parent chain, i.e. the chain on which this chain settles to.
+ */
+ parentChainId: number
+ /**
+ * The core contracts
*/
- partnerChainIDs: number[]
-}
-
-/**
- * Represents an L1 chain, e.g. Ethereum Mainnet or Sepolia.
- */
-export interface L1Network extends Network {
- isArbitrum: false
-}
-
-/**
- * Represents an Arbitrum chain, e.g. Arbitrum One, Arbitrum Sepolia, or an L3 chain.
- */
-export interface L2Network extends Network {
- tokenBridge: TokenBridge
ethBridge: EthBridge
+ /**
+ * The token bridge contracts.
+ */
+ tokenBridge?: TokenBridge
+ /**
+ * The teleporter contracts.
+ */
teleporter?: Teleporter
/**
- * Chain id of the parent chain, i.e. the chain on which this chain settles to.
+ * The time allowed for validators to dispute or challenge state assertions. Measured in L1 blocks.
*/
- partnerChainID: number
- isArbitrum: true
confirmPeriodBlocks: number
- retryableLifetimeSeconds: number
- nitroGenesisBlock: number
- nitroGenesisL1Block: number
/**
- * How long to wait (ms) for a deposit to arrive on l2 before timing out a request
+ * Represents how long a retryable ticket lasts for before it expires (in seconds). Defaults to 7 days.
*/
- depositTimeout: number
+ retryableLifetimeSeconds?: number
/**
* In case of a chain that uses ETH as its native/gas token, this is either `undefined` or the zero address
*
* In case of a chain that uses an ERC-20 token from the parent chain as its native/gas token, this is the address of said token on the parent chain
*/
nativeToken?: string
+ /**
+ * Whether or not it is a testnet chain.
+ */
+ isTestnet: boolean
+ /**
+ * Whether or not the chain was registered by the user.
+ */
+ isCustom: boolean
/**
* Has the network been upgraded to bold. True if yes, otherwise undefined
* This is a temporary property and will be removed in future if Bold is widely adopted and
@@ -81,12 +82,51 @@ export interface L2Network extends Network {
isBold?: boolean
}
+/**
+ * This type is only here for when you want to achieve backwards compatibility between SDK v3 and v4.
+ *
+ * Please see {@link ArbitrumNetwork} for the latest type.
+ *
+ * @deprecated since v4
+ */
+export type L2Network = Prettify<
+ Omit & {
+ chainID: number
+ partnerChainID: number
+ tokenBridge: L2NetworkTokenBridge
+ }
+>
+
export interface Teleporter {
l1Teleporter: string
l2ForwarderFactory: string
}
export interface TokenBridge {
+ parentGatewayRouter: string
+ childGatewayRouter: string
+ parentErc20Gateway: string
+ childErc20Gateway: string
+ parentCustomGateway: string
+ childCustomGateway: string
+ parentWethGateway: string
+ childWethGateway: string
+ parentWeth: string
+ childWeth: string
+ parentProxyAdmin: string
+ childProxyAdmin: string
+ parentMultiCall: string
+ childMultiCall: string
+}
+
+/**
+ * This type is only here for when you want to achieve backwards compatibility between SDK v3 and v4.
+ *
+ * Please see {@link TokenBridge} for the latest type.
+ *
+ * @deprecated since v4
+ */
+export interface L2NetworkTokenBridge {
l1GatewayRouter: string
l2GatewayRouter: string
l1ERC20Gateway: string
@@ -114,33 +154,21 @@ export interface EthBridge {
}
}
-export interface L1Networks {
- [id: string]: L1Network
-}
-
-export interface L2Networks {
- [id: string]: L2Network
-}
-
-export interface Networks {
- [id: string]: L1Network | L2Network
-}
-
const mainnetTokenBridge: TokenBridge = {
- l1GatewayRouter: '0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef',
- l2GatewayRouter: '0x5288c571Fd7aD117beA99bF60FE0846C4E84F933',
- l1ERC20Gateway: '0xa3A7B6F88361F48403514059F1F16C8E78d60EeC',
- l2ERC20Gateway: '0x09e9222E96E7B4AE2a407B98d48e330053351EEe',
- l1CustomGateway: '0xcEe284F754E854890e311e3280b767F80797180d',
- l2CustomGateway: '0x096760F208390250649E3e8763348E783AEF5562',
- l1WethGateway: '0xd92023E9d9911199a6711321D1277285e6d4e2db',
- l2WethGateway: '0x6c411aD3E74De3E7Bd422b94A27770f5B86C623B',
- l2Weth: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
- l1Weth: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
- l1ProxyAdmin: '0x9aD46fac0Cf7f790E5be05A0F15223935A0c0aDa',
- l2ProxyAdmin: '0xd570aCE65C43af47101fC6250FD6fC63D1c22a86',
- l1MultiCall: '0x5ba1e12693dc8f9c48aad8770482f4739beed696',
- l2Multicall: '0x842eC2c7D803033Edf55E478F461FC547Bc54EB2',
+ parentGatewayRouter: '0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef',
+ childGatewayRouter: '0x5288c571Fd7aD117beA99bF60FE0846C4E84F933',
+ parentErc20Gateway: '0xa3A7B6F88361F48403514059F1F16C8E78d60EeC',
+ childErc20Gateway: '0x09e9222E96E7B4AE2a407B98d48e330053351EEe',
+ parentCustomGateway: '0xcEe284F754E854890e311e3280b767F80797180d',
+ childCustomGateway: '0x096760F208390250649E3e8763348E783AEF5562',
+ parentWethGateway: '0xd92023E9d9911199a6711321D1277285e6d4e2db',
+ childWethGateway: '0x6c411aD3E74De3E7Bd422b94A27770f5B86C623B',
+ childWeth: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
+ parentWeth: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
+ parentProxyAdmin: '0x9aD46fac0Cf7f790E5be05A0F15223935A0c0aDa',
+ childProxyAdmin: '0xd570aCE65C43af47101fC6250FD6fC63D1c22a86',
+ parentMultiCall: '0x5ba1e12693dc8f9c48aad8770482f4739beed696',
+ childMultiCall: '0x842eC2c7D803033Edf55E478F461FC547Bc54EB2',
}
const mainnetETHBridge: EthBridge = {
@@ -156,52 +184,15 @@ const mainnetETHBridge: EthBridge = {
}
/**
- * Storage for all networks, either L1, L2 or L3.
+ * Storage for all Arbitrum networks, either L2 or L3.
*/
-export const networks: Networks = {
- 1: {
- chainID: 1,
- name: 'Mainnet',
- explorerUrl: 'https://etherscan.io',
- partnerChainIDs: [42161, 42170],
- blockTime: 14,
- isCustom: false,
- isArbitrum: false,
- },
- 1338: {
- chainID: 1338,
- name: 'Hardhat_Mainnet_Fork',
- explorerUrl: 'https://etherscan.io',
- partnerChainIDs: [42161],
- blockTime: 1,
- isCustom: false,
- isArbitrum: false,
- },
- 11155111: {
- chainID: 11155111,
- name: 'Sepolia',
- explorerUrl: 'https://sepolia.etherscan.io',
- partnerChainIDs: [421614],
- blockTime: 12,
- isCustom: false,
- isArbitrum: false,
- },
- 17000: {
- chainID: 17000,
- name: 'Holesky',
- explorerUrl: 'https://holesky.etherscan.io',
- partnerChainIDs: [],
- blockTime: 12,
- isCustom: false,
- isArbitrum: false,
- },
+const networks: {
+ [id: string]: ArbitrumNetwork
+} = {
42161: {
- chainID: 42161,
+ chainId: 42161,
name: 'Arbitrum One',
- explorerUrl: 'https://arbiscan.io',
- partnerChainID: 1,
- partnerChainIDs: [],
- isArbitrum: true,
+ parentChainId: 1,
tokenBridge: mainnetTokenBridge,
ethBridge: mainnetETHBridge,
teleporter: {
@@ -210,19 +201,10 @@ export const networks: Networks = {
},
confirmPeriodBlocks: 45818,
isCustom: false,
- retryableLifetimeSeconds: SEVEN_DAYS_IN_SECONDS,
- nitroGenesisBlock: 22207817,
- nitroGenesisL1Block: 15447158,
- /**
- * Finalisation on mainnet can be up to 2 epochs = 64 blocks on mainnet
- * We add 10 minutes for the system to create and redeem the ticket, plus some extra buffer of time
- * (Total timeout: 30 minutes)
- */
- depositTimeout: 1800000,
- blockTime: ARB_MINIMUM_BLOCK_TIME_IN_SECONDS,
+ isTestnet: false,
},
42170: {
- chainID: 42170,
+ chainId: 42170,
confirmPeriodBlocks: 45818,
ethBridge: {
bridge: '0xC1Ebd02f738644983b6C4B2d440b8e77DdE276Bd',
@@ -231,45 +213,33 @@ export const networks: Networks = {
rollup: '0xFb209827c58283535b744575e11953DCC4bEAD88',
sequencerInbox: '0x211E1c4c7f1bF5351Ac850Ed10FD68CFfCF6c21b',
},
- explorerUrl: 'https://nova.arbiscan.io',
- isArbitrum: true,
isCustom: false,
+ isTestnet: false,
name: 'Arbitrum Nova',
- partnerChainID: 1,
- partnerChainIDs: [],
- retryableLifetimeSeconds: SEVEN_DAYS_IN_SECONDS,
+ parentChainId: 1,
tokenBridge: {
- l1CustomGateway: '0x23122da8C581AA7E0d07A36Ff1f16F799650232f',
- l1ERC20Gateway: '0xB2535b988dcE19f9D71dfB22dB6da744aCac21bf',
- l1GatewayRouter: '0xC840838Bc438d73C16c2f8b22D2Ce3669963cD48',
- l1MultiCall: '0x8896D23AfEA159a5e9b72C9Eb3DC4E2684A38EA3',
- l1ProxyAdmin: '0xa8f7DdEd54a726eB873E98bFF2C95ABF2d03e560',
- l1Weth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
- l1WethGateway: '0xE4E2121b479017955Be0b175305B35f312330BaE',
- l2CustomGateway: '0xbf544970E6BD77b21C6492C281AB60d0770451F4',
- l2ERC20Gateway: '0xcF9bAb7e53DDe48A6DC4f286CB14e05298799257',
- l2GatewayRouter: '0x21903d3F8176b1a0c17E953Cd896610Be9fFDFa8',
- l2Multicall: '0x5e1eE626420A354BbC9a95FeA1BAd4492e3bcB86',
- l2ProxyAdmin: '0xada790b026097BfB36a5ed696859b97a96CEd92C',
- l2Weth: '0x722E8BdD2ce80A4422E880164f2079488e115365',
- l2WethGateway: '0x7626841cB6113412F9c88D3ADC720C9FAC88D9eD',
+ parentCustomGateway: '0x23122da8C581AA7E0d07A36Ff1f16F799650232f',
+ parentErc20Gateway: '0xB2535b988dcE19f9D71dfB22dB6da744aCac21bf',
+ parentGatewayRouter: '0xC840838Bc438d73C16c2f8b22D2Ce3669963cD48',
+ parentMultiCall: '0x8896D23AfEA159a5e9b72C9Eb3DC4E2684A38EA3',
+ parentProxyAdmin: '0xa8f7DdEd54a726eB873E98bFF2C95ABF2d03e560',
+ parentWeth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
+ parentWethGateway: '0xE4E2121b479017955Be0b175305B35f312330BaE',
+ childCustomGateway: '0xbf544970E6BD77b21C6492C281AB60d0770451F4',
+ childErc20Gateway: '0xcF9bAb7e53DDe48A6DC4f286CB14e05298799257',
+ childGatewayRouter: '0x21903d3F8176b1a0c17E953Cd896610Be9fFDFa8',
+ childMultiCall: '0x5e1eE626420A354BbC9a95FeA1BAd4492e3bcB86',
+ childProxyAdmin: '0xada790b026097BfB36a5ed696859b97a96CEd92C',
+ childWeth: '0x722E8BdD2ce80A4422E880164f2079488e115365',
+ childWethGateway: '0x7626841cB6113412F9c88D3ADC720C9FAC88D9eD',
},
teleporter: {
l1Teleporter: '0xCBd9c6e310D6AaDeF9F025f716284162F0158992',
l2ForwarderFactory: '0x791d2AbC6c3A459E13B9AdF54Fb5e97B7Af38f87',
},
- nitroGenesisBlock: 0,
- nitroGenesisL1Block: 0,
- /**
- * Finalisation on mainnet can be up to 2 epochs = 64 blocks on mainnet
- * We add 10 minutes for the system to create and redeem the ticket, plus some extra buffer of time
- * (Total timeout: 30 minutes)
- */
- depositTimeout: 1800000,
- blockTime: ARB_MINIMUM_BLOCK_TIME_IN_SECONDS,
},
421614: {
- chainID: 421614,
+ chainId: 421614,
confirmPeriodBlocks: 20,
ethBridge: {
bridge: '0x38f918D0E9F1b721EDaA41302E399fa1B79333a9',
@@ -278,377 +248,306 @@ export const networks: Networks = {
rollup: '0xd80810638dbDF9081b72C1B33c65375e807281C8',
sequencerInbox: '0x6c97864CE4bEf387dE0b3310A44230f7E3F1be0D',
},
- explorerUrl: 'https://sepolia-explorer.arbitrum.io',
- isArbitrum: true,
isCustom: false,
+ isTestnet: true,
name: 'Arbitrum Rollup Sepolia Testnet',
- partnerChainID: 11155111,
- partnerChainIDs: [],
- retryableLifetimeSeconds: SEVEN_DAYS_IN_SECONDS,
+ parentChainId: 11155111,
tokenBridge: {
- l1CustomGateway: '0xba2F7B6eAe1F9d174199C5E4867b563E0eaC40F3',
- l1ERC20Gateway: '0x902b3E5f8F19571859F4AB1003B960a5dF693aFF',
- l1GatewayRouter: '0xcE18836b233C83325Cc8848CA4487e94C6288264',
- l1MultiCall: '0xded9AD2E65F3c4315745dD915Dbe0A4Df61b2320',
- l1ProxyAdmin: '0xDBFC2FfB44A5D841aB42b0882711ed6e5A9244b0',
- l1Weth: '0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9',
- l1WethGateway: '0xA8aD8d7e13cbf556eE75CB0324c13535d8100e1E',
- l2CustomGateway: '0x8Ca1e1AC0f260BC4dA7Dd60aCA6CA66208E642C5',
- l2ERC20Gateway: '0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502',
- l2GatewayRouter: '0x9fDD1C4E4AA24EEc1d913FABea925594a20d43C7',
- l2Multicall: '0xA115146782b7143fAdB3065D86eACB54c169d092',
- l2ProxyAdmin: '0x715D99480b77A8d9D603638e593a539E21345FdF',
- l2Weth: '0x980B62Da83eFf3D4576C647993b0c1D7faf17c73',
- l2WethGateway: '0xCFB1f08A4852699a979909e22c30263ca249556D',
+ parentCustomGateway: '0xba2F7B6eAe1F9d174199C5E4867b563E0eaC40F3',
+ parentErc20Gateway: '0x902b3E5f8F19571859F4AB1003B960a5dF693aFF',
+ parentGatewayRouter: '0xcE18836b233C83325Cc8848CA4487e94C6288264',
+ parentMultiCall: '0xded9AD2E65F3c4315745dD915Dbe0A4Df61b2320',
+ parentProxyAdmin: '0xDBFC2FfB44A5D841aB42b0882711ed6e5A9244b0',
+ parentWeth: '0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9',
+ parentWethGateway: '0xA8aD8d7e13cbf556eE75CB0324c13535d8100e1E',
+ childCustomGateway: '0x8Ca1e1AC0f260BC4dA7Dd60aCA6CA66208E642C5',
+ childErc20Gateway: '0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502',
+ childGatewayRouter: '0x9fDD1C4E4AA24EEc1d913FABea925594a20d43C7',
+ childMultiCall: '0xA115146782b7143fAdB3065D86eACB54c169d092',
+ childProxyAdmin: '0x715D99480b77A8d9D603638e593a539E21345FdF',
+ childWeth: '0x980B62Da83eFf3D4576C647993b0c1D7faf17c73',
+ childWethGateway: '0xCFB1f08A4852699a979909e22c30263ca249556D',
},
teleporter: {
l1Teleporter: '0x9E86BbF020594D7FFe05bF32EEDE5b973579A968',
l2ForwarderFactory: '0x88feBaFBb4E36A4E7E8874E4c9Fd73A9D59C2E7c',
},
- nitroGenesisBlock: 0,
- nitroGenesisL1Block: 0,
- depositTimeout: 1800000,
- blockTime: ARB_MINIMUM_BLOCK_TIME_IN_SECONDS,
},
}
/**
* Determines if a chain is a parent of *any* other chain. Could be an L1 or an L2 chain.
*/
-const isParentChain = (chain: L1Network | L2Network): boolean => {
- return chain.partnerChainIDs.length > 0
-}
-
-/**
- * Determines if a chain is an Arbitrum chain. Could be an L2 or an L3 chain.
- */
-const isArbitrumNetwork = (
- chain: L1Network | L2Network
-): chain is L2Network => {
- return chain.isArbitrum
-}
-
-/**
- * Determines if a chain is specifically an L1 chain (not L2 or L3).
- */
-export const isL1Network = (
- chain: L1Network | L2Network
-): chain is L1Network => {
- return !chain.isArbitrum
-}
-
-/**
- * Builds an object that is a list of chains filtered by the provided predicate function indexed by their chain id
- * @param filterFn - A predicate function to determine if a chain should be included.
- * @return An object with only the filtered chains.
- */
-const getChainsByType = (
- filterFn: (chain: L1Network | L2Network) => boolean
-): T => {
- return Object.entries(networks).reduce(
- (accumulator, [chainId, chainData]) => {
- if (filterFn(chainData)) {
- accumulator[chainId] = chainData
- }
- return accumulator
- },
- {}
- ) as T
-}
-
-const getL1Chains = () => getChainsByType(isL1Network)
-const getArbitrumChains = () => getChainsByType(isArbitrumNetwork)
-
-/**
- * Returns the parent chain for the given chain.
- */
-export const getParentForNetwork = (chain: L1Network | L2Network) => {
- if (!isArbitrumNetwork(chain)) {
- throw new ArbSdkError(`Chain ${chain.chainID} is not an Arbitrum chain.`)
- }
-
- const parentChain: L1Network | L2Network | undefined =
- networks[chain.partnerChainID]
-
- if (!parentChain || !isParentChain(parentChain)) {
- throw new ArbSdkError(
- `Parent chain ${chain.partnerChainID} not recognized for chain ${chain.chainID}.`
- )
- }
-
- return parentChain
+export const isParentNetwork = (
+ parentChainOrChainId: ArbitrumNetwork | number
+): boolean => {
+ const parentChainId =
+ typeof parentChainOrChainId === 'number'
+ ? parentChainOrChainId
+ : parentChainOrChainId.chainId
+
+ // Check if there are any chains that have this chain as its parent chain
+ return getArbitrumNetworks().some(c => c.parentChainId === parentChainId)
}
/**
- * Returns a list of children chains for the given chain.
+ * Returns a list of children chains for the given chain or chain id.
*/
-const getChildrenForNetwork = (chain: L1Network | L2Network): L2Network[] => {
- const arbitrumChains = getArbitrumChains()
-
- return Object.values(arbitrumChains).filter(
- arbitrumChain => arbitrumChain.partnerChainID === chain.chainID
+export const getChildrenForNetwork = (
+ parentChainOrChainId: ArbitrumNetwork | number
+): ArbitrumNetwork[] => {
+ const parentChainId =
+ typeof parentChainOrChainId === 'number'
+ ? parentChainOrChainId
+ : parentChainOrChainId.chainId
+
+ return getArbitrumNetworks().filter(
+ arbitrumChain => arbitrumChain.parentChainId === parentChainId
)
}
/**
- * Index of *only* L1 chains that have been added.
- */
-export let l1Networks: L1Networks = getL1Chains()
-
-/**
- * Index of all Arbitrum chains that have been added.
- */
-export let l2Networks: L2Networks = getArbitrumChains()
-
-/**
- * Returns the network associated with the given Signer, Provider or chain id.
- * @note Throws if the chain is not recognized.
+ * Returns the Arbitrum chain associated with the given signer, provider or chain id.
+ *
+ * @note Throws if the chain is not an Arbitrum chain.
*/
-export const getNetwork = async (
- signerOrProviderOrChainID: SignerOrProvider | number,
- layer: 1 | 2
-) => {
- const chainID = await (async () => {
- if (typeof signerOrProviderOrChainID === 'number') {
- return signerOrProviderOrChainID
- }
- const provider = SignerProviderUtils.getProviderOrThrow(
- signerOrProviderOrChainID
- )
-
- const { chainId } = await provider.getNetwork()
- return chainId
- })()
-
- let network: L1Network | L2Network | undefined = undefined
-
- if (layer === 1) {
- network = getL1Chains()[chainID]
- } else {
- network = getArbitrumChains()[chainID]
+export function getArbitrumNetwork(chainId: number): ArbitrumNetwork
+export function getArbitrumNetwork(
+ signerOrProvider: SignerOrProvider
+): Promise
+export function getArbitrumNetwork(
+ signerOrProviderOrChainId: SignerOrProvider | number
+): ArbitrumNetwork | Promise {
+ if (typeof signerOrProviderOrChainId === 'number') {
+ return getArbitrumNetworkByChainId(signerOrProviderOrChainId)
}
+ return getArbitrumNetworkBySignerOrProvider(signerOrProviderOrChainId)
+}
+function getArbitrumNetworkByChainId(chainId: number): ArbitrumNetwork {
+ const network = getArbitrumNetworks().find(n => n.chainId === chainId)
if (!network) {
- throw new ArbSdkError(`Unrecognized network ${chainID}.`)
+ throw new ArbSdkError(`Unrecognized network ${chainId}.`)
}
-
return network
}
-/**
- * Returns the L1 chain associated with the given signer, provider or chain id.
- *
- * @note Throws if the chain is not an L1 chain.
- */
-export const getL1Network = (
- signerOrProviderOrChainID: SignerOrProvider | number
-): Promise => {
- return getNetwork(signerOrProviderOrChainID, 1) as Promise
+async function getArbitrumNetworkBySignerOrProvider(
+ signerOrProvider: SignerOrProvider
+): Promise {
+ const provider = SignerProviderUtils.getProviderOrThrow(signerOrProvider)
+ const { chainId } = await provider.getNetwork()
+ return getArbitrumNetworkByChainId(chainId)
}
/**
- * Returns the Arbitrum chain associated with the given signer, provider or chain id.
- *
- * @note Throws if the chain is not an Arbitrum chain.
+ * Returns all Arbitrum networks registered in the SDK, both default and custom.
*/
-export const getL2Network = (
- signerOrProviderOrChainID: SignerOrProvider | number
-): Promise => {
- return getNetwork(signerOrProviderOrChainID, 2) as Promise
+export function getArbitrumNetworks(): ArbitrumNetwork[] {
+ return Object.values(networks)
}
+export type ArbitrumNetworkInformationFromRollup = Pick<
+ ArbitrumNetwork,
+ 'parentChainId' | 'confirmPeriodBlocks' | 'ethBridge'
+>
+
/**
- * Returns the addresses of all contracts that make up the ETH bridge
- * @param rollupContractAddress Address of the Rollup contract
- * @param l1SignerOrProvider A parent chain signer or provider
- * @returns EthBridge object with all information about the ETH bridge
+ * Returns all the information about an Arbitrum network that can be fetched from its Rollup contract.
+ *
+ * @param rollupAddress Address of the Rollup contract on the parent chain
+ * @param parentProvider Provider for the parent chain
+ *
+ * @returns An {@link ArbitrumNetworkInformationFromRollup} object
*/
-export const getEthBridgeInformation = async (
- rollupContractAddress: string,
- l1SignerOrProvider: SignerOrProvider
-): Promise => {
+export async function getArbitrumNetworkInformationFromRollup(
+ rollupAddress: string,
+ parentProvider: Provider
+): Promise {
const rollup = RollupAdminLogic__factory.connect(
- rollupContractAddress,
- l1SignerOrProvider
+ rollupAddress,
+ parentProvider
)
- const [bridge, inbox, sequencerInbox, outbox] = await Promise.all([
- rollup.bridge(),
- rollup.inbox(),
- rollup.sequencerInbox(),
- rollup.outbox(),
- ])
+ const [bridge, inbox, sequencerInbox, outbox, confirmPeriodBlocks] =
+ await Promise.all([
+ rollup.bridge(),
+ rollup.inbox(),
+ rollup.sequencerInbox(),
+ rollup.outbox(),
+ rollup.confirmPeriodBlocks(),
+ ])
return {
- bridge,
- inbox,
- sequencerInbox,
- outbox,
- rollup: rollupContractAddress,
+ parentChainId: (await parentProvider.getNetwork()).chainId,
+ confirmPeriodBlocks: confirmPeriodBlocks.toNumber(),
+ ethBridge: {
+ bridge,
+ inbox,
+ sequencerInbox,
+ outbox,
+ rollup: rollupAddress,
+ },
}
}
/**
- * Adds any chain to the global index of networks and updates the parent/child relationships.
+ * Registers a custom Arbitrum network.
+ *
+ * @param network {@link ArbitrumNetwork} to be registered
+ * @param options Additional options
+ * @param options.throwIfAlreadyRegistered Whether or not the function should throw if the network is already registered, defaults to `false`
*/
-const addNetwork = (network: L1Network | L2Network) => {
- // store the network with the rest of the networks
- networks[network.chainID] = network
+export function registerCustomArbitrumNetwork(
+ network: ArbitrumNetwork,
+ options?: { throwIfAlreadyRegistered?: boolean }
+): ArbitrumNetwork {
+ const throwIfAlreadyRegistered = options?.throwIfAlreadyRegistered ?? false
- // if it's a parent chain (L1 or L2), assign it as parent to all the children
- if (isParentChain(network)) {
- const children = getChildrenForNetwork(network)
-
- children.forEach(child => {
- child.partnerChainID = network.chainID
- })
+ if (!network.isCustom) {
+ throw new ArbSdkError(
+ `Custom network ${network.chainId} must have isCustom flag set to true`
+ )
}
- // if it's an arbitrum chain, add it to the parent's list of children
- if (isArbitrumNetwork(network)) {
- const parent: L1Network | L2Network | undefined =
- networks[network.partnerChainID]
+ if (typeof networks[network.chainId] !== 'undefined') {
+ const message = `Network ${network.chainId} already included`
- if (!parent) {
- throw new ArbSdkError(
- `Network ${network.chainID}'s parent network ${network.partnerChainID} is not recognized`
- )
+ if (throwIfAlreadyRegistered) {
+ throw new ArbSdkError(message)
}
- parent.partnerChainIDs = [...parent.partnerChainIDs, network.chainID]
+ console.warn(message)
}
- l1Networks = getL1Chains()
- l2Networks = getArbitrumChains()
+ // store the network with the rest of the networks
+ networks[network.chainId] = network
+
+ return network
}
/**
- * Registers a pair of custom L1 and L2 chains, or a single custom Arbitrum chain (L2 or L3).
- *
- * @param customL1Network the custom L1 chain (optional)
- * @param customL2Network the custom L2 or L3 chain
+ * Creates a function that resets the networks index to default. Useful in development.
*/
-export const addCustomNetwork = ({
- customL1Network,
- customL2Network,
-}: {
- customL1Network?: L1Network
- customL2Network: L2Network
-}): void => {
- if (customL1Network) {
- if (customL1Network.chainID !== customL2Network.partnerChainID) {
- throw new ArbSdkError(
- `Partner chain id for L2 network ${customL2Network.chainID} doesn't match the provided L1 network. Expected ${customL1Network.chainID} but got ${customL2Network.partnerChainID}.`
- )
- }
-
- // check the if the parent chain is in any of the lists
- if (l1Networks[customL1Network.chainID]) {
- throw new ArbSdkError(
- `Network ${customL1Network.chainID} already included`
- )
- } else if (!customL1Network.isCustom) {
- throw new ArbSdkError(
- `Custom network ${customL1Network.chainID} must have isCustom flag set to true`
- )
- }
+const createNetworkStateHandler = () => {
+ const initialState = JSON.parse(JSON.stringify(networks))
- addNetwork(customL1Network)
+ return {
+ resetNetworksToDefault: () => {
+ Object.keys(networks).forEach(key => delete networks[key])
+ Object.assign(networks, JSON.parse(JSON.stringify(initialState)))
+ },
}
+}
- if (l2Networks[customL2Network.chainID]) {
- throw new ArbSdkError(`Network ${customL2Network.chainID} already included`)
- } else if (!customL2Network.isCustom) {
- throw new ArbSdkError(
- `Custom network ${customL2Network.chainID} must have isCustom flag set to true`
- )
+export function getNitroGenesisBlock(
+ arbitrumChainOrChainId: ArbitrumNetwork | number
+) {
+ const arbitrumChainId =
+ typeof arbitrumChainOrChainId === 'number'
+ ? arbitrumChainOrChainId
+ : arbitrumChainOrChainId.chainId
+
+ // all networks except Arbitrum One started off with Nitro
+ if (arbitrumChainId === 42161) {
+ return ARB1_NITRO_GENESIS_L2_BLOCK
}
- addNetwork(customL2Network)
+ return 0
}
-/**
- * Registers a custom network that matches the one created by a Nitro local node. Useful in development.
- *
- * @see {@link https://github.com/OffchainLabs/nitro}
- */
-export const addDefaultLocalNetwork = (): {
- l1Network: L1Network
- l2Network: L2Network
-} => {
- const defaultLocalL1Network: L1Network = {
- blockTime: 10,
- chainID: 1337,
- explorerUrl: '',
- isCustom: true,
- name: 'EthLocal',
- partnerChainIDs: [412346],
- isArbitrum: false,
+export async function getMulticallAddress(
+ providerOrChainId: Provider | number
+): Promise {
+ const chains = getArbitrumNetworks()
+
+ const chainId =
+ typeof providerOrChainId === 'number'
+ ? providerOrChainId
+ : (await providerOrChainId.getNetwork()).chainId
+ const chain = chains.find(c => c.chainId === chainId)
+
+ // The provided chain is found in the list
+ if (typeof chain !== 'undefined') {
+ assertArbitrumNetworkHasTokenBridge(chain)
+ // Return the address of Multicall on the chain
+ return chain.tokenBridge.childMultiCall
}
- const defaultLocalL2Network: L2Network = {
- chainID: 412346,
- confirmPeriodBlocks: 20,
- ethBridge: {
- bridge: '0x2b360A9881F21c3d7aa0Ea6cA0De2a3341d4eF3C',
- inbox: '0xfF4a24b22F94979E9ba5f3eb35838AA814bAD6F1',
- outbox: '0x49940929c7cA9b50Ff57a01d3a92817A414E6B9B',
- rollup: '0x65a59D67Da8e710Ef9A01eCa37f83f84AEdeC416',
- sequencerInbox: '0xE7362D0787b51d8C72D504803E5B1d6DcdA89540',
- },
- explorerUrl: '',
- isArbitrum: true,
- isCustom: true,
- name: 'ArbLocal',
- partnerChainID: 1337,
- partnerChainIDs: [],
- retryableLifetimeSeconds: 604800,
- nitroGenesisBlock: 0,
- nitroGenesisL1Block: 0,
- depositTimeout: 900000,
- tokenBridge: {
- l1CustomGateway: '0x3DF948c956e14175f43670407d5796b95Bb219D8',
- l1ERC20Gateway: '0x4A2bA922052bA54e29c5417bC979Daaf7D5Fe4f4',
- l1GatewayRouter: '0x525c2aBA45F66987217323E8a05EA400C65D06DC',
- l1MultiCall: '0xDB2D15a3EB70C347E0D2C2c7861cAFb946baAb48',
- l1ProxyAdmin: '0xe1080224B632A93951A7CFA33EeEa9Fd81558b5e',
- l1Weth: '0x408Da76E87511429485C32E4Ad647DD14823Fdc4',
- l1WethGateway: '0xF5FfD11A55AFD39377411Ab9856474D2a7Cb697e',
- l2CustomGateway: '0x525c2aBA45F66987217323E8a05EA400C65D06DC',
- l2ERC20Gateway: '0xe1080224B632A93951A7CFA33EeEa9Fd81558b5e',
- l2GatewayRouter: '0x1294b86822ff4976BfE136cB06CF43eC7FCF2574',
- l2Multicall: '0xDB2D15a3EB70C347E0D2C2c7861cAFb946baAb48',
- l2ProxyAdmin: '0xda52b25ddB0e3B9CC393b0690Ac62245Ac772527',
- l2Weth: '0x408Da76E87511429485C32E4Ad647DD14823Fdc4',
- l2WethGateway: '0x4A2bA922052bA54e29c5417bC979Daaf7D5Fe4f4',
- },
- blockTime: ARB_MINIMUM_BLOCK_TIME_IN_SECONDS,
+ // The provided chain is not found in the list
+ // Try to find a chain that references this chain as its parent
+ const childChain = chains.find(c => c.parentChainId === chainId)
+
+ // No chains reference this chain as its parent
+ if (typeof childChain === 'undefined') {
+ throw new Error(
+ `Failed to retrieve Multicall address for chain: ${chainId}`
+ )
}
- addCustomNetwork({
- customL1Network: defaultLocalL1Network,
- customL2Network: defaultLocalL2Network,
- })
+ assertArbitrumNetworkHasTokenBridge(childChain)
+ // Return the address of Multicall on the parent chain
+ return childChain.tokenBridge.parentMultiCall
+}
+/**
+ * Maps the old {@link L2Network.tokenBridge} (from SDK v3) to {@link ArbitrumNetwork.tokenBridge} (from SDK v4).
+ */
+export function mapL2NetworkTokenBridgeToTokenBridge(
+ input: L2NetworkTokenBridge
+): TokenBridge {
return {
- l1Network: defaultLocalL1Network,
- l2Network: defaultLocalL2Network,
+ parentGatewayRouter: input.l1GatewayRouter,
+ childGatewayRouter: input.l2GatewayRouter,
+ parentErc20Gateway: input.l1ERC20Gateway,
+ childErc20Gateway: input.l2ERC20Gateway,
+ parentCustomGateway: input.l1CustomGateway,
+ childCustomGateway: input.l2CustomGateway,
+ parentWethGateway: input.l1WethGateway,
+ childWethGateway: input.l2WethGateway,
+ parentWeth: input.l1Weth,
+ childWeth: input.l2Weth,
+ parentProxyAdmin: input.l1ProxyAdmin,
+ childProxyAdmin: input.l2ProxyAdmin,
+ parentMultiCall: input.l1MultiCall,
+ childMultiCall: input.l2Multicall,
}
}
/**
- * Creates a function that resets the networks index to default. Useful in development.
+ * Maps the old {@link L2Network} (from SDK v3) to {@link ArbitrumNetwork} (from SDK v4).
*/
-const createNetworkStateHandler = () => {
- const initialState = JSON.parse(JSON.stringify(networks))
-
+export function mapL2NetworkToArbitrumNetwork(
+ l2Network: L2Network
+): ArbitrumNetwork {
return {
- resetNetworksToDefault: () => {
- Object.keys(networks).forEach(key => delete networks[key])
- Object.assign(networks, JSON.parse(JSON.stringify(initialState)))
- l1Networks = getL1Chains()
- l2Networks = getArbitrumChains()
- },
+ // Spread properties
+ ...l2Network,
+ // Map properties that were changed
+ chainId: l2Network.chainID,
+ parentChainId: l2Network.partnerChainID,
+ tokenBridge: mapL2NetworkTokenBridgeToTokenBridge(l2Network.tokenBridge),
+ }
+}
+
+/**
+ * Asserts that the given object has a token bridge. This is useful because not all Arbitrum network
+ * operations require a token bridge.
+ *
+ * @param network {@link ArbitrumNetwork} object
+ * @throws ArbSdkError if the object does not have a token bridge
+ */
+export function assertArbitrumNetworkHasTokenBridge(
+ network: T
+): asserts network is T & { tokenBridge: TokenBridge } {
+ if (
+ typeof network === 'undefined' ||
+ !('tokenBridge' in network) ||
+ typeof network.tokenBridge === 'undefined'
+ ) {
+ throw new ArbSdkError(
+ `The ArbitrumNetwork object with chainId ${network.chainId} is missing the token bridge contracts addresses. Please add them in the "tokenBridge" property.`
+ )
}
}
diff --git a/src/lib/dataEntities/transactionRequest.ts b/src/lib/dataEntities/transactionRequest.ts
index 67803ddf67..e0ddc5c424 100644
--- a/src/lib/dataEntities/transactionRequest.ts
+++ b/src/lib/dataEntities/transactionRequest.ts
@@ -1,27 +1,27 @@
import { TransactionRequest, Provider } from '@ethersproject/providers'
import { BigNumber } from 'ethers'
import {
- L1ToL2MessageGasParams,
- L1ToL2MessageParams,
-} from '../message/L1ToL2MessageCreator'
+ ParentToChildMessageGasParams,
+ ParentToChildMessageParams,
+} from '../message/ParentToChildMessageCreator'
import { isDefined } from '../utils/lib'
/**
* A transaction request for a transaction that will trigger some sort of
- * execution on the L2
+ * execution on the child chain
*/
-export interface L1ToL2TransactionRequest {
+export interface ParentToChildTransactionRequest {
/**
- * Core fields needed to form the L1 component of the transaction request
+ * Core fields needed to form the parent component of the transaction request
*/
txRequest: Required<
Pick
>
/**
* Information about the retryable ticket, and it's subsequent execution, that
- * will occur on L2
+ * will occur on the child chain
*/
- retryableData: L1ToL2MessageParams & L1ToL2MessageGasParams
+ retryableData: ParentToChildMessageParams & ParentToChildMessageGasParams
/**
* If this request were sent now, would it have enough margin to reliably succeed
*/
@@ -29,44 +29,48 @@ export interface L1ToL2TransactionRequest {
}
/**
- * A transaction request for a transaction that will trigger an L2 to L1 message
+ * A transaction request for a transaction that will trigger a child to parent message
*/
-export interface L2ToL1TransactionRequest {
+export interface ChildToParentTransactionRequest {
txRequest: Required<
Pick
>
/**
- * Estimate the gas limit required to execute the withdrawal on L1.
+ * Estimate the gas limit required to execute the withdrawal on the parent chain.
* Note that this is only a rough estimate as it may not be possible to know
* the exact size of the proof straight away, however the real value should be
* within a few thousand gas of this estimate.
*/
- estimateL1GasLimit: (l1Provider: Provider) => Promise
+ estimateParentGasLimit: (l1Provider: Provider) => Promise
}
/**
- * Ensure the T is not of TransactionRequest type by ensure it doesnt have a specific TransactionRequest property
+ * Ensure the T is not of TransactionRequest type by ensure it doesn't have a specific TransactionRequest property
*/
type IsNotTransactionRequest = T extends { txRequest: any } ? never : T
/**
- * Check if an object is of L1ToL2TransactionRequest type
+ * Check if an object is of ParentToChildTransactionRequest type
* @param possibleRequest
* @returns
*/
-export const isL1ToL2TransactionRequest = (
- possibleRequest: IsNotTransactionRequest | L1ToL2TransactionRequest
-): possibleRequest is L1ToL2TransactionRequest => {
- return isDefined((possibleRequest as L1ToL2TransactionRequest).txRequest)
+export const isParentToChildTransactionRequest = (
+ possibleRequest: IsNotTransactionRequest | ParentToChildTransactionRequest
+): possibleRequest is ParentToChildTransactionRequest => {
+ return isDefined(
+ (possibleRequest as ParentToChildTransactionRequest).txRequest
+ )
}
/**
- * Check if an object is of L2ToL1TransactionRequest type
+ * Check if an object is of ChildToParentTransactionRequest type
* @param possibleRequest
* @returns
*/
-export const isL2ToL1TransactionRequest = (
- possibleRequest: IsNotTransactionRequest | L2ToL1TransactionRequest
-): possibleRequest is L2ToL1TransactionRequest => {
- return (possibleRequest as L2ToL1TransactionRequest).txRequest != undefined
+export const isChildToParentTransactionRequest = (
+ possibleRequest: IsNotTransactionRequest | ChildToParentTransactionRequest
+): possibleRequest is ChildToParentTransactionRequest => {
+ return (
+ (possibleRequest as ChildToParentTransactionRequest).txRequest != undefined
+ )
}
diff --git a/src/lib/inbox/inbox.ts b/src/lib/inbox/inbox.ts
index 832844fe16..7e6f6a4259 100644
--- a/src/lib/inbox/inbox.ts
+++ b/src/lib/inbox/inbox.ts
@@ -28,11 +28,7 @@ import { SequencerInbox__factory } from '../abi/factories/SequencerInbox__factor
import { IInbox__factory } from '../abi/factories/IInbox__factory'
import { RequiredPick } from '../utils/types'
import { MessageDeliveredEvent } from '../abi/Bridge'
-import {
- L1Network,
- L2Network,
- getParentForNetwork,
-} from '../dataEntities/networks'
+import { ArbitrumNetwork } from '../dataEntities/networks'
import { SignerProviderUtils } from '../dataEntities/signerOrProvider'
import { FetchedEvent, EventFetcher } from '../utils/eventFetcher'
import { MultiCaller, CallInput } from '../utils/multicall'
@@ -51,12 +47,12 @@ type ForceInclusionParams = FetchedEvent & {
delayedAcc: string
}
-type GasComponentsWithL2Part = {
+type GasComponentsWithChildPart = {
gasEstimate: BigNumber
gasEstimateForL1: BigNumber
baseFee: BigNumber
l1BaseFeeEstimate: BigNumber
- gasEstimateForL2: BigNumber
+ gasEstimateForChild: BigNumber
}
type RequiredTransactionRequestType = RequiredPick<
TransactionRequest,
@@ -69,18 +65,15 @@ export class InboxTools {
/**
* Parent chain provider
*/
- private readonly l1Provider: Provider
- /**
- * Parent chain for the given Arbitrum chain, can be an L1 or an L2
- */
- private readonly l1Network: L1Network | L2Network
+ private readonly parentProvider: Provider
constructor(
- private readonly l1Signer: Signer,
- private readonly l2Network: L2Network
+ private readonly parentSigner: Signer,
+ private readonly childChain: ArbitrumNetwork
) {
- this.l1Provider = SignerProviderUtils.getProviderOrThrow(this.l1Signer)
- this.l1Network = getParentForNetwork(l2Network)
+ this.parentProvider = SignerProviderUtils.getProviderOrThrow(
+ this.parentSigner
+ )
}
/**
@@ -95,12 +88,12 @@ export class InboxTools {
blockNumber: number,
blockTimestamp: number
): Promise {
- const isParentChainArbitrum = await isArbitrumChain(this.l1Provider)
+ const isParentChainArbitrum = await isArbitrumChain(this.parentProvider)
if (isParentChainArbitrum) {
const nodeInterface = NodeInterface__factory.connect(
NODE_INTERFACE_ADDRESS,
- this.l1Provider
+ this.parentProvider
)
try {
@@ -113,7 +106,7 @@ export class InboxTools {
// alternatively we use binary search to get the nearest block
const _blockNum = (
await getBlockRangesForL1Block({
- provider: this.l1Provider as JsonRpcProvider,
+ arbitrumProvider: this.parentProvider as JsonRpcProvider,
forL1Block: blockNumber - 1,
allowGreater: true,
})
@@ -127,7 +120,7 @@ export class InboxTools {
}
}
- const block = await this.l1Provider.getBlock(blockNumber)
+ const block = await this.parentProvider.getBlock(blockNumber)
const diff = block.timestamp - blockTimestamp
if (diff < 0) return block
@@ -141,14 +134,14 @@ export class InboxTools {
)
}
- //Check if this request is contract creation or not.
+ // Check if this request is contract creation or not.
private isContractCreation(
- transactionl2Request: TransactionRequest
+ childTransactionRequest: TransactionRequest
): boolean {
if (
- transactionl2Request.to === '0x' ||
- !isDefined(transactionl2Request.to) ||
- transactionl2Request.to === ethers.constants.AddressZero
+ childTransactionRequest.to === '0x' ||
+ !isDefined(childTransactionRequest.to) ||
+ childTransactionRequest.to === ethers.constants.AddressZero
) {
return true
}
@@ -157,32 +150,32 @@ export class InboxTools {
/**
* We should use nodeInterface to get the gas estimate is because we
- * are making a delayed inbox message which doesn't need l1 calldata
+ * are making a delayed inbox message which doesn't need parent calldata
* gas fee part.
*/
private async estimateArbitrumGas(
- transactionl2Request: RequiredTransactionRequestType,
- l2Provider: Provider
- ): Promise {
+ childTransactionRequest: RequiredTransactionRequestType,
+ childProvider: Provider
+ ): Promise {
const nodeInterface = NodeInterface__factory.connect(
NODE_INTERFACE_ADDRESS,
- l2Provider
+ childProvider
)
- const contractCreation = this.isContractCreation(transactionl2Request)
+ const contractCreation = this.isContractCreation(childTransactionRequest)
const gasComponents = await nodeInterface.callStatic.gasEstimateComponents(
- transactionl2Request.to || ethers.constants.AddressZero,
+ childTransactionRequest.to || ethers.constants.AddressZero,
contractCreation,
- transactionl2Request.data,
+ childTransactionRequest.data,
{
- from: transactionl2Request.from,
- value: transactionl2Request.value,
+ from: childTransactionRequest.from,
+ value: childTransactionRequest.value,
}
)
- const gasEstimateForL2: BigNumber = gasComponents.gasEstimate.sub(
+ const gasEstimateForChild: BigNumber = gasComponents.gasEstimate.sub(
gasComponents.gasEstimateForL1
)
- return { ...gasComponents, gasEstimateForL2 }
+ return { ...gasComponents, gasEstimateForChild }
}
/**
@@ -194,21 +187,21 @@ export class InboxTools {
let currentL1BlockNumber: number | undefined
const sequencerInbox = SequencerInbox__factory.connect(
- this.l2Network.ethBridge.sequencerInbox,
- this.l1Provider
+ this.childChain.ethBridge.sequencerInbox,
+ this.parentProvider
)
- const isParentChainArbitrum = await isArbitrumChain(this.l1Provider)
+ const isParentChainArbitrum = await isArbitrumChain(this.parentProvider)
if (isParentChainArbitrum) {
const arbProvider = new ArbitrumProvider(
- this.l1Provider as JsonRpcProvider
+ this.parentProvider as JsonRpcProvider
)
const currentArbBlock = await arbProvider.getBlock('latest')
currentL1BlockNumber = currentArbBlock.l1BlockNumber
}
- const multicall = await MultiCaller.fromProvider(this.l1Provider)
+ const multicall = await MultiCaller.fromProvider(this.parentProvider)
const multicallInput: [
CallInput>>,
ReturnType,
@@ -266,7 +259,7 @@ export class InboxTools {
maxSearchRangeBlocks: number,
rangeMultiplier: number
): Promise[]> {
- const eFetcher = new EventFetcher(this.l1Provider)
+ const eFetcher = new EventFetcher(this.parentProvider)
// events don't become eligible until they pass a delay
// find a block range which will emit eligible events
@@ -304,7 +297,7 @@ export class InboxTools {
/**
* Find the event of the latest message that can be force include
* @param maxSearchRangeBlocks The max range of blocks to search in.
- * Defaults to 3 * 6545 ( = ~3 days) prior to the first eligble block
+ * Defaults to 3 * 6545 ( = ~3 days) prior to the first eligible block
* @param startSearchRangeBlocks The start range of block to search in.
* Moves incrementally up to the maxSearchRangeBlocks. Defaults to 100;
* @param rangeMultiplier The multiplier to use when increasing the block range
@@ -314,11 +307,11 @@ export class InboxTools {
public async getForceIncludableEvent(
maxSearchRangeBlocks: number = 3 * 6545,
startSearchRangeBlocks = 100,
- rangeMultipler = 2
+ rangeMultiplier = 2
): Promise {
const bridge = Bridge__factory.connect(
- this.l2Network.ethBridge.bridge,
- this.l1Provider
+ this.childChain.ethBridge.bridge,
+ this.parentProvider
)
// events dont become eligible until they pass a delay
@@ -327,7 +320,7 @@ export class InboxTools {
bridge,
startSearchRangeBlocks,
maxSearchRangeBlocks,
- rangeMultipler
+ rangeMultiplier
)
// no events appeared within that time period
@@ -336,8 +329,8 @@ export class InboxTools {
// take the last event - as including this one will include all previous events
const eventInfo = events[events.length - 1]
const sequencerInbox = SequencerInbox__factory.connect(
- this.l2Network.ethBridge.sequencerInbox,
- this.l1Provider
+ this.childChain.ethBridge.sequencerInbox,
+ this.parentProvider
)
// has the sequencer inbox already read this latest message
const totalDelayedRead = await sequencerInbox.totalDelayedMessagesRead()
@@ -355,7 +348,7 @@ export class InboxTools {
/**
* Force includes all eligible messages in the delayed inbox.
- * The inbox contract doesnt allow a message to be force-included
+ * The inbox contract doesn't allow a message to be force-included
* until after a delay period has been completed.
* @param messageDeliveredEvent Provide this to include all messages up to this one. Responsibility is on the caller to check the eligibility of this event.
* @returns The force include transaction, or null if no eligible message were found for inclusion
@@ -376,14 +369,14 @@ export class InboxTools {
overrides?: Overrides
): Promise {
const sequencerInbox = SequencerInbox__factory.connect(
- this.l2Network.ethBridge.sequencerInbox,
- this.l1Signer
+ this.childChain.ethBridge.sequencerInbox,
+ this.parentSigner
)
const eventInfo =
messageDeliveredEvent || (await this.getForceIncludableEvent())
if (!eventInfo) return null
- const block = await this.l1Provider.getBlock(eventInfo.blockHash)
+ const block = await this.parentProvider.getBlock(eventInfo.blockHash)
return await sequencerInbox.functions.forceInclusion(
eventInfo.event.messageIndex.add(1),
@@ -398,19 +391,19 @@ export class InboxTools {
}
/**
- * Send l2 signed tx using delayed inox, which won't alias the sender's adddress
- * It will be automatically included by the sequencer on l2, if it isn't included
+ * Send Child Chain signed tx using delayed inbox, which won't alias the sender's address
+ * It will be automatically included by the sequencer on Chain, if it isn't included
* within 24 hours, you can force include it
- * @param signedTx A signed transaction which can be sent directly to network,
- * you can call inboxTools.signL2Message to get.
- * @returns The l1 delayed inbox's transaction itself.
+ * @param signedTx A signed transaction which can be sent directly to chain,
+ * you can call inboxTools.signChainMessage to get.
+ * @returns The parent delayed inbox's transaction itself.
*/
- public async sendL2SignedTx(
+ public async sendChildSignedTx(
signedTx: string
): Promise {
const delayedInbox = IInbox__factory.connect(
- this.l2Network.ethBridge.inbox,
- this.l1Signer
+ this.childChain.ethBridge.inbox,
+ this.parentSigner
)
const sendData = ethers.utils.solidityPack(
@@ -423,43 +416,43 @@ export class InboxTools {
/**
* Sign a transaction with msg.to, msg.value and msg.data.
- * You can use this as a helper to call inboxTools.sendL2SignedMessage
+ * You can use this as a helper to call inboxTools.sendChainSignedMessage
* above.
- * @param message A signed transaction which can be sent directly to network,
+ * @param txRequest A signed transaction which can be sent directly to chain,
* tx.to, tx.data, tx.value must be provided when not contract creation, if
* contractCreation is true, no need provide tx.to. tx.gasPrice and tx.nonce
* can be overrided. (You can also send contract creation transaction by set tx.to
* to zero address or null)
- * @param l2Signer ethers Signer type, used to sign l2 transaction
- * @returns The l1 delayed inbox's transaction signed data.
+ * @param childSigner ethers Signer type, used to sign Chain transaction
+ * @returns The parent delayed inbox's transaction signed data.
*/
- public async signL2Tx(
+ public async signChildTx(
txRequest: RequiredTransactionRequestType,
- l2Signer: Signer
+ childSigner: Signer
): Promise {
const tx: RequiredTransactionRequestType = { ...txRequest }
const contractCreation = this.isContractCreation(tx)
if (!isDefined(tx.nonce)) {
- tx.nonce = await l2Signer.getTransactionCount()
+ tx.nonce = await childSigner.getTransactionCount()
}
//check transaction type (if no transaction type or gasPrice provided, use eip1559 type)
if (tx.type === 1 || tx.gasPrice) {
if (tx.gasPrice) {
- tx.gasPrice = await l2Signer.getGasPrice()
+ tx.gasPrice = await childSigner.getGasPrice()
}
} else {
if (!isDefined(tx.maxFeePerGas)) {
- const feeData = await l2Signer.getFeeData()
+ const feeData = await childSigner.getFeeData()
tx.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas!
tx.maxFeePerGas = feeData.maxFeePerGas!
}
tx.type = 2
}
- tx.from = await l2Signer.getAddress()
- tx.chainId = await l2Signer.getChainId()
+ tx.from = await childSigner.getAddress()
+ tx.chainId = await childSigner.getChainId()
// if this is contract creation, user might not input the to address,
// however, it is needed when we call to estimateArbitrumGas, so
@@ -468,17 +461,17 @@ export class InboxTools {
tx.to = ethers.constants.AddressZero
}
- //estimate gas on l2
+ //estimate gas on child chain
try {
tx.gasLimit = (
- await this.estimateArbitrumGas(tx, l2Signer.provider!)
- ).gasEstimateForL2
+ await this.estimateArbitrumGas(tx, childSigner.provider!)
+ ).gasEstimateForChild
} catch (error) {
throw new ArbSdkError('execution failed (estimate gas failed)')
}
if (contractCreation) {
delete tx.to
}
- return await l2Signer.signTransaction(tx)
+ return await childSigner.signTransaction(tx)
}
}
diff --git a/src/lib/message/ChildToParentMessage.ts b/src/lib/message/ChildToParentMessage.ts
new file mode 100644
index 0000000000..7ac988d74e
--- /dev/null
+++ b/src/lib/message/ChildToParentMessage.ts
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2021, Offchain Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* eslint-env node */
+'use strict'
+
+import { Provider } from '@ethersproject/abstract-provider'
+import { Signer } from '@ethersproject/abstract-signer'
+import { BigNumber } from '@ethersproject/bignumber'
+import { BlockTag } from '@ethersproject/abstract-provider'
+
+import { ContractTransaction, Overrides } from 'ethers'
+import {
+ SignerProviderUtils,
+ SignerOrProvider,
+} from '../dataEntities/signerOrProvider'
+import * as classic from './ChildToParentMessageClassic'
+import * as nitro from './ChildToParentMessageNitro'
+import {
+ L2ToL1TransactionEvent as ClassicChildToParentTransactionEvent,
+ L2ToL1TxEvent as NitroChildToParentTransactionEvent,
+} from '../abi/ArbSys'
+import { isDefined } from '../utils/lib'
+import { EventArgs } from '../dataEntities/event'
+import { ChildToParentMessageStatus } from '../dataEntities/message'
+import {
+ getArbitrumNetwork,
+ getNitroGenesisBlock,
+} from '../dataEntities/networks'
+import { ArbSdkError } from '../dataEntities/errors'
+
+export type ChildToParentTransactionEvent =
+ | EventArgs
+ | EventArgs
+
+/**
+ * Conditional type for Signer or Provider. If T is of type Provider
+ * then ChildToParentMessageReaderOrWriter will be of type ChildToParentMessageReader.
+ * If T is of type Signer then ChildToParentMessageReaderOrWriter will be of
+ * type ChildToParentMessageWriter.
+ */
+export type ChildToParentMessageReaderOrWriter =
+ T extends Provider ? ChildToParentMessageReader : ChildToParentMessageWriter
+
+/**
+ * Base functionality for Child-to-Parent messages
+ */
+export class ChildToParentMessage {
+ protected isClassic(
+ e: ChildToParentTransactionEvent
+ ): e is EventArgs {
+ return isDefined(
+ (e as EventArgs).indexInBatch
+ )
+ }
+
+ /**
+ * Instantiates a new `ChildToParentMessageWriter` or `ChildToParentMessageReader` object.
+ *
+ * @param {SignerOrProvider} parentSignerOrProvider Signer or provider to be used for executing or reading the Child-to-Parent message.
+ * @param {ChildToParentTransactionEvent} event The event containing the data of the Child-to-Parent message.
+ * @param {Provider} [parentProvider] Optional. Used to override the Provider which is attached to `ParentSignerOrProvider` in case you need more control. This will be a required parameter in a future major version update.
+ */
+ public static fromEvent(
+ parentSignerOrProvider: T,
+ event: ChildToParentTransactionEvent,
+ parentProvider?: Provider
+ ): ChildToParentMessageReaderOrWriter
+ static fromEvent(
+ parentSignerOrProvider: T,
+ event: ChildToParentTransactionEvent,
+ parentProvider?: Provider
+ ): ChildToParentMessageReader | ChildToParentMessageWriter {
+ return SignerProviderUtils.isSigner(parentSignerOrProvider)
+ ? new ChildToParentMessageWriter(
+ parentSignerOrProvider,
+ event,
+ parentProvider
+ )
+ : new ChildToParentMessageReader(parentSignerOrProvider, event)
+ }
+
+ /**
+ * Get event logs for ChildToParent transactions.
+ * @param childProvider
+ * @param filter Block range filter
+ * @param position The batchnumber indexed field was removed in nitro and a position indexed field was added.
+ * For pre-nitro events the value passed in here will be used to find events with the same batchnumber.
+ * For post nitro events it will be used to find events with the same position.
+ * @param destination The parent destination of the ChildToParent message
+ * @param hash The uniqueId indexed field was removed in nitro and a hash indexed field was added.
+ * For pre-nitro events the value passed in here will be used to find events with the same uniqueId.
+ * For post nitro events it will be used to find events with the same hash.
+ * @param indexInBatch The index in the batch, only valid for pre-nitro events. This parameter is ignored post-nitro
+ * @returns Any classic and nitro events that match the provided filters.
+ */
+ public static async getChildToParentEvents(
+ childProvider: Provider,
+ filter: { fromBlock: BlockTag; toBlock: BlockTag },
+ position?: BigNumber,
+ destination?: string,
+ hash?: BigNumber,
+ indexInBatch?: BigNumber
+ ): Promise<(ChildToParentTransactionEvent & { transactionHash: string })[]> {
+ const childChain = await getArbitrumNetwork(childProvider)
+ const childNitroGenesisBlock = getNitroGenesisBlock(childChain)
+
+ const inClassicRange = (blockTag: BlockTag, nitroGenBlock: number) => {
+ if (typeof blockTag === 'string') {
+ // taking classic of "earliest", "latest", "earliest" and the nitro gen block
+ // yields 0, nitro gen, nitro gen since the classic range is always between 0 and nitro gen
+
+ switch (blockTag) {
+ case 'earliest':
+ return 0
+ case 'latest':
+ return nitroGenBlock
+ case 'pending':
+ return nitroGenBlock
+ default:
+ throw new ArbSdkError(`Unrecognised block tag. ${blockTag}`)
+ }
+ }
+ return Math.min(blockTag, nitroGenBlock)
+ }
+
+ const inNitroRange = (blockTag: BlockTag, nitroGenBlock: number) => {
+ // taking nitro range of "earliest", "latest", "earliest" and the nitro gen block
+ // yields nitro gen, latest, pending since the nitro range is always between nitro gen and latest/pending
+
+ if (typeof blockTag === 'string') {
+ switch (blockTag) {
+ case 'earliest':
+ return nitroGenBlock
+ case 'latest':
+ return 'latest'
+ case 'pending':
+ return 'pending'
+ default:
+ throw new ArbSdkError(`Unrecognised block tag. ${blockTag}`)
+ }
+ }
+
+ return Math.max(blockTag, nitroGenBlock)
+ }
+
+ // only fetch nitro events after the genesis block
+ const classicFilter = {
+ fromBlock: inClassicRange(filter.fromBlock, childNitroGenesisBlock),
+ toBlock: inClassicRange(filter.toBlock, childNitroGenesisBlock),
+ }
+ const logQueries = []
+ if (classicFilter.fromBlock !== classicFilter.toBlock) {
+ logQueries.push(
+ classic.ChildToParentMessageClassic.getChildToParentEvents(
+ childProvider,
+ classicFilter,
+ position,
+ destination,
+ hash,
+ indexInBatch
+ )
+ )
+ }
+
+ const nitroFilter = {
+ fromBlock: inNitroRange(filter.fromBlock, childNitroGenesisBlock),
+ toBlock: inNitroRange(filter.toBlock, childNitroGenesisBlock),
+ }
+ if (nitroFilter.fromBlock !== nitroFilter.toBlock) {
+ logQueries.push(
+ nitro.ChildToParentMessageNitro.getChildToParentEvents(
+ childProvider,
+ nitroFilter,
+ position,
+ destination,
+ hash
+ )
+ )
+ }
+
+ return (await Promise.all(logQueries)).flat(1)
+ }
+}
+
+/**
+ * Provides read-only access for Child-to-Parent messages
+ */
+export class ChildToParentMessageReader extends ChildToParentMessage {
+ private readonly classicReader?: classic.ChildToParentMessageReaderClassic
+ private readonly nitroReader?: nitro.ChildToParentMessageReaderNitro
+
+ constructor(
+ protected readonly parentProvider: Provider,
+ event: ChildToParentTransactionEvent
+ ) {
+ super()
+ if (this.isClassic(event)) {
+ this.classicReader = new classic.ChildToParentMessageReaderClassic(
+ parentProvider,
+ event.batchNumber,
+ event.indexInBatch
+ )
+ } else {
+ this.nitroReader = new nitro.ChildToParentMessageReaderNitro(
+ parentProvider,
+ event
+ )
+ }
+ }
+
+ public async getOutboxProof(
+ childProvider: Provider
+ ): Promise {
+ if (this.nitroReader) {
+ return await this.nitroReader.getOutboxProof(childProvider)
+ } else return await this.classicReader!.tryGetProof(childProvider)
+ }
+
+ /**
+ * Get the status of this message
+ * In order to check if the message has been executed proof info must be provided.
+ * @returns
+ */
+ public async status(
+ childProvider: Provider
+ ): Promise {
+ // can we create a ChildToParentMessage here, we need to - the constructor is what we need
+ if (this.nitroReader) return await this.nitroReader.status(childProvider)
+ else return await this.classicReader!.status(childProvider)
+ }
+
+ /**
+ * Waits until the outbox entry has been created, and will not return until it has been.
+ * WARNING: Outbox entries are only created when the corresponding node is confirmed. Which
+ * can take 1 week+, so waiting here could be a very long operation.
+ * @param retryDelay
+ * @returns outbox entry status (either executed or confirmed but not pending)
+ */
+ public async waitUntilReadyToExecute(
+ childProvider: Provider,
+ retryDelay = 500
+ ): Promise<
+ ChildToParentMessageStatus.EXECUTED | ChildToParentMessageStatus.CONFIRMED
+ > {
+ if (this.nitroReader)
+ return this.nitroReader.waitUntilReadyToExecute(childProvider, retryDelay)
+ else
+ return this.classicReader!.waitUntilOutboxEntryCreated(
+ childProvider,
+ retryDelay
+ )
+ }
+
+ /**
+ * Estimates the Parent block number in which this Child-to-Parent tx will be available for execution.
+ * If the message can or already has been executed, this returns null
+ * @param childProvider
+ * @returns expected Parent block number where the Child-to-Parent message will be executable. Returns null if the message can or already has been executed
+ */
+ public async getFirstExecutableBlock(
+ childProvider: Provider
+ ): Promise {
+ if (this.nitroReader)
+ return this.nitroReader.getFirstExecutableBlock(childProvider)
+ else return this.classicReader!.getFirstExecutableBlock(childProvider)
+ }
+}
+
+/**
+ * Provides read and write access for Child-to-Parent messages
+ */
+export class ChildToParentMessageWriter extends ChildToParentMessageReader {
+ private readonly classicWriter?: classic.ChildToParentMessageWriterClassic
+ private readonly nitroWriter?: nitro.ChildToParentMessageWriterNitro
+
+ /**
+ * Instantiates a new `ChildToParentMessageWriter` object.
+ *
+ * @param {Signer} parentSigner The signer to be used for executing the Child-to-Parent message.
+ * @param {ChildToParentTransactionEvent} event The event containing the data of the Child-to-Parent message.
+ * @param {Provider} [parentProvider] Optional. Used to override the Provider which is attached to `parentSigner` in case you need more control. This will be a required parameter in a future major version update.
+ */
+ constructor(
+ parentSigner: Signer,
+ event: ChildToParentTransactionEvent,
+ parentProvider?: Provider
+ ) {
+ super(parentProvider ?? parentSigner.provider!, event)
+
+ if (this.isClassic(event)) {
+ this.classicWriter = new classic.ChildToParentMessageWriterClassic(
+ parentSigner,
+ event.batchNumber,
+ event.indexInBatch,
+ parentProvider
+ )
+ } else {
+ this.nitroWriter = new nitro.ChildToParentMessageWriterNitro(
+ parentSigner,
+ event,
+ parentProvider
+ )
+ }
+ }
+
+ /**
+ * Executes the ChildToParentMessage on Parent chain.
+ * Will throw an error if the outbox entry has not been created, which happens when the
+ * corresponding assertion is confirmed.
+ * @returns
+ */
+ public async execute(
+ childProvider: Provider,
+ overrides?: Overrides
+ ): Promise {
+ if (this.nitroWriter)
+ return this.nitroWriter.execute(childProvider, overrides)
+ else return await this.classicWriter!.execute(childProvider, overrides)
+ }
+}
diff --git a/src/lib/message/L2ToL1MessageClassic.ts b/src/lib/message/ChildToParentMessageClassic.ts
similarity index 62%
rename from src/lib/message/L2ToL1MessageClassic.ts
rename to src/lib/message/ChildToParentMessageClassic.ts
index 2392511e56..368cba35ca 100644
--- a/src/lib/message/L2ToL1MessageClassic.ts
+++ b/src/lib/message/ChildToParentMessageClassic.ts
@@ -29,7 +29,7 @@ import { ArbSys__factory } from '../abi/factories/ArbSys__factory'
import { Outbox__factory } from '../abi/classic/factories/Outbox__factory'
import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory'
-import { L2ToL1TransactionEvent } from '../abi/ArbSys'
+import { L2ToL1TransactionEvent as ChildToParentTransactionEvent } from '../abi/ArbSys'
import { ContractTransaction, Overrides } from 'ethers'
import { EventFetcher } from '../utils/eventFetcher'
import {
@@ -39,8 +39,8 @@ import {
import { isDefined, wait } from '../utils/lib'
import { ArbSdkError } from '../dataEntities/errors'
import { EventArgs } from '../dataEntities/event'
-import { L2ToL1MessageStatus } from '../dataEntities/message'
-import { getL2Network } from '../dataEntities/networks'
+import { ChildToParentMessageStatus } from '../dataEntities/message'
+import { getArbitrumNetwork } from '../dataEntities/networks'
export interface MessageBatchProofInfo {
/**
@@ -91,14 +91,17 @@ export interface MessageBatchProofInfo {
/**
* Conditional type for Signer or Provider. If T is of type Provider
- * then L2ToL1MessageReaderOrWriter will be of type L2ToL1MessageReader.
- * If T is of type Signer then L2ToL1MessageReaderOrWriter will be of
- * type L2ToL1MessageWriter.
+ * then ChildToParentMessageReaderOrWriter will be of type ChildToParentMessageReader.
+ * If T is of type Signer then ChildToParentMessageReaderOrWriter will be of
+ * type ChildToParentMessageWriter.
*/
-export type L2ToL1MessageReaderOrWriterClassic =
- T extends Provider ? L2ToL1MessageReaderClassic : L2ToL1MessageWriterClassic
+export type ChildToParentMessageReaderOrWriterClassic<
+ T extends SignerOrProvider
+> = T extends Provider
+ ? ChildToParentMessageReaderClassic
+ : ChildToParentMessageWriterClassic
-export class L2ToL1MessageClassic {
+export class ChildToParentMessageClassic {
/**
* The number of the batch this message is part of
*/
@@ -115,50 +118,52 @@ export class L2ToL1MessageClassic {
}
/**
- * Instantiates a new `L2ToL1MessageWriterClassic` or `L2ToL1MessageReaderClassic` object.
+ * Instantiates a new `ChildToParentMessageWriterClassic` or `ChildToParentMessageReaderClassic` object.
*
- * @param {SignerOrProvider} l1SignerOrProvider Signer or provider to be used for executing or reading the L2-to-L1 message.
- * @param {BigNumber} batchNumber The number of the batch containing the L2-to-L1 message.
- * @param {BigNumber} indexInBatch The index of the L2-to-L1 message within the batch.
- * @param {Provider} [l1Provider] Optional. Used to override the Provider which is attached to `l1SignerOrProvider` in case you need more control. This will be a required parameter in a future major version update.
+ * @param {SignerOrProvider} parentSignerOrProvider Signer or provider to be used for executing or reading the Child-to-Parent message.
+ * @param {BigNumber} batchNumber The number of the batch containing the Child-to-Parent message.
+ * @param {BigNumber} indexInBatch The index of the Child-to-Parent message within the batch.
+ * @param {Provider} [parentProvider] Optional. Used to override the Provider which is attached to `parentSignerOrProvider` in case you need more control. This will be a required parameter in a future major version update.
*/
public static fromBatchNumber(
- l1SignerOrProvider: T,
+ parentSignerOrProvider: T,
batchNumber: BigNumber,
indexInBatch: BigNumber,
- l1Provider?: Provider
- ): L2ToL1MessageReaderOrWriterClassic
+ parentProvider?: Provider
+ ): ChildToParentMessageReaderOrWriterClassic
public static fromBatchNumber(
- l1SignerOrProvider: T,
+ parentSignerOrProvider: T,
batchNumber: BigNumber,
indexInBatch: BigNumber,
- l1Provider?: Provider
- ): L2ToL1MessageReaderClassic | L2ToL1MessageWriterClassic {
- return SignerProviderUtils.isSigner(l1SignerOrProvider)
- ? new L2ToL1MessageWriterClassic(
- l1SignerOrProvider,
+ parentProvider?: Provider
+ ): ChildToParentMessageReaderClassic | ChildToParentMessageWriterClassic {
+ return SignerProviderUtils.isSigner(parentSignerOrProvider)
+ ? new ChildToParentMessageWriterClassic(
+ parentSignerOrProvider,
batchNumber,
indexInBatch,
- l1Provider
+ parentProvider
)
- : new L2ToL1MessageReaderClassic(
- l1SignerOrProvider,
+ : new ChildToParentMessageReaderClassic(
+ parentSignerOrProvider,
batchNumber,
indexInBatch
)
}
- public static async getL2ToL1Events(
- l2Provider: Provider,
+ public static async getChildToParentEvents(
+ childProvider: Provider,
filter: { fromBlock: BlockTag; toBlock: BlockTag },
batchNumber?: BigNumber,
destination?: string,
uniqueId?: BigNumber,
indexInBatch?: BigNumber
): Promise<
- (EventArgs & { transactionHash: string })[]
+ (EventArgs & {
+ transactionHash: string
+ })[]
> {
- const eventFetcher = new EventFetcher(l2Provider)
+ const eventFetcher = new EventFetcher(childProvider)
const events = (
await eventFetcher.getEvents(
ArbSys__factory,
@@ -180,11 +185,11 @@ export class L2ToL1MessageClassic {
}
/**
- * Provides read-only access for classic l2-to-l1-messages
+ * Provides read-only access for classic Child-to-Parent-messages
*/
-export class L2ToL1MessageReaderClassic extends L2ToL1MessageClassic {
+export class ChildToParentMessageReaderClassic extends ChildToParentMessageClassic {
constructor(
- protected readonly l1Provider: Provider,
+ protected readonly parentProvider: Provider,
batchNumber: BigNumber,
indexInBatch: BigNumber
) {
@@ -199,18 +204,21 @@ export class L2ToL1MessageReaderClassic extends L2ToL1MessageClassic {
/**
* Classic had 2 outboxes, we need to find the correct one for the provided batch number
- * @param l2Provider
+ * @param childProvider
* @param batchNumber
* @returns
*/
- protected async getOutboxAddress(l2Provider: Provider, batchNumber: number) {
+ protected async getOutboxAddress(
+ childProvider: Provider,
+ batchNumber: number
+ ) {
if (!isDefined(this.outboxAddress)) {
- const l2Network = await getL2Network(l2Provider)
+ const childChain = await getArbitrumNetwork(childProvider)
// find the outbox where the activation batch number of the next outbox
// is greater than the supplied batch
- const outboxes = isDefined(l2Network.ethBridge.classicOutboxes)
- ? Object.entries(l2Network.ethBridge.classicOutboxes)
+ const outboxes = isDefined(childChain.ethBridge.classicOutboxes)
+ ? Object.entries(childChain.ethBridge.classicOutboxes)
: []
const res = outboxes
@@ -233,24 +241,24 @@ export class L2ToL1MessageReaderClassic extends L2ToL1MessageClassic {
return this.outboxAddress
}
- private async outboxEntryExists(l2Provider: Provider) {
+ private async outboxEntryExists(childProvider: Provider) {
const outboxAddress = await this.getOutboxAddress(
- l2Provider,
+ childProvider,
this.batchNumber.toNumber()
)
- const outbox = Outbox__factory.connect(outboxAddress, this.l1Provider)
+ const outbox = Outbox__factory.connect(outboxAddress, this.parentProvider)
return await outbox.outboxEntryExists(this.batchNumber)
}
public static async tryGetProof(
- l2Provider: Provider,
+ childProvider: Provider,
batchNumber: BigNumber,
indexInBatch: BigNumber
): Promise {
const nodeInterface = NodeInterface__factory.connect(
NODE_INTERFACE_ADDRESS,
- l2Provider
+ childProvider
)
try {
return await nodeInterface.legacyLookupMessageBatchProof(
@@ -271,15 +279,15 @@ export class L2ToL1MessageReaderClassic extends L2ToL1MessageClassic {
/**
* Get the execution proof for this message. Returns null if the batch does not exist yet.
- * @param l2Provider
+ * @param childProvider
* @returns
*/
public async tryGetProof(
- l2Provider: Provider
+ childProvider: Provider
): Promise {
if (!isDefined(this.proof)) {
- this.proof = await L2ToL1MessageReaderClassic.tryGetProof(
- l2Provider,
+ this.proof = await ChildToParentMessageReaderClassic.tryGetProof(
+ childProvider,
this.batchNumber,
this.indexInBatch
)
@@ -290,16 +298,16 @@ export class L2ToL1MessageReaderClassic extends L2ToL1MessageClassic {
/**
* Check if given outbox message has already been executed
*/
- public async hasExecuted(l2Provider: Provider): Promise {
- const proofInfo = await this.tryGetProof(l2Provider)
+ public async hasExecuted(childProvider: Provider): Promise {
+ const proofInfo = await this.tryGetProof(childProvider)
if (!isDefined(proofInfo)) return false
const outboxAddress = await this.getOutboxAddress(
- l2Provider,
+ childProvider,
this.batchNumber.toNumber()
)
- const outbox = Outbox__factory.connect(outboxAddress, this.l1Provider)
+ const outbox = Outbox__factory.connect(outboxAddress, this.parentProvider)
try {
await outbox.callStatic.executeTransaction(
this.batchNumber,
@@ -325,22 +333,24 @@ export class L2ToL1MessageReaderClassic extends L2ToL1MessageClassic {
/**
* Get the status of this message
* In order to check if the message has been executed proof info must be provided.
- * @param proofInfo
+ * @param childProvider
* @returns
*/
- public async status(l2Provider: Provider): Promise {
+ public async status(
+ childProvider: Provider
+ ): Promise {
try {
- const messageExecuted = await this.hasExecuted(l2Provider)
+ const messageExecuted = await this.hasExecuted(childProvider)
if (messageExecuted) {
- return L2ToL1MessageStatus.EXECUTED
+ return ChildToParentMessageStatus.EXECUTED
}
- const outboxEntryExists = await this.outboxEntryExists(l2Provider)
+ const outboxEntryExists = await this.outboxEntryExists(childProvider)
return outboxEntryExists
- ? L2ToL1MessageStatus.CONFIRMED
- : L2ToL1MessageStatus.UNCONFIRMED
+ ? ChildToParentMessageStatus.CONFIRMED
+ : ChildToParentMessageStatus.UNCONFIRMED
} catch (e) {
- return L2ToL1MessageStatus.UNCONFIRMED
+ return ChildToParentMessageStatus.UNCONFIRMED
}
}
@@ -352,82 +362,84 @@ export class L2ToL1MessageReaderClassic extends L2ToL1MessageClassic {
* @returns outbox entry status (either executed or confirmed but not pending)
*/
public async waitUntilOutboxEntryCreated(
- l2Provider: Provider,
+ childProvider: Provider,
retryDelay = 500
- ): Promise {
- const exists = await this.outboxEntryExists(l2Provider)
+ ): Promise<
+ ChildToParentMessageStatus.EXECUTED | ChildToParentMessageStatus.CONFIRMED
+ > {
+ const exists = await this.outboxEntryExists(childProvider)
if (exists) {
- return (await this.hasExecuted(l2Provider))
- ? L2ToL1MessageStatus.EXECUTED
- : L2ToL1MessageStatus.CONFIRMED
+ return (await this.hasExecuted(childProvider))
+ ? ChildToParentMessageStatus.EXECUTED
+ : ChildToParentMessageStatus.CONFIRMED
} else {
await wait(retryDelay)
- return await this.waitUntilOutboxEntryCreated(l2Provider, retryDelay)
+ return await this.waitUntilOutboxEntryCreated(childProvider, retryDelay)
}
}
/**
- * Estimates the L1 block number in which this L2 to L1 tx will be available for execution
- * @param l2Provider
- * @returns Always returns null for classic l2toL1 messages since they can be executed in any block now.
+ * Estimates the Parent Chain block number in which this Child-to-Parent tx will be available for execution
+ * @param childProvider
+ * @returns Always returns null for classic chainToParentChain messages since they can be executed in any block now.
*/
public async getFirstExecutableBlock(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- l2Provider: Provider
+ childProvider: Provider
): Promise {
return null
}
}
/**
- * Provides read and write access for classic l2-to-l1-messages
+ * Provides read and write access for classic Child-to-Parent-messages
*/
-export class L2ToL1MessageWriterClassic extends L2ToL1MessageReaderClassic {
+export class ChildToParentMessageWriterClassic extends ChildToParentMessageReaderClassic {
/**
- * Instantiates a new `L2ToL1MessageWriterClassic` object.
+ * Instantiates a new `ChildToParentMessageWriterClassic` object.
*
- * @param {Signer} l1Signer The signer to be used for executing the L2-to-L1 message.
- * @param {BigNumber} batchNumber The number of the batch containing the L2-to-L1 message.
- * @param {BigNumber} indexInBatch The index of the L2-to-L1 message within the batch.
- * @param {Provider} [l1Provider] Optional. Used to override the Provider which is attached to `l1Signer` in case you need more control. This will be a required parameter in a future major version update.
+ * @param {Signer} parentSigner The signer to be used for executing the Child-to-Parent message.
+ * @param {BigNumber} batchNumber The number of the batch containing the Child-to-Parent message.
+ * @param {BigNumber} indexInBatch The index of the Child-to-Parent message within the batch.
+ * @param {Provider} [parentProvider] Optional. Used to override the Provider which is attached to `parentSigner` in case you need more control. This will be a required parameter in a future major version update.
*/
constructor(
- private readonly l1Signer: Signer,
+ private readonly parentSigner: Signer,
batchNumber: BigNumber,
indexInBatch: BigNumber,
- l1Provider?: Provider
+ parentProvider?: Provider
) {
- super(l1Provider ?? l1Signer.provider!, batchNumber, indexInBatch)
+ super(parentProvider ?? parentSigner.provider!, batchNumber, indexInBatch)
}
/**
- * Executes the L2ToL1Message on L1.
+ * Executes the ChildToParentMessage on Parent Chain.
* Will throw an error if the outbox entry has not been created, which happens when the
* corresponding assertion is confirmed.
* @returns
*/
public async execute(
- l2Provider: Provider,
+ childProvider: Provider,
overrides?: Overrides
): Promise {
- const status = await this.status(l2Provider)
- if (status !== L2ToL1MessageStatus.CONFIRMED) {
+ const status = await this.status(childProvider)
+ if (status !== ChildToParentMessageStatus.CONFIRMED) {
throw new ArbSdkError(
- `Cannot execute message. Status is: ${status} but must be ${L2ToL1MessageStatus.CONFIRMED}.`
+ `Cannot execute message. Status is: ${status} but must be ${ChildToParentMessageStatus.CONFIRMED}.`
)
}
- const proofInfo = await this.tryGetProof(l2Provider)
+ const proofInfo = await this.tryGetProof(childProvider)
if (!isDefined(proofInfo)) {
throw new ArbSdkError(
`Unexpected missing proof: ${this.batchNumber.toString()} ${this.indexInBatch.toString()}}`
)
}
const outboxAddress = await this.getOutboxAddress(
- l2Provider,
+ childProvider,
this.batchNumber.toNumber()
)
- const outbox = Outbox__factory.connect(outboxAddress, this.l1Signer)
+ const outbox = Outbox__factory.connect(outboxAddress, this.parentSigner)
// We can predict and print number of missing blocks
// if not challenged
return await outbox.functions.executeTransaction(
diff --git a/src/lib/message/L2ToL1MessageNitro.ts b/src/lib/message/ChildToParentMessageNitro.ts
similarity index 63%
rename from src/lib/message/L2ToL1MessageNitro.ts
rename to src/lib/message/ChildToParentMessageNitro.ts
index 77d8d650a9..e9f25f155b 100644
--- a/src/lib/message/L2ToL1MessageNitro.ts
+++ b/src/lib/message/ChildToParentMessageNitro.ts
@@ -32,7 +32,7 @@ import { BoldRollupUserLogic__factory } from '../abi-bold/factories/BoldRollupUs
import { Outbox__factory } from '../abi/factories/Outbox__factory'
import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory'
-import { L2ToL1TxEvent } from '../abi/ArbSys'
+import { L2ToL1TxEvent as ChildToParentTxEvent } from '../abi/ArbSys'
import { ContractTransaction, Overrides } from 'ethers'
import { Mutex } from 'async-mutex'
import { EventFetcher, FetchedEvent } from '../utils/eventFetcher'
@@ -42,7 +42,7 @@ import {
SignerOrProvider,
} from '../dataEntities/signerOrProvider'
import { getBlockRangesForL1Block, isArbitrumChain, wait } from '../utils/lib'
-import { L2Network, getL2Network } from '../dataEntities/networks'
+import { ArbitrumNetwork, getArbitrumNetwork } from '../dataEntities/networks'
import { NodeCreatedEvent, RollupUserLogic } from '../abi/RollupUserLogic'
import {
AssertionCreatedEvent,
@@ -52,117 +52,128 @@ import { ArbitrumProvider } from '../utils/arbProvider'
import { ArbBlock } from '../dataEntities/rpc'
import { JsonRpcProvider } from '@ethersproject/providers'
import { EventArgs } from '../dataEntities/event'
-import { L2ToL1MessageStatus } from '../dataEntities/message'
+import { ChildToParentMessageStatus } from '../dataEntities/message'
import { Bridge__factory } from '../abi/factories/Bridge__factory'
/**
* Conditional type for Signer or Provider. If T is of type Provider
- * then L2ToL1MessageReaderOrWriter will be of type L2ToL1MessageReader.
- * If T is of type Signer then L2ToL1MessageReaderOrWriter will be of
- * type L2ToL1MessageWriter.
+ * then ChildToParentMessageReaderOrWriter will be of type ChildToParentMessageReader.
+ * If T is of type Signer then ChildToParentMessageReaderOrWriter will be of
+ * type ChildToParentMessageWriter.
*/
-export type L2ToL1MessageReaderOrWriterNitro =
- T extends Provider ? L2ToL1MessageReaderNitro : L2ToL1MessageWriterNitro
+export type ChildToParentMessageReaderOrWriterNitro<
+ T extends SignerOrProvider
+> = T extends Provider
+ ? ChildToParentMessageReaderNitro
+ : ChildToParentMessageWriterNitro
-// expected number of L1 blocks that it takes for an L2 tx to be included in a L1 assertion
+// expected number of parent chain blocks that it takes for a Child chain tx to be included in a parent chain assertion
const ASSERTION_CREATED_PADDING = 50
-// expected number of L1 blocks that it takes for a validator to confirm an L1 block after the assertion deadline is passed
+// expected number of parent blocks that it takes for a validator to confirm a parent block after the assertion deadline is passed
const ASSERTION_CONFIRMED_PADDING = 20
-const l2BlockRangeCache: { [key in string]: (number | undefined)[] } = {}
+const childBlockRangeCache: { [key in string]: (number | undefined)[] } = {}
const mutex = new Mutex()
-function getL2BlockRangeCacheKey({
- l2ChainId,
+function getChildBlockRangeCacheKey({
+ childChainId,
l1BlockNumber,
}: {
- l2ChainId: number
+ childChainId: number
l1BlockNumber: number
}) {
- return `${l2ChainId}-${l1BlockNumber}`
+ return `${childChainId}-${l1BlockNumber}`
}
-function setL2BlockRangeCache(key: string, value: (number | undefined)[]) {
- l2BlockRangeCache[key] = value
+function setChildBlockRangeCache(key: string, value: (number | undefined)[]) {
+ childBlockRangeCache[key] = value
}
async function getBlockRangesForL1BlockWithCache({
- l1Provider,
- l2Provider,
+ parentProvider,
+ childProvider,
forL1Block,
}: {
- l1Provider: JsonRpcProvider
- l2Provider: JsonRpcProvider
+ parentProvider: JsonRpcProvider
+ childProvider: JsonRpcProvider
forL1Block: number
}) {
- const l2ChainId = (await l2Provider.getNetwork()).chainId
- const key = getL2BlockRangeCacheKey({
- l2ChainId,
+ const childChainId = (await childProvider.getNetwork()).chainId
+ const key = getChildBlockRangeCacheKey({
+ childChainId,
l1BlockNumber: forL1Block,
})
- if (l2BlockRangeCache[key]) {
- return l2BlockRangeCache[key]
+ if (childBlockRangeCache[key]) {
+ return childBlockRangeCache[key]
}
// implements a lock that only fetches cache once
const release = await mutex.acquire()
// if cache has been acquired while awaiting the lock
- if (l2BlockRangeCache[key]) {
+ if (childBlockRangeCache[key]) {
release()
- return l2BlockRangeCache[key]
+ return childBlockRangeCache[key]
}
try {
- const l2BlockRange = await getBlockRangesForL1Block({
+ const childBlockRange = await getBlockRangesForL1Block({
forL1Block,
- provider: l1Provider,
+ arbitrumProvider: parentProvider,
})
- setL2BlockRangeCache(key, l2BlockRange)
+ setChildBlockRangeCache(key, childBlockRange)
} finally {
release()
}
- return l2BlockRangeCache[key]
+ return childBlockRangeCache[key]
}
/**
- * Base functionality for nitro L2->L1 messages
+ * Base functionality for nitro Child->Parent messages
*/
-export class L2ToL1MessageNitro {
- protected constructor(public readonly event: EventArgs) {}
+export class ChildToParentMessageNitro {
+ protected constructor(
+ public readonly event: EventArgs
+ ) {}
/**
- * Instantiates a new `L2ToL1MessageWriterNitro` or `L2ToL1MessageReaderNitro` object.
+ * Instantiates a new `ChildToParentMessageWriterNitro` or `ChildToParentMessageReaderNitro` object.
*
- * @param {SignerOrProvider} l1SignerOrProvider Signer or provider to be used for executing or reading the L2-to-L1 message.
- * @param {EventArgs} event The event containing the data of the L2-to-L1 message.
- * @param {Provider} [l1Provider] Optional. Used to override the Provider which is attached to `l1SignerOrProvider` in case you need more control. This will be a required parameter in a future major version update.
+ * @param {SignerOrProvider} parentSignerOrProvider Signer or provider to be used for executing or reading the Child-to-Parent message.
+ * @param {EventArgs} event The event containing the data of the Child-to-Parent message.
+ * @param {Provider} [parentProvider] Optional. Used to override the Provider which is attached to `parentSignerOrProvider` in case you need more control. This will be a required parameter in a future major version update.
*/
public static fromEvent(
- l1SignerOrProvider: T,
- event: EventArgs,
- l1Provider?: Provider
- ): L2ToL1MessageReaderOrWriterNitro
+ parentSignerOrProvider: T,
+ event: EventArgs,
+ parentProvider?: Provider
+ ): ChildToParentMessageReaderOrWriterNitro
public static fromEvent(
- l1SignerOrProvider: T,
- event: EventArgs,
- l1Provider?: Provider
- ): L2ToL1MessageReaderNitro | L2ToL1MessageWriterNitro {
- return SignerProviderUtils.isSigner(l1SignerOrProvider)
- ? new L2ToL1MessageWriterNitro(l1SignerOrProvider, event, l1Provider)
- : new L2ToL1MessageReaderNitro(l1SignerOrProvider, event)
+ parentSignerOrProvider: T,
+ event: EventArgs,
+ parentProvider?: Provider
+ ): ChildToParentMessageReaderNitro | ChildToParentMessageWriterNitro {
+ return SignerProviderUtils.isSigner(parentSignerOrProvider)
+ ? new ChildToParentMessageWriterNitro(
+ parentSignerOrProvider,
+ event,
+ parentProvider
+ )
+ : new ChildToParentMessageReaderNitro(parentSignerOrProvider, event)
}
- public static async getL2ToL1Events(
- l2Provider: Provider,
+ public static async getChildToParentEvents(
+ childProvider: Provider,
filter: { fromBlock: BlockTag; toBlock: BlockTag },
position?: BigNumber,
destination?: string,
hash?: BigNumber
- ): Promise<(EventArgs & { transactionHash: string })[]> {
- const eventFetcher = new EventFetcher(l2Provider)
+ ): Promise<
+ (EventArgs & { transactionHash: string })[]
+ > {
+ const eventFetcher = new EventFetcher(childProvider)
return (
await eventFetcher.getEvents(
ArbSys__factory,
@@ -174,9 +185,9 @@ export class L2ToL1MessageNitro {
}
/**
- * Provides read-only access nitro for l2-to-l1-messages
+ * Provides read-only access nitro for child-to-parent-messages
*/
-export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
+export class ChildToParentMessageReaderNitro extends ChildToParentMessageNitro {
protected sendRootHash?: string
protected sendRootSize?: BigNumber
protected sendRootConfirmed?: boolean
@@ -184,19 +195,19 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
protected l1BatchNumber?: number
constructor(
- protected readonly l1Provider: Provider,
- event: EventArgs
+ protected readonly parentProvider: Provider,
+ event: EventArgs
) {
super(event)
}
- public async getOutboxProof(l2Provider: Provider) {
- const { sendRootSize } = await this.getSendProps(l2Provider)
+ public async getOutboxProof(childProvider: Provider) {
+ const { sendRootSize } = await this.getSendProps(childProvider)
if (!sendRootSize)
throw new ArbSdkError('Assertion not yet created, cannot get proof.')
const nodeInterface = NodeInterface__factory.connect(
NODE_INTERFACE_ADDRESS,
- l2Provider
+ childProvider
)
const outboxProofParams =
@@ -211,11 +222,11 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
/**
* Check if this message has already been executed in the Outbox
*/
- protected async hasExecuted(l2Provider: Provider): Promise {
- const l2Network = await getL2Network(l2Provider)
+ protected async hasExecuted(childProvider: Provider): Promise {
+ const childChain = await getArbitrumNetwork(childProvider)
const outbox = Outbox__factory.connect(
- l2Network.ethBridge.outbox,
- this.l1Provider
+ childChain.ethBridge.outbox,
+ this.parentProvider
)
return outbox.callStatic.isSpent(this.event.position)
@@ -226,12 +237,14 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
* In order to check if the message has been executed proof info must be provided.
* @returns
*/
- public async status(l2Provider: Provider): Promise {
- const { sendRootConfirmed } = await this.getSendProps(l2Provider)
- if (!sendRootConfirmed) return L2ToL1MessageStatus.UNCONFIRMED
- return (await this.hasExecuted(l2Provider))
- ? L2ToL1MessageStatus.EXECUTED
- : L2ToL1MessageStatus.CONFIRMED
+ public async status(
+ childProvider: Provider
+ ): Promise {
+ const { sendRootConfirmed } = await this.getSendProps(childProvider)
+ if (!sendRootConfirmed) return ChildToParentMessageStatus.UNCONFIRMED
+ return (await this.hasExecuted(childProvider))
+ ? ChildToParentMessageStatus.EXECUTED
+ : ChildToParentMessageStatus.CONFIRMED
}
private parseNodeCreatedAssertion(event: FetchedEvent) {
@@ -264,10 +277,10 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
}
private async getBlockFromAssertionLog(
- l2Provider: JsonRpcProvider,
+ childProvider: JsonRpcProvider,
log: FetchedEvent | FetchedEvent
) {
- const arbitrumProvider = new ArbitrumProvider(l2Provider)
+ const arbitrumProvider = new ArbitrumProvider(childProvider)
if (!log) {
console.warn('No AssertionCreated events found, defaulting to block 0')
@@ -278,20 +291,20 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
? this.parseAssertionCreatedEvent(log)
: this.parseNodeCreatedAssertion(log)
- const l2Block = await arbitrumProvider.getBlock(
+ const childBlock = await arbitrumProvider.getBlock(
parsedLog.afterState.blockHash
)
- if (!l2Block) {
+ if (!childBlock) {
throw new ArbSdkError(
`Block not found. ${parsedLog.afterState.blockHash}`
)
}
- if (l2Block.sendRoot !== parsedLog.afterState.sendRoot) {
+ if (childBlock.sendRoot !== parsedLog.afterState.sendRoot) {
throw new ArbSdkError(
- `L2 block send root doesn't match parsed log. ${l2Block.sendRoot} ${parsedLog.afterState.sendRoot}`
+ `Child chain block send root doesn't match parsed log. ${childBlock.sendRoot} ${parsedLog.afterState.sendRoot}`
)
}
- return l2Block
+ return childBlock
}
private isBoldRollupUserLogic(
@@ -303,7 +316,7 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
private async getBlockFromAssertionId(
rollup: RollupUserLogic | BoldRollupUserLogic,
assertionId: BigNumber | string,
- l2Provider: Provider
+ childProvider: Provider
): Promise {
const createdAtBlock: BigNumber = this.isBoldRollupUserLogic(rollup)
? (
@@ -316,11 +329,11 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
let createdToBlock = createdAtBlock
// If L1 is Arbitrum, then L2 is an Orbit chain.
- if (await isArbitrumChain(this.l1Provider)) {
+ if (await isArbitrumChain(this.parentProvider)) {
try {
const nodeInterface = NodeInterface__factory.connect(
NODE_INTERFACE_ADDRESS,
- this.l1Provider
+ this.parentProvider
)
const l2BlockRangeFromNode = await nodeInterface.l2BlockRangeForL1(
@@ -333,8 +346,8 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
// defaults to binary search
try {
const l2BlockRange = await getBlockRangesForL1BlockWithCache({
- l1Provider: this.l1Provider as JsonRpcProvider,
- l2Provider: l2Provider as JsonRpcProvider,
+ parentProvider: this.parentProvider as JsonRpcProvider,
+ childProvider: childProvider as JsonRpcProvider,
forL1Block: createdAtBlock.toNumber(),
})
const startBlock = l2BlockRange[0]
@@ -384,18 +397,18 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
`Unexpected number of AssertionCreated events. Expected 0 or 1, got ${logs.length}.`
)
return await this.getBlockFromAssertionLog(
- l2Provider as JsonRpcProvider,
+ childProvider as JsonRpcProvider,
logs[0]
)
}
- protected async getBatchNumber(l2Provider: Provider) {
+ protected async getBatchNumber(childProvider: Provider) {
if (this.l1BatchNumber == undefined) {
// findBatchContainingBlock errors if block number does not exist
try {
const nodeInterface = NodeInterface__factory.connect(
NODE_INTERFACE_ADDRESS,
- l2Provider
+ childProvider
)
const res = await nodeInterface.findBatchContainingBlock(
this.event.arbBlockNum
@@ -409,23 +422,25 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
return this.l1BatchNumber
}
- protected async getSendProps(l2Provider: Provider) {
+ protected async getSendProps(childProvider: Provider) {
if (!this.sendRootConfirmed) {
- const l2Network = await getL2Network(l2Provider)
- const rollup = await this.getRollupAndUpdateNetwork(l2Network)
+ const childChain = await getArbitrumNetwork(childProvider)
+ const rollup = await this.getRollupAndUpdateNetwork(childChain)
const latestConfirmedAssertionId =
await rollup.callStatic.latestConfirmed()
- const l2BlockConfirmed = await this.getBlockFromAssertionId(
+ const childBlockConfirmed = await this.getBlockFromAssertionId(
rollup,
latestConfirmedAssertionId,
- l2Provider
+ childProvider
)
- const sendRootSizeConfirmed = BigNumber.from(l2BlockConfirmed.sendCount)
+ const sendRootSizeConfirmed = BigNumber.from(
+ childBlockConfirmed.sendCount
+ )
if (sendRootSizeConfirmed.gt(this.event.position)) {
this.sendRootSize = sendRootSizeConfirmed
- this.sendRootHash = l2BlockConfirmed.sendRoot
+ this.sendRootHash = childBlockConfirmed.sendRoot
this.sendRootConfirmed = true
} else {
let latestCreatedAssertionId: BigNumber | string
@@ -461,16 +476,16 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
if (!latestEquals) {
// In rare case latestNodeNum can be equal to latestConfirmedNodeNum
// eg immediately after an upgrade, or at genesis, or on a chain where confirmation time = 0 like AnyTrust may have
- const l2Block = await this.getBlockFromAssertionId(
+ const childBlock = await this.getBlockFromAssertionId(
rollup,
latestCreatedAssertionId,
- l2Provider
+ childProvider
)
- const sendRootSize = BigNumber.from(l2Block.sendCount)
+ const sendRootSize = BigNumber.from(childBlock.sendCount)
if (sendRootSize.gt(this.event.position)) {
this.sendRootSize = sendRootSize
- this.sendRootHash = l2Block.sendRoot
+ this.sendRootHash = childBlock.sendRoot
}
}
}
@@ -490,40 +505,42 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
* @returns outbox entry status (either executed or confirmed but not pending)
*/
public async waitUntilReadyToExecute(
- l2Provider: Provider,
+ childProvider: Provider,
retryDelay = 500
- ): Promise {
- const status = await this.status(l2Provider)
+ ): Promise<
+ ChildToParentMessageStatus.EXECUTED | ChildToParentMessageStatus.CONFIRMED
+ > {
+ const status = await this.status(childProvider)
if (
- status === L2ToL1MessageStatus.CONFIRMED ||
- status === L2ToL1MessageStatus.EXECUTED
+ status === ChildToParentMessageStatus.CONFIRMED ||
+ status === ChildToParentMessageStatus.EXECUTED
) {
return status
} else {
await wait(retryDelay)
- return await this.waitUntilReadyToExecute(l2Provider, retryDelay)
+ return await this.waitUntilReadyToExecute(childProvider, retryDelay)
}
}
/**
* Check whether the provided network has a BoLD rollup
- * @param l2Network
- * @param l1Provider
+ * @param arbitrumNetwork
+ * @param parentProvider
* @returns
*/
private async isBold(
- l2Network: L2Network,
- l1Provider: Provider
+ arbitrumNetwork: ArbitrumNetwork,
+ parentProvider: Provider
): Promise {
const bridge = Bridge__factory.connect(
- l2Network.ethBridge.bridge,
- l1Provider
+ arbitrumNetwork.ethBridge.bridge,
+ parentProvider
)
const remoteRollupAddr = await bridge.rollup()
const rollup = RollupUserLogic__factory.connect(
remoteRollupAddr,
- l1Provider
+ parentProvider
)
try {
// bold rollup does not have an extraChallengeTimeBlocks function
@@ -544,55 +561,58 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
/**
* If the local network is not currently bold, checks if the remote network is bold
* and if so updates the local network with a new rollup address
- * @param l2Network
+ * @param arbitrumNetwork
* @returns The rollup contract, bold or legacy
*/
- private async getRollupAndUpdateNetwork(l2Network: L2Network) {
- if (!l2Network.isBold) {
- const boldRollupAddr = await this.isBold(l2Network, this.l1Provider)
+ private async getRollupAndUpdateNetwork(arbitrumNetwork: ArbitrumNetwork) {
+ if (!arbitrumNetwork.isBold) {
+ const boldRollupAddr = await this.isBold(
+ arbitrumNetwork,
+ this.parentProvider
+ )
if (boldRollupAddr) {
- l2Network.isBold = true
- l2Network.ethBridge.rollup = boldRollupAddr
+ arbitrumNetwork.isBold = true
+ arbitrumNetwork.ethBridge.rollup = boldRollupAddr
}
}
- return l2Network.isBold
+ return arbitrumNetwork.isBold
? BoldRollupUserLogic__factory.connect(
- l2Network.ethBridge.rollup,
- this.l1Provider
+ arbitrumNetwork.ethBridge.rollup,
+ this.parentProvider
)
: RollupUserLogic__factory.connect(
- l2Network.ethBridge.rollup,
- this.l1Provider
+ arbitrumNetwork.ethBridge.rollup,
+ this.parentProvider
)
}
/**
* Estimates the L1 block number in which this L2 to L1 tx will be available for execution.
* If the message can or already has been executed, this returns null
- * @param l2Provider
- * @returns expected L1 block number where the L2 to L1 message will be executable. Returns null if the message can be or already has been executed
+ * @param childProvider
+ * @returns expected parent chain block number where the child chain to parent chain message will be executable. Returns null if the message can be or already has been executed
*/
public async getFirstExecutableBlock(
- l2Provider: Provider
+ childProvider: Provider
): Promise {
- const l2Network = await getL2Network(l2Provider)
- const rollup = await this.getRollupAndUpdateNetwork(l2Network)
+ const arbitrumNetwork = await getArbitrumNetwork(childProvider)
+ const rollup = await this.getRollupAndUpdateNetwork(arbitrumNetwork)
- const status = await this.status(l2Provider)
- if (status === L2ToL1MessageStatus.EXECUTED) return null
- if (status === L2ToL1MessageStatus.CONFIRMED) return null
+ const status = await this.status(childProvider)
+ if (status === ChildToParentMessageStatus.EXECUTED) return null
+ if (status === ChildToParentMessageStatus.CONFIRMED) return null
// consistency check in case we change the enum in the future
- if (status !== L2ToL1MessageStatus.UNCONFIRMED)
- throw new ArbSdkError('L2ToL1Msg expected to be unconfirmed')
+ if (status !== ChildToParentMessageStatus.UNCONFIRMED)
+ throw new ArbSdkError('ChildToParentMsg expected to be unconfirmed')
- const latestBlock = await this.l1Provider.getBlockNumber()
- const eventFetcher = new EventFetcher(this.l1Provider)
+ const latestBlock = await this.parentProvider.getBlockNumber()
+ const eventFetcher = new EventFetcher(this.parentProvider)
let logs:
| FetchedEvent[]
| FetchedEvent[]
- if (l2Network.isBold) {
+ if (arbitrumNetwork.isBold) {
logs = (
await eventFetcher.getEvents(
BoldRollupUserLogic__factory,
@@ -600,7 +620,7 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
{
fromBlock: Math.max(
latestBlock -
- BigNumber.from(l2Network.confirmPeriodBlocks)
+ BigNumber.from(arbitrumNetwork.confirmPeriodBlocks)
.add(ASSERTION_CONFIRMED_PADDING)
.toNumber(),
0
@@ -618,7 +638,7 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
{
fromBlock: Math.max(
latestBlock -
- BigNumber.from(l2Network.confirmPeriodBlocks)
+ BigNumber.from(arbitrumNetwork.confirmPeriodBlocks)
.add(ASSERTION_CONFIRMED_PADDING)
.toNumber(),
0
@@ -630,21 +650,21 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
).sort((a, b) => a.event.nodeNum.toNumber() - b.event.nodeNum.toNumber())
}
- const lastL2Block =
+ const lastChildBlock =
logs.length === 0
? undefined
: await this.getBlockFromAssertionLog(
- l2Provider as JsonRpcProvider,
+ childProvider as JsonRpcProvider,
logs[logs.length - 1]
)
- const lastSendCount = lastL2Block
- ? BigNumber.from(lastL2Block.sendCount)
+ const lastSendCount = lastChildBlock
+ ? BigNumber.from(lastChildBlock.sendCount)
: BigNumber.from(0)
- // here we assume the L2 to L1 tx is actually valid, so the user needs to wait the max time
- // since there isn't a pending asssertion that includes this message yet
+ // here we assume the child-to-parent tx is actually valid, so the user needs to wait the max time
+ // since there isn't a pending assertion that includes this message yet
if (lastSendCount.lte(this.event.position))
- return BigNumber.from(l2Network.confirmPeriodBlocks)
+ return BigNumber.from(arbitrumNetwork.confirmPeriodBlocks)
.add(ASSERTION_CREATED_PADDING)
.add(ASSERTION_CONFIRMED_PADDING)
.add(latestBlock)
@@ -657,11 +677,11 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
while (left <= right) {
const mid = Math.floor((left + right) / 2)
const log = logs[mid]
- const l2Block = await this.getBlockFromAssertionLog(
- l2Provider as JsonRpcProvider,
+ const childBlock = await this.getBlockFromAssertionLog(
+ childProvider as JsonRpcProvider,
log
)
- const sendCount = BigNumber.from(l2Block.sendCount)
+ const sendCount = BigNumber.from(childBlock.sendCount)
if (sendCount.gt(this.event.position)) {
foundLog = log
right = mid - 1
@@ -670,14 +690,14 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
}
}
- if (l2Network.isBold) {
+ if (arbitrumNetwork.isBold) {
const assertionHash = (foundLog as FetchedEvent)
.event.assertionHash
const assertion = await (rollup as BoldRollupUserLogic).getAssertion(
assertionHash
)
return assertion.createdAtBlock
- .add(l2Network.confirmPeriodBlocks)
+ .add(arbitrumNetwork.confirmPeriodBlocks)
.add(ASSERTION_CONFIRMED_PADDING)
} else {
const earliestNodeWithExit = (foundLog as FetchedEvent)
@@ -691,45 +711,45 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro {
}
/**
- * Provides read and write access for nitro l2-to-l1-messages
+ * Provides read and write access for nitro child-to-Parent-messages
*/
-export class L2ToL1MessageWriterNitro extends L2ToL1MessageReaderNitro {
+export class ChildToParentMessageWriterNitro extends ChildToParentMessageReaderNitro {
/**
- * Instantiates a new `L2ToL1MessageWriterNitro` object.
+ * Instantiates a new `ChildToParentMessageWriterNitro` object.
*
- * @param {Signer} l1Signer The signer to be used for executing the L2-to-L1 message.
- * @param {EventArgs} event The event containing the data of the L2-to-L1 message.
- * @param {Provider} [l1Provider] Optional. Used to override the Provider which is attached to `l1Signer` in case you need more control. This will be a required parameter in a future major version update.
+ * @param {Signer} parentSigner The signer to be used for executing the Child-to-Parent message.
+ * @param {EventArgs} event The event containing the data of the Child-to-Parent message.
+ * @param {Provider} [parentProvider] Optional. Used to override the Provider which is attached to `parentSigner` in case you need more control. This will be a required parameter in a future major version update.
*/
constructor(
- private readonly l1Signer: Signer,
- event: EventArgs,
- l1Provider?: Provider
+ private readonly parentSigner: Signer,
+ event: EventArgs,
+ parentProvider?: Provider
) {
- super(l1Provider ?? l1Signer.provider!, event)
+ super(parentProvider ?? parentSigner.provider!, event)
}
/**
- * Executes the L2ToL1Message on L1.
+ * Executes the ChildToParentMessage on Parent Chain.
* Will throw an error if the outbox entry has not been created, which happens when the
* corresponding assertion is confirmed.
* @returns
*/
public async execute(
- l2Provider: Provider,
+ childProvider: Provider,
overrides?: Overrides
): Promise {
- const status = await this.status(l2Provider)
- if (status !== L2ToL1MessageStatus.CONFIRMED) {
+ const status = await this.status(childProvider)
+ if (status !== ChildToParentMessageStatus.CONFIRMED) {
throw new ArbSdkError(
- `Cannot execute message. Status is: ${status} but must be ${L2ToL1MessageStatus.CONFIRMED}.`
+ `Cannot execute message. Status is: ${status} but must be ${ChildToParentMessageStatus.CONFIRMED}.`
)
}
- const proof = await this.getOutboxProof(l2Provider)
- const l2Network = await getL2Network(l2Provider)
+ const proof = await this.getOutboxProof(childProvider)
+ const childChain = await getArbitrumNetwork(childProvider)
const outbox = Outbox__factory.connect(
- l2Network.ethBridge.outbox,
- this.l1Signer
+ childChain.ethBridge.outbox,
+ this.parentSigner
)
return await outbox.executeTransaction(
diff --git a/src/lib/message/L2Transaction.ts b/src/lib/message/ChildTransaction.ts
similarity index 72%
rename from src/lib/message/L2Transaction.ts
rename to src/lib/message/ChildTransaction.ts
index 51ac0fa7b2..7c86ba2e75 100644
--- a/src/lib/message/L2Transaction.ts
+++ b/src/lib/message/ChildTransaction.ts
@@ -25,12 +25,12 @@ import {
SignerOrProvider,
} from '../dataEntities/signerOrProvider'
import {
- L2ToL1MessageReader,
- L2ToL1MessageReaderOrWriter,
- L2ToL1Message,
- L2ToL1MessageWriter,
- L2ToL1TransactionEvent,
-} from './L2ToL1Message'
+ ChildToParentMessageReader,
+ ChildToParentMessageReaderOrWriter,
+ ChildToParentMessage,
+ ChildToParentMessageWriter,
+ ChildToParentTransactionEvent,
+} from './ChildToParentMessage'
import { ArbSys__factory } from '../abi/factories/ArbSys__factory'
import { ArbRetryableTx__factory } from '../abi/factories/ArbRetryableTx__factory'
import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory'
@@ -40,18 +40,18 @@ import { NODE_INTERFACE_ADDRESS } from '../dataEntities/constants'
import { EventArgs, parseTypedLogs } from '../dataEntities/event'
import { ArbitrumProvider } from '../utils/arbProvider'
-export interface L2ContractTransaction extends ContractTransaction {
- wait(confirmations?: number): Promise
+export interface ChildContractTransaction extends ContractTransaction {
+ wait(confirmations?: number): Promise
}
-export interface RedeemTransaction extends L2ContractTransaction {
+export interface RedeemTransaction extends ChildContractTransaction {
waitForRedeem: () => Promise
}
/**
* Extension of ethers-js TransactionReceipt, adding Arbitrum-specific functionality
*/
-export class L2TransactionReceipt implements TransactionReceipt {
+export class ChildTransactionReceipt implements TransactionReceipt {
public readonly to: string
public readonly from: string
public readonly contractAddress: string
@@ -91,10 +91,10 @@ export class L2TransactionReceipt implements TransactionReceipt {
}
/**
- * Get an L2ToL1TxEvent events created by this transaction
+ * Get {@link ChildToParentTransactionEvent} events created by this transaction
* @returns
*/
- public getL2ToL1Events(): L2ToL1TransactionEvent[] {
+ public getChildToParentEvents(): ChildToParentTransactionEvent[] {
const classicLogs = parseTypedLogs(
ArbSys__factory,
this.logs,
@@ -113,47 +113,47 @@ export class L2TransactionReceipt implements TransactionReceipt {
}
/**
- * Get any l2-to-l1-messages created by this transaction
- * @param l2SignerOrProvider
+ * Get any child-to-parent-messages created by this transaction
+ * @param parentSignerOrProvider
*/
- public async getL2ToL1Messages(
- l1SignerOrProvider: T
- ): Promise[]>
- public async getL2ToL1Messages(
- l1SignerOrProvider: T
- ): Promise {
- const provider = SignerProviderUtils.getProvider(l1SignerOrProvider)
+ public async getChildToParentMessages(
+ parentSignerOrProvider: T
+ ): Promise[]>
+ public async getChildToParentMessages(
+ parentSignerOrProvider: T
+ ): Promise {
+ const provider = SignerProviderUtils.getProvider(parentSignerOrProvider)
if (!provider) throw new ArbSdkError('Signer not connected to provider.')
- return this.getL2ToL1Events().map(log =>
- L2ToL1Message.fromEvent(l1SignerOrProvider, log)
+ return this.getChildToParentEvents().map(log =>
+ ChildToParentMessage.fromEvent(parentSignerOrProvider, log)
)
}
/**
- * Get number of L1 confirmations that the batch including this tx has
- * @param l2Provider
+ * Get number of parent chain confirmations that the batch including this tx has
+ * @param childProvider
* @returns number of confirmations of batch including tx, or 0 if no batch included this tx
*/
- public getBatchConfirmations(l2Provider: providers.JsonRpcProvider) {
+ public getBatchConfirmations(childProvider: providers.JsonRpcProvider) {
const nodeInterface = NodeInterface__factory.connect(
NODE_INTERFACE_ADDRESS,
- l2Provider
+ childProvider
)
return nodeInterface.getL1Confirmations(this.blockHash)
}
/**
* Get the number of the batch that included this tx (will throw if no such batch exists)
- * @param l2Provider
+ * @param childProvider
* @returns number of batch in which tx was included, or errors if no batch includes the current tx
*/
- public async getBatchNumber(l2Provider: providers.JsonRpcProvider) {
+ public async getBatchNumber(childProvider: providers.JsonRpcProvider) {
const nodeInterface = NodeInterface__factory.connect(
NODE_INTERFACE_ADDRESS,
- l2Provider
+ childProvider
)
- const arbProvider = new ArbitrumProvider(l2Provider)
+ const arbProvider = new ArbitrumProvider(childProvider)
const rec = await arbProvider.getTransactionReceipt(this.transactionHash)
if (rec == null)
throw new ArbSdkError(
@@ -165,16 +165,16 @@ export class L2TransactionReceipt implements TransactionReceipt {
/**
* Whether the data associated with this transaction has been
- * made available on L1
- * @param l2Provider
+ * made available on parent chain
+ * @param childProvider
* @param confirmations The number of confirmations on the batch before data is to be considered available
* @returns
*/
public async isDataAvailable(
- l2Provider: providers.JsonRpcProvider,
+ childProvider: providers.JsonRpcProvider,
confirmations = 10
): Promise {
- const res = await this.getBatchConfirmations(l2Provider)
+ const res = await this.getBatchConfirmations(childProvider)
// is there a batch with enough confirmations
return res.toNumber() > confirmations
}
@@ -186,28 +186,28 @@ export class L2TransactionReceipt implements TransactionReceipt {
*/
public static monkeyPatchWait = (
contractTransaction: ContractTransaction
- ): L2ContractTransaction => {
+ ): ChildContractTransaction => {
const wait = contractTransaction.wait
contractTransaction.wait = async (_confirmations?: number) => {
- // we ignore the confirmations for now since L2 transactions shouldn't re-org
+ // we ignore the confirmations for now since child chain transactions shouldn't re-org
// in future we should give users a more fine grained way to check the finality of
- // an l2 transaction - check if a batch is on L1, if an assertion has been made, and if
+ // an child chain transaction - check if a batch is on a parent chain, if an assertion has been made, and if
// it has been confirmed.
const result = await wait()
- return new L2TransactionReceipt(result)
+ return new ChildTransactionReceipt(result)
}
- return contractTransaction as L2ContractTransaction
+ return contractTransaction as ChildContractTransaction
}
/**
* Adds a waitForRedeem function to a redeem transaction
* @param redeemTx
- * @param l2Provider
+ * @param childProvider
* @returns
*/
public static toRedeemTransaction(
- redeemTx: L2ContractTransaction,
- l2Provider: providers.Provider
+ redeemTx: ChildContractTransaction,
+ childProvider: providers.Provider
): RedeemTransaction {
const returnRec = redeemTx as RedeemTransaction
returnRec.waitForRedeem = async () => {
@@ -221,7 +221,7 @@ export class L2TransactionReceipt implements TransactionReceipt {
)
}
- return await l2Provider.getTransactionReceipt(
+ return await childProvider.getTransactionReceipt(
redeemScheduledEvents[0].retryTxHash
)
}
diff --git a/src/lib/message/L2ToL1Message.ts b/src/lib/message/L2ToL1Message.ts
deleted file mode 100644
index eb93eeca9f..0000000000
--- a/src/lib/message/L2ToL1Message.ts
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright 2021, Offchain Labs, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* eslint-env node */
-'use strict'
-
-import { Provider } from '@ethersproject/abstract-provider'
-import { Signer } from '@ethersproject/abstract-signer'
-import { BigNumber } from '@ethersproject/bignumber'
-import { BlockTag } from '@ethersproject/abstract-provider'
-
-import { ContractTransaction, Overrides } from 'ethers'
-import {
- SignerProviderUtils,
- SignerOrProvider,
-} from '../dataEntities/signerOrProvider'
-import * as classic from './L2ToL1MessageClassic'
-import * as nitro from './L2ToL1MessageNitro'
-import {
- L2ToL1TransactionEvent as ClassicL2ToL1TransactionEvent,
- L2ToL1TxEvent as NitroL2ToL1TransactionEvent,
-} from '../abi/ArbSys'
-import { isDefined } from '../utils/lib'
-import { EventArgs } from '../dataEntities/event'
-import { L2ToL1MessageStatus } from '../dataEntities/message'
-import { getL2Network } from '../dataEntities/networks'
-import { ArbSdkError } from '../dataEntities/errors'
-
-export type L2ToL1TransactionEvent =
- | EventArgs
- | EventArgs
-
-/**
- * Conditional type for Signer or Provider. If T is of type Provider
- * then L2ToL1MessageReaderOrWriter will be of type L2ToL1MessageReader.
- * If T is of type Signer then L2ToL1MessageReaderOrWriter will be of
- * type L2ToL1MessageWriter.
- */
-export type L2ToL1MessageReaderOrWriter =
- T extends Provider ? L2ToL1MessageReader : L2ToL1MessageWriter
-
-/**
- * Base functionality for L2->L1 messages
- */
-export class L2ToL1Message {
- protected isClassic(
- e: L2ToL1TransactionEvent
- ): e is EventArgs {
- return isDefined(
- (e as EventArgs).indexInBatch
- )
- }
-
- /**
- * Instantiates a new `L2ToL1MessageWriter` or `L2ToL1MessageReader` object.
- *
- * @param {SignerOrProvider} l1SignerOrProvider Signer or provider to be used for executing or reading the L2-to-L1 message.
- * @param {L2ToL1TransactionEvent} event The event containing the data of the L2-to-L1 message.
- * @param {Provider} [l1Provider] Optional. Used to override the Provider which is attached to `l1SignerOrProvider` in case you need more control. This will be a required parameter in a future major version update.
- */
- public static fromEvent(
- l1SignerOrProvider: T,
- event: L2ToL1TransactionEvent,
- l1Provider?: Provider
- ): L2ToL1MessageReaderOrWriter
- static fromEvent(
- l1SignerOrProvider: T,
- event: L2ToL1TransactionEvent,
- l1Provider?: Provider
- ): L2ToL1MessageReader | L2ToL1MessageWriter {
- return SignerProviderUtils.isSigner(l1SignerOrProvider)
- ? new L2ToL1MessageWriter(l1SignerOrProvider, event, l1Provider)
- : new L2ToL1MessageReader(l1SignerOrProvider, event)
- }
-
- /**
- * Get event logs for L2ToL1 transactions.
- * @param l2Provider
- * @param filter Block range filter
- * @param position The batchnumber indexed field was removed in nitro and a position indexed field was added.
- * For pre-nitro events the value passed in here will be used to find events with the same batchnumber.
- * For post nitro events it will be used to find events with the same position.
- * @param destination The L1 destination of the L2ToL1 message
- * @param hash The uniqueId indexed field was removed in nitro and a hash indexed field was added.
- * For pre-nitro events the value passed in here will be used to find events with the same uniqueId.
- * For post nitro events it will be used to find events with the same hash.
- * @param indexInBatch The index in the batch, only valid for pre-nitro events. This parameter is ignored post-nitro
- * @returns Any classic and nitro events that match the provided filters.
- */
- public static async getL2ToL1Events(
- l2Provider: Provider,
- filter: { fromBlock: BlockTag; toBlock: BlockTag },
- position?: BigNumber,
- destination?: string,
- hash?: BigNumber,
- indexInBatch?: BigNumber
- ): Promise<(L2ToL1TransactionEvent & { transactionHash: string })[]> {
- const l2Network = await getL2Network(l2Provider)
-
- const inClassicRange = (blockTag: BlockTag, nitroGenBlock: number) => {
- if (typeof blockTag === 'string') {
- // taking classic of "earliest", "latest", "earliest" and the nitro gen block
- // yields 0, nitro gen, nitro gen since the classic range is always between 0 and nitro gen
-
- switch (blockTag) {
- case 'earliest':
- return 0
- case 'latest':
- return nitroGenBlock
- case 'pending':
- return nitroGenBlock
- default:
- throw new ArbSdkError(`Unrecognised block tag. ${blockTag}`)
- }
- }
- return Math.min(blockTag, nitroGenBlock)
- }
-
- const inNitroRange = (blockTag: BlockTag, nitroGenBlock: number) => {
- // taking nitro range of "earliest", "latest", "earliest" and the nitro gen block
- // yields nitro gen, latest, pending since the nitro range is always between nitro gen and latest/pending
-
- if (typeof blockTag === 'string') {
- switch (blockTag) {
- case 'earliest':
- return nitroGenBlock
- case 'latest':
- return 'latest'
- case 'pending':
- return 'pending'
- default:
- throw new ArbSdkError(`Unrecognised block tag. ${blockTag}`)
- }
- }
-
- return Math.max(blockTag, nitroGenBlock)
- }
-
- // only fetch nitro events after the genesis block
- const classicFilter = {
- fromBlock: inClassicRange(filter.fromBlock, l2Network.nitroGenesisBlock),
- toBlock: inClassicRange(filter.toBlock, l2Network.nitroGenesisBlock),
- }
- const logQueries = []
- if (classicFilter.fromBlock !== classicFilter.toBlock) {
- logQueries.push(
- classic.L2ToL1MessageClassic.getL2ToL1Events(
- l2Provider,
- classicFilter,
- position,
- destination,
- hash,
- indexInBatch
- )
- )
- }
-
- const nitroFilter = {
- fromBlock: inNitroRange(filter.fromBlock, l2Network.nitroGenesisBlock),
- toBlock: inNitroRange(filter.toBlock, l2Network.nitroGenesisBlock),
- }
- if (nitroFilter.fromBlock !== nitroFilter.toBlock) {
- logQueries.push(
- nitro.L2ToL1MessageNitro.getL2ToL1Events(
- l2Provider,
- nitroFilter,
- position,
- destination,
- hash
- )
- )
- }
-
- return (await Promise.all(logQueries)).flat(1)
- }
-}
-
-/**
- * Provides read-only access for l2-to-l1-messages
- */
-export class L2ToL1MessageReader extends L2ToL1Message {
- private readonly classicReader?: classic.L2ToL1MessageReaderClassic
- private readonly nitroReader?: nitro.L2ToL1MessageReaderNitro
-
- constructor(
- protected readonly l1Provider: Provider,
- event: L2ToL1TransactionEvent
- ) {
- super()
- if (this.isClassic(event)) {
- this.classicReader = new classic.L2ToL1MessageReaderClassic(
- l1Provider,
- event.batchNumber,
- event.indexInBatch
- )
- } else {
- this.nitroReader = new nitro.L2ToL1MessageReaderNitro(l1Provider, event)
- }
- }
-
- public async getOutboxProof(
- l2Provider: Provider
- ): Promise {
- if (this.nitroReader) {
- return await this.nitroReader.getOutboxProof(l2Provider)
- } else return await this.classicReader!.tryGetProof(l2Provider)
- }
-
- /**
- * Get the status of this message
- * In order to check if the message has been executed proof info must be provided.
- * @returns
- */
- public async status(l2Provider: Provider): Promise {
- // can we create an l2tol1message here, we need to - the constructor is what we need
- if (this.nitroReader) return await this.nitroReader.status(l2Provider)
- else return await this.classicReader!.status(l2Provider)
- }
-
- /**
- * Waits until the outbox entry has been created, and will not return until it has been.
- * WARNING: Outbox entries are only created when the corresponding node is confirmed. Which
- * can take 1 week+, so waiting here could be a very long operation.
- * @param retryDelay
- * @returns outbox entry status (either executed or confirmed but not pending)
- */
- public async waitUntilReadyToExecute(
- l2Provider: Provider,
- retryDelay = 500
- ): Promise {
- if (this.nitroReader)
- return this.nitroReader.waitUntilReadyToExecute(l2Provider, retryDelay)
- else
- return this.classicReader!.waitUntilOutboxEntryCreated(
- l2Provider,
- retryDelay
- )
- }
-
- /**
- * Estimates the L1 block number in which this L2 to L1 tx will be available for execution.
- * If the message can or already has been executed, this returns null
- * @param l2Provider
- * @returns expected L1 block number where the L2 to L1 message will be executable. Returns null if the message can or already has been executed
- */
- public async getFirstExecutableBlock(
- l2Provider: Provider
- ): Promise {
- if (this.nitroReader)
- return this.nitroReader.getFirstExecutableBlock(l2Provider)
- else return this.classicReader!.getFirstExecutableBlock(l2Provider)
- }
-}
-
-/**
- * Provides read and write access for l2-to-l1-messages
- */
-export class L2ToL1MessageWriter extends L2ToL1MessageReader {
- private readonly classicWriter?: classic.L2ToL1MessageWriterClassic
- private readonly nitroWriter?: nitro.L2ToL1MessageWriterNitro
-
- /**
- * Instantiates a new `L2ToL1MessageWriter` object.
- *
- * @param {Signer} l1Signer The signer to be used for executing the L2-to-L1 message.
- * @param {L2ToL1TransactionEvent} event The event containing the data of the L2-to-L1 message.
- * @param {Provider} [l1Provider] Optional. Used to override the Provider which is attached to `l1Signer` in case you need more control. This will be a required parameter in a future major version update.
- */
- constructor(
- l1Signer: Signer,
- event: L2ToL1TransactionEvent,
- l1Provider?: Provider
- ) {
- super(l1Provider ?? l1Signer.provider!, event)
-
- if (this.isClassic(event)) {
- this.classicWriter = new classic.L2ToL1MessageWriterClassic(
- l1Signer,
- event.batchNumber,
- event.indexInBatch,
- l1Provider
- )
- } else {
- this.nitroWriter = new nitro.L2ToL1MessageWriterNitro(
- l1Signer,
- event,
- l1Provider
- )
- }
- }
-
- /**
- * Executes the L2ToL1Message on L1.
- * Will throw an error if the outbox entry has not been created, which happens when the
- * corresponding assertion is confirmed.
- * @returns
- */
- public async execute(
- l2Provider: Provider,
- overrides?: Overrides
- ): Promise {
- if (this.nitroWriter) return this.nitroWriter.execute(l2Provider, overrides)
- else return await this.classicWriter!.execute(l2Provider, overrides)
- }
-}
diff --git a/src/lib/message/L1ToL2Message.ts b/src/lib/message/ParentToChildMessage.ts
similarity index 68%
rename from src/lib/message/L1ToL2Message.ts
rename to src/lib/message/ParentToChildMessage.ts
index 2339c77576..df0d4ab125 100644
--- a/src/lib/message/L1ToL2Message.ts
+++ b/src/lib/message/ParentToChildMessage.ts
@@ -26,40 +26,44 @@ import { getAddress } from '@ethersproject/address'
import { keccak256 } from '@ethersproject/keccak256'
import { ArbRetryableTx__factory } from '../abi/factories/ArbRetryableTx__factory'
-import { ARB_RETRYABLE_TX_ADDRESS } from '../dataEntities/constants'
+import {
+ ARB_RETRYABLE_TX_ADDRESS,
+ DEFAULT_DEPOSIT_TIMEOUT,
+ SEVEN_DAYS_IN_SECONDS,
+} from '../dataEntities/constants'
import {
SignerProviderUtils,
SignerOrProvider,
} from '../dataEntities/signerOrProvider'
import { ArbSdkError } from '../dataEntities/errors'
import { ethers, Overrides } from 'ethers'
-import { L2TransactionReceipt, RedeemTransaction } from './L2Transaction'
-import { getL2Network } from '../../lib/dataEntities/networks'
+import { ChildTransactionReceipt, RedeemTransaction } from './ChildTransaction'
import { RetryableMessageParams } from '../dataEntities/message'
import { getTransactionReceipt, isDefined } from '../utils/lib'
import { EventFetcher } from '../utils/eventFetcher'
import { ErrorCode, Logger } from '@ethersproject/logger'
+import { getArbitrumNetwork } from '../dataEntities/networks'
-export enum L1ToL2MessageStatus {
+export enum ParentToChildMessageStatus {
/**
* The retryable ticket has yet to be created
*/
NOT_YET_CREATED = 1,
/**
* An attempt was made to create the retryable ticket, but it failed.
- * This could be due to not enough submission cost being paid by the L1 transaction
+ * This could be due to not enough submission cost being paid by the Parent transaction
*/
CREATION_FAILED = 2,
/**
* The retryable ticket has been created but has not been redeemed. This could be due to the
- * auto redeem failing, or if the params (max l2 gas price) * (max l2 gas) = 0 then no auto
+ * auto redeem failing, or if the params (max chain gas price) * (max chain gas) = 0 then no auto
* redeem tx is ever issued. An auto redeem is also never issued for ETH deposits.
* A manual redeem is now required.
*/
- FUNDS_DEPOSITED_ON_L2 = 3,
+ FUNDS_DEPOSITED_ON_CHILD = 3,
/**
* The retryable ticket has been redeemed (either by auto, or manually) and the
- * l2 transaction has been executed
+ * chain transaction has been executed
*/
REDEEMED = 4,
/**
@@ -68,13 +72,13 @@ export enum L1ToL2MessageStatus {
EXPIRED = 5,
}
-export enum EthDepositStatus {
+export enum EthDepositMessageStatus {
/**
- * ETH is not deposited on L2 yet
+ * ETH is not deposited on Chain yet
*/
PENDING = 1,
/**
- * ETH is deposited successfully on L2
+ * ETH is deposited successfully on Chain
*/
DEPOSITED = 2,
}
@@ -87,16 +91,16 @@ interface RetryableExistsError extends Error {
/**
* Conditional type for Signer or Provider. If T is of type Provider
- * then L1ToL2MessageReaderOrWriter will be of type L1ToL2MessageReader.
- * If T is of type Signer then L1ToL2MessageReaderOrWriter will be of
- * type L1ToL2MessageWriter.
+ * then ParentToChildMessageReaderOrWriter will be of type ParentToChildMessageReader.
+ * If T is of type Signer then ParentToChildMessageReaderOrWriter will be of
+ * type ParentToChildMessageWriter.
*/
-export type L1ToL2MessageReaderOrWriter =
- T extends Provider ? L1ToL2MessageReader : L1ToL2MessageWriter
+export type ParentToChildMessageReaderOrWriter =
+ T extends Provider ? ParentToChildMessageReader : ParentToChildMessageWriter
-export abstract class L1ToL2Message {
+export abstract class ParentToChildMessage {
/**
- * When messages are sent from L1 to L2 a retryable ticket is created on L2.
+ * When messages are sent from Parent to Child a retryable ticket is created on the child chain.
* The retryableCreationId can be used to retrieve information about the success or failure of the
* creation of the retryable ticket.
*/
@@ -105,29 +109,29 @@ export abstract class L1ToL2Message {
/**
* The submit retryable transactions use the typed transaction envelope 2718.
* The id of these transactions is the hash of the RLP encoded transaction.
- * @param l2ChainId
- * @param fromAddress the aliased address that called the L1 inbox as emitted in the bridge event.
+ * @param childChainId
+ * @param fromAddress the aliased address that called the Parent inbox as emitted in the bridge event.
* @param messageNumber
- * @param l1BaseFee
+ * @param parentBaseFee
* @param destAddress
- * @param l2CallValue
- * @param l1Value
+ * @param childCallValue
+ * @param parentCallValue
* @param maxSubmissionFee
- * @param excessFeeRefundAddress refund address specified in the retryable creation. Note the L1 inbox aliases this address if it is a L1 smart contract. The user is expected to provide this value already aliased when needed.
- * @param callValueRefundAddress refund address specified in the retryable creation. Note the L1 inbox aliases this address if it is a L1 smart contract. The user is expected to provide this value already aliased when needed.
+ * @param excessFeeRefundAddress refund address specified in the retryable creation. Note the Parent inbox aliases this address if it is a Parent smart contract. The user is expected to provide this value already aliased when needed.
+ * @param callValueRefundAddress refund address specified in the retryable creation. Note the Parent inbox aliases this address if it is a Parent smart contract. The user is expected to provide this value already aliased when needed.
* @param gasLimit
* @param maxFeePerGas
* @param data
* @returns
*/
public static calculateSubmitRetryableId(
- l2ChainId: number,
+ childChainId: number,
fromAddress: string,
messageNumber: BigNumber,
- l1BaseFee: BigNumber,
+ parentBaseFee: BigNumber,
destAddress: string,
- l2CallValue: BigNumber,
- l1Value: BigNumber,
+ childCallValue: BigNumber,
+ parentCallValue: BigNumber,
maxSubmissionFee: BigNumber,
excessFeeRefundAddress: string,
callValueRefundAddress: string,
@@ -139,21 +143,21 @@ export abstract class L1ToL2Message {
return ethers.utils.stripZeros(value.toHexString())
}
- const chainId = BigNumber.from(l2ChainId)
+ const chainId = BigNumber.from(childChainId)
const msgNum = BigNumber.from(messageNumber)
const fields: any[] = [
formatNumber(chainId),
zeroPad(formatNumber(msgNum), 32),
fromAddress,
- formatNumber(l1BaseFee),
+ formatNumber(parentBaseFee),
- formatNumber(l1Value),
+ formatNumber(parentCallValue),
formatNumber(maxFeePerGas),
formatNumber(gasLimit),
// when destAddress is 0x0, arbos treat that as nil
destAddress === ethers.constants.AddressZero ? '0x' : destAddress,
- formatNumber(l2CallValue),
+ formatNumber(childCallValue),
callValueRefundAddress,
formatNumber(maxSubmissionFee),
excessFeeRefundAddress,
@@ -170,36 +174,36 @@ export abstract class L1ToL2Message {
}
public static fromEventComponents(
- l2SignerOrProvider: T,
+ chainSignerOrProvider: T,
chainId: number,
sender: string,
messageNumber: BigNumber,
- l1BaseFee: BigNumber,
+ parentBaseFee: BigNumber,
messageData: RetryableMessageParams
- ): L1ToL2MessageReaderOrWriter
+ ): ParentToChildMessageReaderOrWriter
public static fromEventComponents(
- l2SignerOrProvider: T,
+ chainSignerOrProvider: T,
chainId: number,
sender: string,
messageNumber: BigNumber,
- l1BaseFee: BigNumber,
+ parentBaseFee: BigNumber,
messageData: RetryableMessageParams
- ): L1ToL2MessageReader | L1ToL2MessageWriter {
- return SignerProviderUtils.isSigner(l2SignerOrProvider)
- ? new L1ToL2MessageWriter(
- l2SignerOrProvider,
+ ): ParentToChildMessageReader | ParentToChildMessageWriter {
+ return SignerProviderUtils.isSigner(chainSignerOrProvider)
+ ? new ParentToChildMessageWriter(
+ chainSignerOrProvider,
chainId,
sender,
messageNumber,
- l1BaseFee,
+ parentBaseFee,
messageData
)
- : new L1ToL2MessageReader(
- l2SignerOrProvider,
+ : new ParentToChildMessageReader(
+ chainSignerOrProvider,
chainId,
sender,
messageNumber,
- l1BaseFee,
+ parentBaseFee,
messageData
)
}
@@ -208,14 +212,14 @@ export abstract class L1ToL2Message {
public readonly chainId: number,
public readonly sender: string,
public readonly messageNumber: BigNumber,
- public readonly l1BaseFee: BigNumber,
+ public readonly parentBaseFee: BigNumber,
public readonly messageData: RetryableMessageParams
) {
- this.retryableCreationId = L1ToL2Message.calculateSubmitRetryableId(
+ this.retryableCreationId = ParentToChildMessage.calculateSubmitRetryableId(
chainId,
sender,
messageNumber,
- l1BaseFee,
+ parentBaseFee,
messageData.destAddress,
messageData.l2CallValue,
messageData.l1Value,
@@ -230,33 +234,41 @@ export abstract class L1ToL2Message {
}
/**
- * If the status is redeemed an l2TxReceipt is populated.
- * For all other statuses l2TxReceipt is not populated
+ * If the status is redeemed, childTxReceipt is populated.
+ * For all other statuses childTxReceipt is not populated
*/
-export type L1ToL2MessageWaitResult =
- | { status: L1ToL2MessageStatus.REDEEMED; l2TxReceipt: TransactionReceipt }
- | { status: Exclude }
+export type ParentToChildMessageWaitForStatusResult =
+ | {
+ status: ParentToChildMessageStatus.REDEEMED
+ childTxReceipt: TransactionReceipt
+ }
+ | {
+ status: Exclude<
+ ParentToChildMessageStatus,
+ ParentToChildMessageStatus.REDEEMED
+ >
+ }
-export type EthDepositMessageWaitResult = {
- l2TxReceipt: TransactionReceipt | null
+export type EthDepositMessageWaitForStatusResult = {
+ childTxReceipt: TransactionReceipt | null
}
-export class L1ToL2MessageReader extends L1ToL2Message {
+export class ParentToChildMessageReader extends ParentToChildMessage {
private retryableCreationReceipt: TransactionReceipt | undefined | null
public constructor(
- public readonly l2Provider: Provider,
+ public readonly childProvider: Provider,
chainId: number,
sender: string,
messageNumber: BigNumber,
- l1BaseFee: BigNumber,
+ parentBaseFee: BigNumber,
messageData: RetryableMessageParams
) {
- super(chainId, sender, messageNumber, l1BaseFee, messageData)
+ super(chainId, sender, messageNumber, parentBaseFee, messageData)
}
/**
* Try to get the receipt for the retryable ticket creation.
- * This is the L2 transaction that creates the retryable ticket.
+ * This is the Chain transaction that creates the retryable ticket.
* If confirmations or timeout is provided, this will wait for the ticket to be created
* @returns Null if retryable has not been created
*/
@@ -266,7 +278,7 @@ export class L1ToL2MessageReader extends L1ToL2Message {
): Promise {
if (!this.retryableCreationReceipt) {
this.retryableCreationReceipt = await getTransactionReceipt(
- this.l2Provider,
+ this.childProvider,
this.retryableCreationId,
confirmations,
timeout
@@ -285,11 +297,11 @@ export class L1ToL2MessageReader extends L1ToL2Message {
const creationReceipt = await this.getRetryableCreationReceipt()
if (creationReceipt) {
- const l2Receipt = new L2TransactionReceipt(creationReceipt)
- const redeemEvents = l2Receipt.getRedeemScheduledEvents()
+ const chainReceipt = new ChildTransactionReceipt(creationReceipt)
+ const redeemEvents = chainReceipt.getRedeemScheduledEvents()
if (redeemEvents.length === 1) {
- return await this.l2Provider.getTransactionReceipt(
+ return await this.childProvider.getTransactionReceipt(
redeemEvents[0].retryTxHash
)
} else if (redeemEvents.length > 1) {
@@ -303,34 +315,39 @@ export class L1ToL2MessageReader extends L1ToL2Message {
}
/**
- * Receipt for the successful l2 transaction created by this message.
+ * Receipt for the successful chain transaction created by this message.
* @returns TransactionReceipt of the first successful redeem if exists, otherwise the current status of the message.
*/
- public async getSuccessfulRedeem(): Promise