From 042f6a2b4f97cd3be55bc58a9ad20fa6e141b347 Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Fri, 22 Sep 2023 09:18:40 -0400 Subject: [PATCH 01/14] chore: renames L1/2 to parentChain/chain in inbox --- scripts/sendL2SignedMsg.ts | 4 +- src/lib/inbox/inbox.ts | 136 +++++++++++++++------------- tests/integration/sendL2msg.test.ts | 4 +- 3 files changed, 76 insertions(+), 68 deletions(-) diff --git a/scripts/sendL2SignedMsg.ts b/scripts/sendL2SignedMsg.ts index 10ac03e9e7..088b19c0cf 100644 --- a/scripts/sendL2SignedMsg.ts +++ b/scripts/sendL2SignedMsg.ts @@ -29,8 +29,8 @@ const sendSignedMsg = async () => { value: BigNumber.from(0), data: '0x12', } - const signedTx = await inbox.signL2Tx(message, l2Deployer) - await inbox.sendL2SignedTx(signedTx) + const signedTx = await inbox.signChainTx(message, l2Deployer) + await inbox.sendChainSignedTx(signedTx) } sendSignedMsg() diff --git a/src/lib/inbox/inbox.ts b/src/lib/inbox/inbox.ts index 240bfb61b6..c6d28d74a0 100644 --- a/src/lib/inbox/inbox.ts +++ b/src/lib/inbox/inbox.ts @@ -28,7 +28,10 @@ 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 { l1Networks, L2Network } from '../dataEntities/networks' +import { + l1Networks as parentChainNetworks, + L2Network as ChainNetwork, +} from '../dataEntities/networks' import { SignerProviderUtils } from '../dataEntities/signerOrProvider' import { FetchedEvent, EventFetcher } from '../utils/eventFetcher' import { MultiCaller, CallInput } from '../utils/multicall' @@ -42,12 +45,12 @@ type ForceInclusionParams = FetchedEvent & { delayedAcc: string } -type GasComponentsWithL2Part = { +type GasComponentsWithChainPart = { gasEstimate: BigNumber gasEstimateForL1: BigNumber baseFee: BigNumber l1BaseFeeEstimate: BigNumber - gasEstimateForL2: BigNumber + gasEstimateForChain: BigNumber } type RequiredTransactionRequestType = RequiredPick< TransactionRequest, @@ -57,18 +60,20 @@ type RequiredTransactionRequestType = RequiredPick< * Tools for interacting with the inbox and bridge contracts */ export class InboxTools { - private readonly l1Provider - private readonly l1Network + private readonly parentChainProvider + private readonly parentChainNetwork constructor( - private readonly l1Signer: Signer, - private readonly l2Network: L2Network + private readonly parentChainSigner: Signer, + private readonly chainNetwork: ChainNetwork ) { - this.l1Provider = SignerProviderUtils.getProviderOrThrow(this.l1Signer) - this.l1Network = l1Networks[l2Network.partnerChainID] - if (!this.l1Network) + this.parentChainProvider = SignerProviderUtils.getProviderOrThrow( + this.parentChainSigner + ) + this.parentChainNetwork = parentChainNetworks[chainNetwork.partnerChainID] + if (!this.parentChainNetwork) throw new ArbSdkError( - `L1Network not found for chain id: ${l2Network.partnerChainID}.` + `ParentChainNetwork not found for chain id: ${chainNetwork.partnerChainID}.` ) } @@ -84,13 +89,16 @@ export class InboxTools { blockNumber: number, blockTimestamp: number ): Promise { - const block = await this.l1Provider.getBlock(blockNumber) + const block = await this.parentChainProvider.getBlock(blockNumber) const diff = block.timestamp - blockTimestamp if (diff < 0) return block // we take a long average block time of 14s // and always move at least 10 blocks - const diffBlocks = Math.max(Math.ceil(diff / this.l1Network.blockTime), 10) + const diffBlocks = Math.max( + Math.ceil(diff / this.parentChainNetwork.blockTime), + 10 + ) return await this.findFirstBlockBelow( blockNumber - diffBlocks, @@ -100,12 +108,12 @@ export class InboxTools { //Check if this request is contract creation or not. private isContractCreation( - transactionl2Request: TransactionRequest + transactionChainRequest: TransactionRequest ): boolean { if ( - transactionl2Request.to === '0x' || - !isDefined(transactionl2Request.to) || - transactionl2Request.to === ethers.constants.AddressZero + transactionChainRequest.to === '0x' || + !isDefined(transactionChainRequest.to) || + transactionChainRequest.to === ethers.constants.AddressZero ) { return true } @@ -114,32 +122,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 parentChain calldata * gas fee part. */ private async estimateArbitrumGas( - transactionl2Request: RequiredTransactionRequestType, - l2Provider: Provider - ): Promise { + transactionChainRequest: RequiredTransactionRequestType, + chainProvider: Provider + ): Promise { const nodeInterface = NodeInterface__factory.connect( NODE_INTERFACE_ADDRESS, - l2Provider + chainProvider ) - const contractCreation = this.isContractCreation(transactionl2Request) + const contractCreation = this.isContractCreation(transactionChainRequest) const gasComponents = await nodeInterface.callStatic.gasEstimateComponents( - transactionl2Request.to || ethers.constants.AddressZero, + transactionChainRequest.to || ethers.constants.AddressZero, contractCreation, - transactionl2Request.data, + transactionChainRequest.data, { - from: transactionl2Request.from, - value: transactionl2Request.value, + from: transactionChainRequest.from, + value: transactionChainRequest.value, } ) - const gasEstimateForL2: BigNumber = gasComponents.gasEstimate.sub( + const gasEstimateForChain: BigNumber = gasComponents.gasEstimate.sub( gasComponents.gasEstimateForL1 ) - return { ...gasComponents, gasEstimateForL2 } + return { ...gasComponents, gasEstimateForChain } } /** @@ -149,11 +157,11 @@ export class InboxTools { */ private async getForceIncludableBlockRange(blockNumberRangeSize: number) { const sequencerInbox = SequencerInbox__factory.connect( - this.l2Network.ethBridge.sequencerInbox, - this.l1Provider + this.chainNetwork.ethBridge.sequencerInbox, + this.parentChainProvider ) - const multicall = await MultiCaller.fromProvider(this.l1Provider) + const multicall = await MultiCaller.fromProvider(this.parentChainProvider) const multicallInput: [ CallInput>>, ReturnType, @@ -207,7 +215,7 @@ export class InboxTools { maxSearchRangeBlocks: number, rangeMultiplier: number ): Promise[]> { - const eFetcher = new EventFetcher(this.l1Provider) + const eFetcher = new EventFetcher(this.parentChainProvider) // events don't become eligible until they pass a delay // find a block range which will emit eligible events @@ -245,7 +253,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 @@ -255,11 +263,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.chainNetwork.ethBridge.bridge, + this.parentChainProvider ) // events dont become eligible until they pass a delay @@ -268,7 +276,7 @@ export class InboxTools { bridge, startSearchRangeBlocks, maxSearchRangeBlocks, - rangeMultipler + rangeMultiplier ) // no events appeared within that time period @@ -277,8 +285,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.chainNetwork.ethBridge.sequencerInbox, + this.parentChainProvider ) // has the sequencer inbox already read this latest message const totalDelayedRead = await sequencerInbox.totalDelayedMessagesRead() @@ -317,14 +325,14 @@ export class InboxTools { overrides?: Overrides ): Promise { const sequencerInbox = SequencerInbox__factory.connect( - this.l2Network.ethBridge.sequencerInbox, - this.l1Signer + this.chainNetwork.ethBridge.sequencerInbox, + this.parentChainSigner ) const eventInfo = messageDeliveredEvent || (await this.getForceIncludableEvent()) if (!eventInfo) return null - const block = await this.l1Provider.getBlock(eventInfo.blockHash) + const block = await this.parentChainProvider.getBlock(eventInfo.blockHash) return await sequencerInbox.functions.forceInclusion( eventInfo.event.messageIndex.add(1), @@ -339,19 +347,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 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. + * you can call inboxTools.signChainMessage to get. + * @returns The parentChain delayed inbox's transaction itself. */ - public async sendL2SignedTx( + public async sendChainSignedTx( signedTx: string ): Promise { const delayedInbox = IInbox__factory.connect( - this.l2Network.ethBridge.inbox, - this.l1Signer + this.chainNetwork.ethBridge.inbox, + this.parentChainSigner ) const sendData = ethers.utils.solidityPack( @@ -364,43 +372,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, * 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 chainSigner ethers Signer type, used to sign Chain transaction + * @returns The parentChain delayed inbox's transaction signed data. */ - public async signL2Tx( + public async signChainTx( txRequest: RequiredTransactionRequestType, - l2Signer: Signer + chainSigner: Signer ): Promise { const tx: RequiredTransactionRequestType = { ...txRequest } const contractCreation = this.isContractCreation(tx) if (!isDefined(tx.nonce)) { - tx.nonce = await l2Signer.getTransactionCount() + tx.nonce = await chainSigner.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 chainSigner.getGasPrice() } } else { if (!isDefined(tx.maxFeePerGas)) { - const feeData = await l2Signer.getFeeData() + const feeData = await chainSigner.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 chainSigner.getAddress() + tx.chainId = await chainSigner.getChainId() // if this is contract creation, user might not input the to address, // however, it is needed when we call to estimateArbitrumGas, so @@ -409,17 +417,17 @@ export class InboxTools { tx.to = ethers.constants.AddressZero } - //estimate gas on l2 + //estimate gas on Chain try { tx.gasLimit = ( - await this.estimateArbitrumGas(tx, l2Signer.provider!) - ).gasEstimateForL2 + await this.estimateArbitrumGas(tx, chainSigner.provider!) + ).gasEstimateForChain } catch (error) { throw new ArbSdkError('execution failed (estimate gas failed)') } if (contractCreation) { delete tx.to } - return await l2Signer.signTransaction(tx) + return await chainSigner.signTransaction(tx) } } diff --git a/tests/integration/sendL2msg.test.ts b/tests/integration/sendL2msg.test.ts index e704ab0faa..6c1aeda558 100644 --- a/tests/integration/sendL2msg.test.ts +++ b/tests/integration/sendL2msg.test.ts @@ -33,9 +33,9 @@ const sendSignedTx = async (testState: any, info?: any) => { ...info, value: BigNumber.from(0), } - const signedTx = await inbox.signL2Tx(message, l2Deployer) + const signedTx = await inbox.signChainTx(message, l2Deployer) - const l1Tx = await inbox.sendL2SignedTx(signedTx) + const l1Tx = await inbox.sendChainSignedTx(signedTx) return { signedMsg: signedTx, l1TransactionReceipt: await l1Tx?.wait(), From a64ccb2ea557c872be1dec1af5a901b43e85b13c Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Mon, 25 Sep 2023 13:06:17 -0400 Subject: [PATCH 02/14] chore: update l1/2 name for dataEntities --- scripts/testSetup.ts | 40 ++++---- src/index.ts | 12 +-- src/lib/assetBridger/assetBridger.ts | 12 ++- src/lib/assetBridger/erc20Bridger.ts | 6 +- src/lib/assetBridger/ethBridger.ts | 4 +- src/lib/dataEntities/networks.ts | 102 ++++++++++--------- src/lib/inbox/inbox.ts | 4 +- src/lib/message/L1ToL2Message.ts | 8 +- src/lib/message/L1ToL2MessageCreator.ts | 4 +- src/lib/message/L1ToL2MessageGasEstimator.ts | 4 +- src/lib/message/L1Transaction.ts | 8 +- src/lib/message/L2ToL1Message.ts | 4 +- src/lib/message/L2ToL1MessageClassic.ts | 4 +- src/lib/message/L2ToL1MessageNitro.ts | 10 +- src/lib/utils/lib.ts | 4 +- src/lib/utils/multicall.ts | 20 ++-- tests/fork/inbox.test.ts | 5 +- tests/integration/ethBridgeAddresses.test.ts | 2 +- tests/integration/sendL2msg.test.ts | 5 +- tests/integration/testHelpers.ts | 2 +- tests/unit/l2toL1MessageEvents.test.ts | 2 +- tests/unit/multicall.test.ts | 2 +- 22 files changed, 142 insertions(+), 122 deletions(-) diff --git a/scripts/testSetup.ts b/scripts/testSetup.ts index 5558054297..eb0272fe89 100644 --- a/scripts/testSetup.ts +++ b/scripts/testSetup.ts @@ -22,10 +22,10 @@ import { Wallet } from '@ethersproject/wallet' import dotenv from 'dotenv' import { EthBridger, InboxTools, Erc20Bridger } from '../src' import { - L1Network, - L2Network, - getL1Network, - getL2Network, + ParentChainNetwork, + ChainNetwork, + getParentChainNetwork, + getChainNetwork, addCustomNetwork, } from '../src/lib/dataEntities/networks' import { Signer } from 'ethers' @@ -70,8 +70,8 @@ export const getCustomNetworks = async ( l1Url: string, l2Url: string ): Promise<{ - l1Network: L1Network - l2Network: Omit + l1Network: ParentChainNetwork + l2Network: Omit }> => { const l1Provider = new JsonRpcProvider(l1Url) const l2Provider = new JsonRpcProvider(l2Url) @@ -98,7 +98,7 @@ export const getCustomNetworks = async ( const l1NetworkInfo = await l1Provider.getNetwork() const l2NetworkInfo = await l2Provider.getNetwork() - const l1Network: L1Network = { + const l1Network: ParentChainNetwork = { blockTime: 10, chainID: l1NetworkInfo.chainId, explorerUrl: '', @@ -108,7 +108,7 @@ export const getCustomNetworks = async ( isArbitrum: false, } - const l2Network: Omit = { + const l2Network: Omit = { chainID: l2NetworkInfo.chainId, confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), ethBridge: { @@ -149,7 +149,7 @@ export const setupNetworks = async ( l2Deployer, coreL2Network.ethBridge.inbox ) - const l2Network: L2Network = { + const l2Network: ChainNetwork = { ...coreL2Network, tokenBridge: { l1CustomGateway: l1Contracts.customGateway.address, @@ -171,8 +171,8 @@ export const setupNetworks = async ( } addCustomNetwork({ - customL1Network: l1Network, - customL2Network: l2Network, + customParentChainNetwork: l1Network, + customChainNetwork: l2Network, }) // also register the weth gateway @@ -204,8 +204,8 @@ export const getSigner = (provider: JsonRpcProvider, key?: string) => { } export const testSetup = async (): Promise<{ - l1Network: L1Network - l2Network: L2Network + l1Network: ParentChainNetwork + l2Network: ChainNetwork l1Signer: Signer l2Signer: Signer erc20Bridger: Erc20Bridger @@ -225,10 +225,10 @@ export const testSetup = async (): Promise<{ const l1Signer = seed.connect(ethProvider) const l2Signer = seed.connect(arbProvider) - let setL1Network: L1Network, setL2Network: L2Network + let setL1Network: ParentChainNetwork, setL2Network: ChainNetwork try { - const l1Network = await getL1Network(l1Deployer) - const l2Network = await getL2Network(l2Deployer) + const l1Network = await getParentChainNetwork(l1Deployer) + const l2Network = await getChainNetwork(l2Deployer) setL1Network = l1Network setL2Network = l2Network } catch (err) { @@ -240,12 +240,12 @@ export const testSetup = async (): Promise<{ const { l1Network, l2Network } = JSON.parse( fs.readFileSync(localNetworkFile).toString() ) as { - l1Network: L1Network - l2Network: L2Network + l1Network: ParentChainNetwork + l2Network: ChainNetwork } addCustomNetwork({ - customL1Network: l1Network, - customL2Network: l2Network, + customParentChainNetwork: l1Network, + customChainNetwork: l2Network, }) setL1Network = l1Network setL2Network = l2Network diff --git a/src/index.ts b/src/index.ts index 99056afc27..6ad13a8124 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,12 +43,12 @@ export { L1ToL2MessageGasEstimator } from './lib/message/L1ToL2MessageGasEstimat export { argSerializerConstructor } from './lib/utils/byte_serialize_params' export { CallInput, MultiCaller } from './lib/utils/multicall' export { - L1Networks, - L2Networks, - L1Network, - L2Network, - getL1Network, - getL2Network, + ParentChainNetworks as L1Networks, + ChainNetworks as L2Networks, + ParentChainNetwork, + ChainNetwork as L2Network, + getParentChainNetwork as getL1Network, + getChainNetwork as getL2Network, addCustomNetwork, addDefaultLocalNetwork, } from './lib/dataEntities/networks' diff --git a/src/lib/assetBridger/assetBridger.ts b/src/lib/assetBridger/assetBridger.ts index ea3f72162b..8afc6f1ce9 100644 --- a/src/lib/assetBridger/assetBridger.ts +++ b/src/lib/assetBridger/assetBridger.ts @@ -20,7 +20,11 @@ import { ArbSdkError } from '../dataEntities/errors' import { L1ContractTransaction } from '../message/L1Transaction' import { L2ContractTransaction } from '../message/L2Transaction' -import { l1Networks, L1Network, L2Network } from '../dataEntities/networks' +import { + parentChainNetworks, + ParentChainNetwork, + ChainNetwork, +} from '../dataEntities/networks' import { SignerOrProvider, SignerProviderUtils, @@ -30,10 +34,10 @@ import { * Base for bridging assets from l1 to l2 and back */ export abstract class AssetBridger { - public readonly l1Network: L1Network + public readonly l1Network: ParentChainNetwork - public constructor(public readonly l2Network: L2Network) { - this.l1Network = l1Networks[l2Network.partnerChainID] + public constructor(public readonly l2Network: ChainNetwork) { + this.l1Network = parentChainNetworks[l2Network.partnerChainID] if (!this.l1Network) { throw new ArbSdkError( `Unknown l1 network chain id: ${l2Network.partnerChainID}` diff --git a/src/lib/assetBridger/erc20Bridger.ts b/src/lib/assetBridger/erc20Bridger.ts index d4883ac22f..c8f0fae5fc 100644 --- a/src/lib/assetBridger/erc20Bridger.ts +++ b/src/lib/assetBridger/erc20Bridger.ts @@ -45,7 +45,7 @@ import { L1ToL2MessageGasEstimator, } from '../message/L1ToL2MessageGasEstimator' import { SignerProviderUtils } from '../dataEntities/signerOrProvider' -import { L2Network, getL2Network } from '../dataEntities/networks' +import { ChainNetwork, getChainNetwork } from '../dataEntities/networks' import { ArbSdkError, MissingProviderArbSdkError } from '../dataEntities/errors' import { DISABLED_GATEWAY } from '../dataEntities/constants' import { EventFetcher } from '../utils/eventFetcher' @@ -178,7 +178,7 @@ export class Erc20Bridger extends AssetBridger< /** * Bridger for moving ERC20 tokens back and forth between L1 to L2 */ - public constructor(l2Network: L2Network) { + public constructor(l2Network: ChainNetwork) { super(l2Network) } @@ -188,7 +188,7 @@ export class Erc20Bridger extends AssetBridger< * @returns */ public static async fromProvider(l2Provider: Provider) { - return new Erc20Bridger(await getL2Network(l2Provider)) + return new Erc20Bridger(await getChainNetwork(l2Provider)) } /** diff --git a/src/lib/assetBridger/ethBridger.ts b/src/lib/assetBridger/ethBridger.ts index 4441f3d7f6..0373b1e11e 100644 --- a/src/lib/assetBridger/ethBridger.ts +++ b/src/lib/assetBridger/ethBridger.ts @@ -45,7 +45,7 @@ import { import { OmitTyped } from '../utils/types' import { SignerProviderUtils } from '../dataEntities/signerOrProvider' import { MissingProviderArbSdkError } from '../dataEntities/errors' -import { getL2Network } from '../dataEntities/networks' +import { getChainNetwork } from '../dataEntities/networks' export interface EthWithdrawParams { /** @@ -138,7 +138,7 @@ export class EthBridger extends AssetBridger< * @returns */ public static async fromProvider(l2Provider: Provider) { - return new EthBridger(await getL2Network(l2Provider)) + return new EthBridger(await getChainNetwork(l2Provider)) } /** diff --git a/src/lib/dataEntities/networks.ts b/src/lib/dataEntities/networks.ts index 8199dae1b8..158aef9ffe 100644 --- a/src/lib/dataEntities/networks.ts +++ b/src/lib/dataEntities/networks.ts @@ -21,13 +21,13 @@ import { ArbSdkError } from '../dataEntities/errors' import { SEVEN_DAYS_IN_SECONDS } from './constants' import { RollupAdminLogic__factory } from '../abi/factories/RollupAdminLogic__factory' -export interface L1Network extends Network { +export interface ParentChainNetwork extends Network { partnerChainIDs: number[] blockTime: number //seconds isArbitrum: false } -export interface L2Network extends Network { +export interface ChainNetwork extends Network { tokenBridge: TokenBridge ethBridge: EthBridge partnerChainID: number @@ -77,12 +77,12 @@ export interface EthBridge { } } -export interface L1Networks { - [id: string]: L1Network +export interface ParentChainNetworks { + [id: string]: ParentChainNetwork } -export interface L2Networks { - [id: string]: L2Network +export interface ChainNetworks { + [id: string]: ChainNetwork } const mainnetTokenBridge: TokenBridge = { @@ -114,7 +114,7 @@ const mainnetETHBridge: EthBridge = { }, } -export const l1Networks: L1Networks = { +export const parentChainNetworks: ParentChainNetworks = { 1: { chainID: 1, name: 'Mainnet', @@ -153,7 +153,7 @@ export const l1Networks: L1Networks = { }, } -export const l2Networks: L2Networks = { +export const chainNetworks: ChainNetworks = { 42161: { chainID: 42161, name: 'Arbitrum One', @@ -345,7 +345,7 @@ const getNetwork = async ( return chainId })() - const networks = layer === 1 ? l1Networks : l2Networks + const networks = layer === 1 ? parentChainNetworks : chainNetworks if (networks[chainID]) { return networks[chainID] } else { @@ -353,15 +353,15 @@ const getNetwork = async ( } } -export const getL1Network = ( +export const getParentChainNetwork = ( signerOrProviderOrChainID: SignerOrProvider | number -): Promise => { - return getNetwork(signerOrProviderOrChainID, 1) as Promise +): Promise => { + return getNetwork(signerOrProviderOrChainID, 1) as Promise } -export const getL2Network = ( +export const getChainNetwork = ( signerOrProviderOrChainID: SignerOrProvider | number -): Promise => { - return getNetwork(signerOrProviderOrChainID, 2) as Promise +): Promise => { + return getNetwork(signerOrProviderOrChainID, 2) as Promise } /** @@ -396,44 +396,52 @@ export const getEthBridgeInformation = async ( } export const addCustomNetwork = ({ - customL1Network, - customL2Network, + customParentChainNetwork, + customChainNetwork, }: { - customL1Network?: L1Network - customL2Network: L2Network + customParentChainNetwork?: ParentChainNetwork + customChainNetwork: ChainNetwork }): void => { - if (customL1Network) { - if (l1Networks[customL1Network.chainID]) { + if (customParentChainNetwork) { + if (parentChainNetworks[customParentChainNetwork.chainID]) { throw new ArbSdkError( - `Network ${customL1Network.chainID} already included` + `Network ${customParentChainNetwork.chainID} already included` ) - } else if (!customL1Network.isCustom) { + } else if (!customParentChainNetwork.isCustom) { throw new ArbSdkError( - `Custom network ${customL1Network.chainID} must have isCustom flag set to true` + `Custom network ${customParentChainNetwork.chainID} must have isCustom flag set to true` ) } else { - l1Networks[customL1Network.chainID] = customL1Network + parentChainNetworks[customParentChainNetwork.chainID] = + customParentChainNetwork } } - if (l2Networks[customL2Network.chainID]) - throw new ArbSdkError(`Network ${customL2Network.chainID} already included`) - else if (!customL2Network.isCustom) { + if (chainNetworks[customChainNetwork.chainID]) throw new ArbSdkError( - `Custom network ${customL2Network.chainID} must have isCustom flag set to true` + `Network ${customChainNetwork.chainID} already included` + ) + else if (!customChainNetwork.isCustom) { + throw new ArbSdkError( + `Custom network ${customChainNetwork.chainID} must have isCustom flag set to true` ) } - l2Networks[customL2Network.chainID] = customL2Network + chainNetworks[customChainNetwork.chainID] = customChainNetwork - const l1PartnerChain = l1Networks[customL2Network.partnerChainID] - if (!l1PartnerChain) + const parentChainPartnerChain = + parentChainNetworks[customChainNetwork.partnerChainID] + if (!parentChainPartnerChain) throw new ArbSdkError( - `Network ${customL2Network.chainID}'s partner network, ${customL2Network.partnerChainID}, not recognized` + `Network ${customChainNetwork.chainID}'s partner network, ${customChainNetwork.partnerChainID}, not recognized` ) - if (!l1PartnerChain.partnerChainIDs.includes(customL2Network.chainID)) { - l1PartnerChain.partnerChainIDs.push(customL2Network.chainID) + if ( + !parentChainPartnerChain.partnerChainIDs.includes( + customChainNetwork.chainID + ) + ) { + parentChainPartnerChain.partnerChainIDs.push(customChainNetwork.chainID) } } @@ -443,10 +451,10 @@ export const addCustomNetwork = ({ * @see {@link https://github.com/OffchainLabs/nitro} */ export const addDefaultLocalNetwork = (): { - l1Network: L1Network - l2Network: L2Network + parentChainNetwork: ParentChainNetwork + chainNetwork: ChainNetwork } => { - const defaultLocalL1Network: L1Network = { + const defaultLocalParentChainNetwork: ParentChainNetwork = { blockTime: 10, chainID: 1337, explorerUrl: '', @@ -456,7 +464,7 @@ export const addDefaultLocalNetwork = (): { isArbitrum: false, } - const defaultLocalL2Network: L2Network = { + const defaultLocalChainNetwork: ChainNetwork = { chainID: 412346, confirmPeriodBlocks: 20, ethBridge: { @@ -494,19 +502,19 @@ export const addDefaultLocalNetwork = (): { } addCustomNetwork({ - customL1Network: defaultLocalL1Network, - customL2Network: defaultLocalL2Network, + customParentChainNetwork: defaultLocalParentChainNetwork, + customChainNetwork: defaultLocalChainNetwork, }) return { - l1Network: defaultLocalL1Network, - l2Network: defaultLocalL2Network, + parentChainNetwork: defaultLocalParentChainNetwork, + chainNetwork: defaultLocalChainNetwork, } } -export const isL1Network = ( - network: L1Network | L2Network -): network is L1Network => { - if ((network as L1Network).partnerChainIDs) return true +export const isParentChainNetwork = ( + network: ParentChainNetwork | ChainNetwork +): network is ParentChainNetwork => { + if ((network as ParentChainNetwork).partnerChainIDs) return true else return false } diff --git a/src/lib/inbox/inbox.ts b/src/lib/inbox/inbox.ts index c6d28d74a0..ec3fbb21d2 100644 --- a/src/lib/inbox/inbox.ts +++ b/src/lib/inbox/inbox.ts @@ -29,8 +29,8 @@ import { IInbox__factory } from '../abi/factories/IInbox__factory' import { RequiredPick } from '../utils/types' import { MessageDeliveredEvent } from '../abi/Bridge' import { - l1Networks as parentChainNetworks, - L2Network as ChainNetwork, + parentChainNetworks as parentChainNetworks, + ChainNetwork as ChainNetwork, } from '../dataEntities/networks' import { SignerProviderUtils } from '../dataEntities/signerOrProvider' import { FetchedEvent, EventFetcher } from '../utils/eventFetcher' diff --git a/src/lib/message/L1ToL2Message.ts b/src/lib/message/L1ToL2Message.ts index 2339c77576..e0ef44d007 100644 --- a/src/lib/message/L1ToL2Message.ts +++ b/src/lib/message/L1ToL2Message.ts @@ -34,7 +34,7 @@ import { import { ArbSdkError } from '../dataEntities/errors' import { ethers, Overrides } from 'ethers' import { L2TransactionReceipt, RedeemTransaction } from './L2Transaction' -import { getL2Network } from '../../lib/dataEntities/networks' +import { getChainNetwork } from '../../lib/dataEntities/networks' import { RetryableMessageParams } from '../dataEntities/message' import { getTransactionReceipt, isDefined } from '../utils/lib' import { EventFetcher } from '../utils/eventFetcher' @@ -307,7 +307,7 @@ export class L1ToL2MessageReader extends L1ToL2Message { * @returns TransactionReceipt of the first successful redeem if exists, otherwise the current status of the message. */ public async getSuccessfulRedeem(): Promise { - const l2Network = await getL2Network(this.l2Provider) + const l2Network = await getChainNetwork(this.l2Provider) const eventFetcher = new EventFetcher(this.l2Provider) const creationReceipt = await this.getRetryableCreationReceipt() @@ -472,7 +472,7 @@ export class L1ToL2MessageReader extends L1ToL2Message { confirmations?: number, timeout?: number ): Promise { - const l2Network = await getL2Network(this.chainId) + const l2Network = await getChainNetwork(this.chainId) const chosenTimeout = isDefined(timeout) ? timeout @@ -846,7 +846,7 @@ export class EthDepositMessage { } public async wait(confirmations?: number, timeout?: number) { - const l2Network = await getL2Network(this.l2ChainId) + const l2Network = await getChainNetwork(this.l2ChainId) const chosenTimeout = isDefined(timeout) ? timeout diff --git a/src/lib/message/L1ToL2MessageCreator.ts b/src/lib/message/L1ToL2MessageCreator.ts index d930e2b22f..71f60da3fd 100644 --- a/src/lib/message/L1ToL2MessageCreator.ts +++ b/src/lib/message/L1ToL2MessageCreator.ts @@ -7,7 +7,7 @@ import { } from './L1ToL2MessageGasEstimator' import { L1ContractTransaction, L1TransactionReceipt } from './L1Transaction' import { Inbox__factory } from '../abi/factories/Inbox__factory' -import { getL2Network } from '../dataEntities/networks' +import { getChainNetwork } from '../dataEntities/networks' import { PayableOverrides } from '@ethersproject/contracts' import { SignerProviderUtils } from '../dataEntities/signerOrProvider' import { MissingProviderArbSdkError } from '../dataEntities/errors' @@ -96,7 +96,7 @@ export class L1ToL2MessageCreator { options ) - const l2Network = await getL2Network(l2Provider) + const l2Network = await getChainNetwork(l2Provider) const inboxInterface = Inbox__factory.createInterface() const functionData = inboxInterface.encodeFunctionData( 'createRetryableTicket', diff --git a/src/lib/message/L1ToL2MessageGasEstimator.ts b/src/lib/message/L1ToL2MessageGasEstimator.ts index 99c7686fc1..acd58a47fc 100644 --- a/src/lib/message/L1ToL2MessageGasEstimator.ts +++ b/src/lib/message/L1ToL2MessageGasEstimator.ts @@ -5,7 +5,7 @@ import { Inbox__factory } from '../abi/factories/Inbox__factory' import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory' import { NODE_INTERFACE_ADDRESS } from '../dataEntities/constants' import { ArbSdkError } from '../dataEntities/errors' -import { getL2Network } from '../dataEntities/networks' +import { getChainNetwork } from '../dataEntities/networks' import { RetryableData, RetryableDataTools, @@ -125,7 +125,7 @@ export class L1ToL2MessageGasEstimator { ): Promise { const defaultedOptions = this.applySubmissionPriceDefaults(options) - const network = await getL2Network(this.l2Provider) + const network = await getChainNetwork(this.l2Provider) const inbox = Inbox__factory.connect(network.ethBridge.inbox, l1Provider) return this.percentIncrease( diff --git a/src/lib/message/L1Transaction.ts b/src/lib/message/L1Transaction.ts index d2b79b3e4b..054428a8ad 100644 --- a/src/lib/message/L1Transaction.ts +++ b/src/lib/message/L1Transaction.ts @@ -46,7 +46,7 @@ import { MessageDeliveredEvent } from '../abi/Bridge' import { EventArgs, parseTypedLogs } from '../dataEntities/event' import { isDefined } from '../utils/lib' import { SubmitRetryableMessageDataParser } from './messageDataParser' -import { getL2Network } from '../dataEntities/networks' +import { getChainNetwork } from '../dataEntities/networks' export interface L1ContractTransaction< TReceipt extends L1TransactionReceipt = L1TransactionReceipt @@ -106,7 +106,7 @@ export class L1TransactionReceipt implements TransactionReceipt { l2SignerOrProvider: T ): Promise { const provider = SignerProviderUtils.getProviderOrThrow(l2SignerOrProvider) - const network = await getL2Network(provider) + const network = await getChainNetwork(provider) return this.blockNumber < network.nitroGenesisL1Block } @@ -207,7 +207,7 @@ export class L1TransactionReceipt implements TransactionReceipt { public async getL1ToL2MessagesClassic( l2Provider: Provider ): Promise { - const network = await getL2Network(l2Provider) + const network = await getChainNetwork(l2Provider) const chainID = network.chainID.toString() const isClassic = await this.isClassic(l2Provider) @@ -243,7 +243,7 @@ export class L1TransactionReceipt implements TransactionReceipt { l2SignerOrProvider: T ): Promise { const provider = SignerProviderUtils.getProviderOrThrow(l2SignerOrProvider) - const network = await getL2Network(provider) + const network = await getChainNetwork(provider) const chainID = network.chainID.toString() const isClassic = await this.isClassic(provider) diff --git a/src/lib/message/L2ToL1Message.ts b/src/lib/message/L2ToL1Message.ts index 1b3d1a4bce..94451924a9 100644 --- a/src/lib/message/L2ToL1Message.ts +++ b/src/lib/message/L2ToL1Message.ts @@ -35,7 +35,7 @@ import { import { isDefined } from '../utils/lib' import { EventArgs } from '../dataEntities/event' import { L2ToL1MessageStatus } from '../dataEntities/message' -import { getL2Network } from '../dataEntities/networks' +import { getChainNetwork } from '../dataEntities/networks' import { ArbSdkError } from '../dataEntities/errors' export type L2ToL1TransactionEvent = @@ -107,7 +107,7 @@ export class L2ToL1Message { hash?: BigNumber, indexInBatch?: BigNumber ): Promise<(L2ToL1TransactionEvent & { transactionHash: string })[]> { - const l2Network = await getL2Network(l2Provider) + const l2Network = await getChainNetwork(l2Provider) const inClassicRange = (blockTag: BlockTag, nitroGenBlock: number) => { if (typeof blockTag === 'string') { diff --git a/src/lib/message/L2ToL1MessageClassic.ts b/src/lib/message/L2ToL1MessageClassic.ts index 1edba7fc1d..5967a83545 100644 --- a/src/lib/message/L2ToL1MessageClassic.ts +++ b/src/lib/message/L2ToL1MessageClassic.ts @@ -40,7 +40,7 @@ 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 { getChainNetwork } from '../dataEntities/networks' export interface MessageBatchProofInfo { /** @@ -205,7 +205,7 @@ export class L2ToL1MessageReaderClassic extends L2ToL1MessageClassic { */ protected async getOutboxAddress(l2Provider: Provider, batchNumber: number) { if (!isDefined(this.outboxAddress)) { - const l2Network = await getL2Network(l2Provider) + const l2Network = await getChainNetwork(l2Provider) // find the outbox where the activation batch number of the next outbox // is greater than the supplied batch diff --git a/src/lib/message/L2ToL1MessageNitro.ts b/src/lib/message/L2ToL1MessageNitro.ts index 2ef4711d55..1c1239f259 100644 --- a/src/lib/message/L2ToL1MessageNitro.ts +++ b/src/lib/message/L2ToL1MessageNitro.ts @@ -39,7 +39,7 @@ import { SignerOrProvider, } from '../dataEntities/signerOrProvider' import { getBlockRangesForL1Block, isArbitrumChain, wait } from '../utils/lib' -import { getL2Network } from '../dataEntities/networks' +import { getChainNetwork } from '../dataEntities/networks' import { NodeCreatedEvent, RollupUserLogic } from '../abi/RollupUserLogic' import { ArbitrumProvider } from '../utils/arbProvider' import { ArbBlock } from '../dataEntities/rpc' @@ -146,7 +146,7 @@ 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) + const l2Network = await getChainNetwork(l2Provider) const outbox = Outbox__factory.connect( l2Network.ethBridge.outbox, this.l1Provider @@ -271,7 +271,7 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro { protected async getSendProps(l2Provider: Provider) { if (!this.sendRootConfirmed) { - const l2Network = await getL2Network(l2Provider) + const l2Network = await getChainNetwork(l2Provider) const rollup = RollupUserLogic__factory.connect( l2Network.ethBridge.rollup, @@ -349,7 +349,7 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro { public async getFirstExecutableBlock( l2Provider: Provider ): Promise { - const l2Network = await getL2Network(l2Provider) + const l2Network = await getChainNetwork(l2Provider) const rollup = RollupUserLogic__factory.connect( l2Network.ethBridge.rollup, @@ -466,7 +466,7 @@ export class L2ToL1MessageWriterNitro extends L2ToL1MessageReaderNitro { ) } const proof = await this.getOutboxProof(l2Provider) - const l2Network = await getL2Network(l2Provider) + const l2Network = await getChainNetwork(l2Provider) const outbox = Outbox__factory.connect( l2Network.ethBridge.outbox, this.l1Signer diff --git a/src/lib/utils/lib.ts b/src/lib/utils/lib.ts index c40341e1e6..133ac470f3 100644 --- a/src/lib/utils/lib.ts +++ b/src/lib/utils/lib.ts @@ -2,7 +2,7 @@ import { Provider } from '@ethersproject/abstract-provider' import { TransactionReceipt, JsonRpcProvider } from '@ethersproject/providers' import { ArbSdkError } from '../dataEntities/errors' import { ArbitrumProvider } from './arbProvider' -import { l2Networks } from '../dataEntities/networks' +import { chainNetworks } from '../dataEntities/networks' import { ArbSys__factory } from '../abi/factories/ArbSys__factory' import { ARB_SYS_ADDRESS } from '../dataEntities/constants' @@ -100,7 +100,7 @@ export async function getFirstBlockForL1Block({ const arbProvider = new ArbitrumProvider(provider) const currentArbBlock = await arbProvider.getBlockNumber() const arbitrumChainId = (await arbProvider.getNetwork()).chainId - const { nitroGenesisBlock } = l2Networks[arbitrumChainId] + const { nitroGenesisBlock } = chainNetworks[arbitrumChainId] async function getL1Block(forL2Block: number) { const { l1BlockNumber } = await arbProvider.getBlock(forL2Block) diff --git a/src/lib/utils/multicall.ts b/src/lib/utils/multicall.ts index 187b170c1f..16631031fc 100644 --- a/src/lib/utils/multicall.ts +++ b/src/lib/utils/multicall.ts @@ -24,11 +24,11 @@ import { Multicall2 } from '../abi/Multicall2' import { Multicall2__factory } from '../abi/factories/Multicall2__factory' import { ArbSdkError } from '../dataEntities/errors' import { - isL1Network, - L1Network, - l1Networks, - L2Network, - l2Networks, + isParentChainNetwork, + ParentChainNetwork, + parentChainNetworks, + ChainNetwork, + chainNetworks, } from '../dataEntities/networks' /** @@ -131,8 +131,10 @@ export class MultiCaller { */ public static async fromProvider(provider: Provider): Promise { const chainId = (await provider.getNetwork()).chainId - const l2Network = l2Networks[chainId] as L2Network | undefined - const l1Network = l1Networks[chainId] as L1Network | undefined + const l2Network = chainNetworks[chainId] as ChainNetwork | undefined + const l1Network = parentChainNetworks[chainId] as + | ParentChainNetwork + | undefined const network = l2Network || l1Network if (!network) { @@ -142,8 +144,8 @@ export class MultiCaller { } let multiCallAddr: string - if (isL1Network(network)) { - const firstL2 = l2Networks[network.partnerChainIDs[0]] + if (isParentChainNetwork(network)) { + const firstL2 = chainNetworks[network.partnerChainIDs[0]] if (!firstL2) throw new ArbSdkError( `No partner chain found l1 network: ${network.chainID} : partner chain ids ${network.partnerChainIDs}` diff --git a/tests/fork/inbox.test.ts b/tests/fork/inbox.test.ts index d91c238ee2..990e14cee7 100644 --- a/tests/fork/inbox.test.ts +++ b/tests/fork/inbox.test.ts @@ -30,7 +30,10 @@ import { InboxTools } from '../../src' import { ethers, network } from 'hardhat' import { hexZeroPad } from '@ethersproject/bytes' -import { L2Network, getL2Network } from '../../src/lib/dataEntities/networks' +import { + ChainNetwork as L2Network, + getChainNetwork as getL2Network, +} from '../../src/lib/dataEntities/networks' import { solidityKeccak256 } from 'ethers/lib/utils' import { ContractTransaction, Signer } from 'ethers' diff --git a/tests/integration/ethBridgeAddresses.test.ts b/tests/integration/ethBridgeAddresses.test.ts index 5d9db19974..ce3455bbbe 100644 --- a/tests/integration/ethBridgeAddresses.test.ts +++ b/tests/integration/ethBridgeAddresses.test.ts @@ -3,7 +3,7 @@ import { expect } from 'chai' import { EthBridge, getEthBridgeInformation, - getL2Network, + getChainNetwork as getL2Network, } from '../../src/lib/dataEntities/networks' import dotenv from 'dotenv' dotenv.config() diff --git a/tests/integration/sendL2msg.test.ts b/tests/integration/sendL2msg.test.ts index 6c1aeda558..6f7eee19d9 100644 --- a/tests/integration/sendL2msg.test.ts +++ b/tests/integration/sendL2msg.test.ts @@ -19,7 +19,10 @@ import { BigNumber, ethers, Signer } from 'ethers' import { InboxTools } from '../../src/lib/inbox/inbox' -import { getL2Network, L2Network } from '../../src/lib/dataEntities/networks' +import { + getChainNetwork as getL2Network, + ChainNetwork as L2Network, +} from '../../src/lib/dataEntities/networks' import { testSetup } from '../../scripts/testSetup' import { greeter } from './helper/greeter' import { expect } from 'chai' diff --git a/tests/integration/testHelpers.ts b/tests/integration/testHelpers.ts index a258c96daf..dc6453590f 100644 --- a/tests/integration/testHelpers.ts +++ b/tests/integration/testHelpers.ts @@ -31,7 +31,7 @@ import { L1ToL2MessageStatus, L2ToL1MessageStatus, } from '../../src' -import { L2Network } from '../../src/lib/dataEntities/networks' +import { ChainNetwork as L2Network } from '../../src/lib/dataEntities/networks' import { GasOverrides } from '../../src/lib/message/L1ToL2MessageGasEstimator' import { ArbSdkError } from '../../src/lib/dataEntities/errors' import { ERC20 } from '../../src/lib/abi/ERC20' diff --git a/tests/unit/l2toL1MessageEvents.test.ts b/tests/unit/l2toL1MessageEvents.test.ts index 8fff9e597b..2921c8813f 100644 --- a/tests/unit/l2toL1MessageEvents.test.ts +++ b/tests/unit/l2toL1MessageEvents.test.ts @@ -19,7 +19,7 @@ import { Logger, LogLevel } from '@ethersproject/logger' Logger.setLogLevel(LogLevel.ERROR) import { L2ToL1Message } from '../../src' -import { getL2Network } from '../../src/lib/dataEntities/networks' +import { getChainNetwork as getL2Network } from '../../src/lib/dataEntities/networks' import { providers } from 'ethers' import { anything, deepEqual, instance, mock, verify, when } from 'ts-mockito' diff --git a/tests/unit/multicall.test.ts b/tests/unit/multicall.test.ts index 8db7e1dd6a..f114bbfa0b 100644 --- a/tests/unit/multicall.test.ts +++ b/tests/unit/multicall.test.ts @@ -1,6 +1,6 @@ 'use strict' -import { getL2Network } from '../../src/lib/dataEntities/networks' +import { getChainNetwork as getL2Network } from '../../src/lib/dataEntities/networks' import { providers } from 'ethers' import { mock, when, anything, instance, deepEqual } from 'ts-mockito' import { expect } from 'chai' From 63f6b6b258ce69a5e07ad87ee0621608bf2e4490 Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Wed, 27 Sep 2023 10:26:10 -0400 Subject: [PATCH 03/14] chore: renames L1ToL2Message to parentChain/Chain --- src/index.ts | 10 +- src/lib/message/L1ToL2Message.ts | 390 +++++++++++++++++-------------- src/lib/message/L1Transaction.ts | 16 +- 3 files changed, 225 insertions(+), 191 deletions(-) diff --git a/src/index.ts b/src/index.ts index 6ad13a8124..f2f0964774 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,12 +32,12 @@ export { L1TransactionReceipt, } from './lib/message/L1Transaction' export { - L1ToL2MessageStatus, + ParentChainToChainMessageStatus as L1ToL2MessageStatus, EthDepositStatus, - L1ToL2Message, - L1ToL2MessageReader, - L1ToL2MessageReaderClassic, - L1ToL2MessageWriter, + ParentChainToChainMessage as L1ToL2Message, + ParentChainToChainMessageReader as L1ToL2MessageReader, + ParentChainToChainMessageReaderClassic as L1ToL2MessageReaderClassic, + ParentChainToChainMessageWriter as L1ToL2MessageWriter, } from './lib/message/L1ToL2Message' export { L1ToL2MessageGasEstimator } from './lib/message/L1ToL2MessageGasEstimator' export { argSerializerConstructor } from './lib/utils/byte_serialize_params' diff --git a/src/lib/message/L1ToL2Message.ts b/src/lib/message/L1ToL2Message.ts index e0ef44d007..164619b549 100644 --- a/src/lib/message/L1ToL2Message.ts +++ b/src/lib/message/L1ToL2Message.ts @@ -33,33 +33,36 @@ import { } from '../dataEntities/signerOrProvider' import { ArbSdkError } from '../dataEntities/errors' import { ethers, Overrides } from 'ethers' -import { L2TransactionReceipt, RedeemTransaction } from './L2Transaction' +import { + L2TransactionReceipt as ChainTransactionReceipt, + RedeemTransaction, +} from './L2Transaction' import { getChainNetwork } from '../../lib/dataEntities/networks' import { RetryableMessageParams } from '../dataEntities/message' import { getTransactionReceipt, isDefined } from '../utils/lib' import { EventFetcher } from '../utils/eventFetcher' import { ErrorCode, Logger } from '@ethersproject/logger' -export enum L1ToL2MessageStatus { +export enum ParentChainToChainMessageStatus { /** * 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 ParentChain 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_CHAIN = 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, /** @@ -70,11 +73,11 @@ export enum L1ToL2MessageStatus { export enum EthDepositStatus { /** - * 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 +90,19 @@ 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 ParentChainToChainMessageReaderOrWriter will be of type ParentChainToChainMessageReader. + * If T is of type Signer then ParentChainToChainMessageReaderOrWriter will be of + * type ParentChainToChainMessageWriter. */ -export type L1ToL2MessageReaderOrWriter = - T extends Provider ? L1ToL2MessageReader : L1ToL2MessageWriter +export type ParentChainToChainMessageReaderOrWriter< + T extends SignerOrProvider +> = T extends Provider + ? ParentChainToChainMessageReader + : ParentChainToChainMessageWriter -export abstract class L1ToL2Message { +export abstract class ParentChainToChainMessage { /** - * When messages are sent from L1 to L2 a retryable ticket is created on L2. + * When messages are sent from ParentChain to Chain a retryable ticket is created on Chain. * The retryableCreationId can be used to retrieve information about the success or failure of the * creation of the retryable ticket. */ @@ -105,29 +111,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 chainChainId + * @param fromAddress the aliased address that called the ParentChain inbox as emitted in the bridge event. * @param messageNumber - * @param l1BaseFee + * @param parentChainBaseFee * @param destAddress - * @param l2CallValue - * @param l1Value + * @param chainCallValue + * @param parentChainValue * @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 ParentChain inbox aliases this address if it is a ParentChain 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 ParentChain inbox aliases this address if it is a ParentChain 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, + chainChainId: number, fromAddress: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, destAddress: string, - l2CallValue: BigNumber, - l1Value: BigNumber, + chainCallValue: BigNumber, + parentChainValue: BigNumber, maxSubmissionFee: BigNumber, excessFeeRefundAddress: string, callValueRefundAddress: string, @@ -139,21 +145,21 @@ export abstract class L1ToL2Message { return ethers.utils.stripZeros(value.toHexString()) } - const chainId = BigNumber.from(l2ChainId) + const chainId = BigNumber.from(chainChainId) const msgNum = BigNumber.from(messageNumber) const fields: any[] = [ formatNumber(chainId), zeroPad(formatNumber(msgNum), 32), fromAddress, - formatNumber(l1BaseFee), + formatNumber(parentChainBaseFee), - formatNumber(l1Value), + formatNumber(parentChainValue), formatNumber(maxFeePerGas), formatNumber(gasLimit), // when destAddress is 0x0, arbos treat that as nil destAddress === ethers.constants.AddressZero ? '0x' : destAddress, - formatNumber(l2CallValue), + formatNumber(chainCallValue), callValueRefundAddress, formatNumber(maxSubmissionFee), excessFeeRefundAddress, @@ -170,36 +176,36 @@ export abstract class L1ToL2Message { } public static fromEventComponents( - l2SignerOrProvider: T, + chainSignerOrProvider: T, chainId: number, sender: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, messageData: RetryableMessageParams - ): L1ToL2MessageReaderOrWriter + ): ParentChainToChainMessageReaderOrWriter public static fromEventComponents( - l2SignerOrProvider: T, + chainSignerOrProvider: T, chainId: number, sender: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, messageData: RetryableMessageParams - ): L1ToL2MessageReader | L1ToL2MessageWriter { - return SignerProviderUtils.isSigner(l2SignerOrProvider) - ? new L1ToL2MessageWriter( - l2SignerOrProvider, + ): ParentChainToChainMessageReader | ParentChainToChainMessageWriter { + return SignerProviderUtils.isSigner(chainSignerOrProvider) + ? new ParentChainToChainMessageWriter( + chainSignerOrProvider, chainId, sender, messageNumber, - l1BaseFee, + parentChainBaseFee, messageData ) - : new L1ToL2MessageReader( - l2SignerOrProvider, + : new ParentChainToChainMessageReader( + chainSignerOrProvider, chainId, sender, messageNumber, - l1BaseFee, + parentChainBaseFee, messageData ) } @@ -208,55 +214,64 @@ export abstract class L1ToL2Message { public readonly chainId: number, public readonly sender: string, public readonly messageNumber: BigNumber, - public readonly l1BaseFee: BigNumber, + public readonly parentChainBaseFee: BigNumber, public readonly messageData: RetryableMessageParams ) { - this.retryableCreationId = L1ToL2Message.calculateSubmitRetryableId( - chainId, - sender, - messageNumber, - l1BaseFee, - messageData.destAddress, - messageData.l2CallValue, - messageData.l1Value, - messageData.maxSubmissionFee, - messageData.excessFeeRefundAddress, - messageData.callValueRefundAddress, - messageData.gasLimit, - messageData.maxFeePerGas, - messageData.data - ) + this.retryableCreationId = + ParentChainToChainMessage.calculateSubmitRetryableId( + chainId, + sender, + messageNumber, + parentChainBaseFee, + messageData.destAddress, + messageData.l2CallValue, + messageData.l1Value, + messageData.maxSubmissionFee, + messageData.excessFeeRefundAddress, + messageData.callValueRefundAddress, + messageData.gasLimit, + messageData.maxFeePerGas, + messageData.data + ) } } /** - * If the status is redeemed an l2TxReceipt is populated. - * For all other statuses l2TxReceipt is not populated + * If the status is redeemed an chainTxReceipt is populated. + * For all other statuses chainTxReceipt is not populated */ -export type L1ToL2MessageWaitResult = - | { status: L1ToL2MessageStatus.REDEEMED; l2TxReceipt: TransactionReceipt } - | { status: Exclude } +export type ParentChainToChainMessageWaitResult = + | { + status: ParentChainToChainMessageStatus.REDEEMED + chainTxReceipt: TransactionReceipt + } + | { + status: Exclude< + ParentChainToChainMessageStatus, + ParentChainToChainMessageStatus.REDEEMED + > + } export type EthDepositMessageWaitResult = { - l2TxReceipt: TransactionReceipt | null + chainTxReceipt: TransactionReceipt | null } -export class L1ToL2MessageReader extends L1ToL2Message { +export class ParentChainToChainMessageReader extends ParentChainToChainMessage { private retryableCreationReceipt: TransactionReceipt | undefined | null public constructor( - public readonly l2Provider: Provider, + public readonly chainProvider: Provider, chainId: number, sender: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, messageData: RetryableMessageParams ) { - super(chainId, sender, messageNumber, l1BaseFee, messageData) + super(chainId, sender, messageNumber, parentChainBaseFee, 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 +281,7 @@ export class L1ToL2MessageReader extends L1ToL2Message { ): Promise { if (!this.retryableCreationReceipt) { this.retryableCreationReceipt = await getTransactionReceipt( - this.l2Provider, + this.chainProvider, this.retryableCreationId, confirmations, timeout @@ -285,11 +300,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 ChainTransactionReceipt(creationReceipt) + const redeemEvents = chainReceipt.getRedeemScheduledEvents() if (redeemEvents.length === 1) { - return await this.l2Provider.getTransactionReceipt( + return await this.chainProvider.getTransactionReceipt( redeemEvents[0].retryTxHash ) } else if (redeemEvents.length > 1) { @@ -303,34 +318,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 { - const l2Network = await getChainNetwork(this.l2Provider) - const eventFetcher = new EventFetcher(this.l2Provider) + public async getSuccessfulRedeem(): Promise { + const chainNetwork = await getChainNetwork(this.chainProvider) + const eventFetcher = new EventFetcher(this.chainProvider) const creationReceipt = await this.getRetryableCreationReceipt() if (!isDefined(creationReceipt)) { // retryable was never created, or not created yet // therefore it cant have been redeemed or be expired - return { status: L1ToL2MessageStatus.NOT_YET_CREATED } + return { status: ParentChainToChainMessageStatus.NOT_YET_CREATED } } if (creationReceipt.status === 0) { - return { status: L1ToL2MessageStatus.CREATION_FAILED } + return { status: ParentChainToChainMessageStatus.CREATION_FAILED } } // check the auto redeem first to avoid doing costly log queries in the happy case const autoRedeem = await this.getAutoRedeemAttempt() if (autoRedeem && autoRedeem.status === 1) { - return { l2TxReceipt: autoRedeem, status: L1ToL2MessageStatus.REDEEMED } + return { + chainTxReceipt: autoRedeem, + status: ParentChainToChainMessageStatus.REDEEMED, + } } if (await this.retryableExists()) { // the retryable was created and still exists // therefore it cant have been redeemed or be expired - return { status: L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 } + return { + status: ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN, + } } // from this point on we know that the retryable was created but does not exist, @@ -340,10 +360,12 @@ export class L1ToL2MessageReader extends L1ToL2Message { // to do this we need to filter through the whole lifetime of the ticket looking // for relevant redeem scheduled events let increment = 1000 - let fromBlock = await this.l2Provider.getBlock(creationReceipt.blockNumber) - let timeout = fromBlock.timestamp + l2Network.retryableLifetimeSeconds + let fromBlock = await this.chainProvider.getBlock( + creationReceipt.blockNumber + ) + let timeout = fromBlock.timestamp + chainNetwork.retryableLifetimeSeconds const queriedRange: { from: number; to: number }[] = [] - const maxBlock = await this.l2Provider.getBlockNumber() + const maxBlock = await this.chainProvider.getBlockNumber() while (fromBlock.number < maxBlock) { const toBlockNumber = Math.min(fromBlock.number + increment, maxBlock) @@ -363,7 +385,7 @@ export class L1ToL2MessageReader extends L1ToL2Message { const successfulRedeem = ( await Promise.all( redeemEvents.map(e => - this.l2Provider.getTransactionReceipt(e.event.retryTxHash) + this.chainProvider.getTransactionReceipt(e.event.retryTxHash) ) ) ).filter(r => isDefined(r) && r.status === 1) @@ -374,11 +396,11 @@ export class L1ToL2MessageReader extends L1ToL2Message { ) if (successfulRedeem.length == 1) return { - l2TxReceipt: successfulRedeem[0], - status: L1ToL2MessageStatus.REDEEMED, + chainTxReceipt: successfulRedeem[0], + status: ParentChainToChainMessageStatus.REDEEMED, } - const toBlock = await this.l2Provider.getBlock(toBlockNumber) + const toBlock = await this.chainProvider.getBlock(toBlockNumber) if (toBlock.timestamp > timeout) { // Check for LifetimeExtended event while (queriedRange.length > 0) { @@ -418,7 +440,7 @@ export class L1ToL2MessageReader extends L1ToL2Message { // we know from earlier that the retryable no longer exists, so if we havent found the redemption // we know that it must have expired - return { status: L1ToL2MessageStatus.EXPIRED } + return { status: ParentChainToChainMessageStatus.EXPIRED } } /** @@ -432,12 +454,12 @@ export class L1ToL2MessageReader extends L1ToL2Message { private async retryableExists(): Promise { const currentTimestamp = BigNumber.from( - (await this.l2Provider.getBlock('latest')).timestamp + (await this.chainProvider.getBlock('latest')).timestamp ) try { const timeoutTimestamp = await this.getTimeout() // timeoutTimestamp returns the timestamp at which the retryable ticket expires - // it can also return revert if the ticket l2Tx does not exist + // it can also return revert if the ticket chainTx does not exist return currentTimestamp.lte(timeoutTimestamp) } catch (err) { if ( @@ -452,31 +474,31 @@ export class L1ToL2MessageReader extends L1ToL2Message { } } - public async status(): Promise { + public async status(): Promise { return (await this.getSuccessfulRedeem()).status } /** - * Wait for the retryable ticket to be created, for it to be redeemed, and for the l2Tx to be executed. - * Note: The terminal status of a transaction that only does an eth deposit is FUNDS_DEPOSITED_ON_L2 as - * no L2 transaction needs to be executed, however the terminal state of any other transaction is REDEEMED - * which represents that the retryable ticket has been redeemed and the L2 tx has been executed. + * Wait for the retryable ticket to be created, for it to be redeemed, and for the chainTx to be executed. + * Note: The terminal status of a transaction that only does an eth deposit is FUNDS_DEPOSITED_ON_CHAIN as + * no Chain transaction needs to be executed, however the terminal state of any other transaction is REDEEMED + * which represents that the retryable ticket has been redeemed and the Chain tx has been executed. * @param confirmations Amount of confirmations the retryable ticket and the auto redeem receipt should have * @param timeout Amount of time to wait for the retryable ticket to be created - * Defaults to 15 minutes, as by this time all transactions are expected to be included on L2. Throws on timeout. - * @returns The wait result contains a status, and optionally the l2TxReceipt. - * If the status is "REDEEMED" then a l2TxReceipt is also available on the result. - * If the status has any other value then l2TxReceipt is not populated. + * Defaults to 15 minutes, as by this time all transactions are expected to be included on Chain. Throws on timeout. + * @returns The wait result contains a status, and optionally the chainTxReceipt. + * If the status is "REDEEMED" then a chainTxReceipt is also available on the result. + * If the status has any other value then chainTxReceipt is not populated. */ public async waitForStatus( confirmations?: number, timeout?: number - ): Promise { - const l2Network = await getChainNetwork(this.chainId) + ): Promise { + const chainNetwork = await getChainNetwork(this.chainId) const chosenTimeout = isDefined(timeout) ? timeout - : l2Network.depositTimeout + : chainNetwork.depositTimeout // try to wait for the retryable ticket to be created const _retryableCreationReceipt = await this.getRetryableCreationReceipt( @@ -501,10 +523,10 @@ export class L1ToL2MessageReader extends L1ToL2Message { * The minimium lifetime of a retryable tx * @returns */ - public static async getLifetime(l2Provider: Provider): Promise { + public static async getLifetime(chainProvider: Provider): Promise { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - l2Provider + chainProvider ) return await arbRetryableTx.getLifetime() } @@ -516,37 +538,41 @@ export class L1ToL2MessageReader extends L1ToL2Message { public async getTimeout(): Promise { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Provider + this.chainProvider ) return await arbRetryableTx.getTimeout(this.retryableCreationId) } /** - * Address to which CallValue will be credited to on L2 if the retryable ticket times out or is cancelled. + * Address to which CallValue will be credited to on Chain if the retryable ticket times out or is cancelled. * The Beneficiary is also the address with the right to cancel a Retryable Ticket (if the ticket hasn’t been redeemed yet). * @returns */ public getBeneficiary(): Promise { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Provider + this.chainProvider ) return arbRetryableTx.getBeneficiary(this.retryableCreationId) } } -export class L1ToL2MessageReaderClassic { +export class ParentChainToChainMessageReaderClassic { private retryableCreationReceipt: TransactionReceipt | undefined | null public readonly messageNumber: BigNumber public readonly retryableCreationId: string public readonly autoRedeemId: string - public readonly l2TxHash: string - public readonly l2Provider: Provider + public readonly chainTxHash: string + public readonly chainProvider: Provider - constructor(l2Provider: Provider, chainId: number, messageNumber: BigNumber) { + constructor( + chainProvider: Provider, + chainId: number, + messageNumber: BigNumber + ) { const bitFlip = (num: BigNumber) => num.or(BigNumber.from(1).shl(255)) this.messageNumber = messageNumber - this.l2Provider = l2Provider + this.chainProvider = chainProvider this.retryableCreationId = keccak256( concat([ @@ -562,7 +588,7 @@ export class L1ToL2MessageReaderClassic { ]) ) - this.l2TxHash = keccak256( + this.chainTxHash = keccak256( concat([ zeroPad(this.retryableCreationId, 32), zeroPad(BigNumber.from(0).toHexString(), 32), @@ -570,11 +596,11 @@ export class L1ToL2MessageReaderClassic { ) } - private calculateL2DerivedHash(retryableCreationId: string): string { + private calculateChainDerivedHash(retryableCreationId: string): string { return keccak256( concat([ zeroPad(retryableCreationId, 32), - // BN 0 meaning L2 TX + // BN 0 meaning Chain TX zeroPad(BigNumber.from(0).toHexString(), 32), ]) ) @@ -582,7 +608,7 @@ export class L1ToL2MessageReaderClassic { /** * 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 */ @@ -592,7 +618,7 @@ export class L1ToL2MessageReaderClassic { ): Promise { if (!this.retryableCreationReceipt) { this.retryableCreationReceipt = await getTransactionReceipt( - this.l2Provider, + this.chainProvider, this.retryableCreationId, confirmations, timeout @@ -602,77 +628,81 @@ export class L1ToL2MessageReaderClassic { return this.retryableCreationReceipt || null } - public async status(): Promise { + public async status(): Promise { const creationReceipt = await this.getRetryableCreationReceipt() if (!isDefined(creationReceipt)) { - return L1ToL2MessageStatus.NOT_YET_CREATED + return ParentChainToChainMessageStatus.NOT_YET_CREATED } if (creationReceipt.status === 0) { - return L1ToL2MessageStatus.CREATION_FAILED + return ParentChainToChainMessageStatus.CREATION_FAILED } - const l2DerivedHash = this.calculateL2DerivedHash(this.retryableCreationId) - const l2TxReceipt = await this.l2Provider.getTransactionReceipt( - l2DerivedHash + const chainDerivedHash = this.calculateChainDerivedHash( + this.retryableCreationId + ) + const chainTxReceipt = await this.chainProvider.getTransactionReceipt( + chainDerivedHash ) - if (l2TxReceipt && l2TxReceipt.status === 1) { - return L1ToL2MessageStatus.REDEEMED + if (chainTxReceipt && chainTxReceipt.status === 1) { + return ParentChainToChainMessageStatus.REDEEMED } - return L1ToL2MessageStatus.EXPIRED + return ParentChainToChainMessageStatus.EXPIRED } } -export class L1ToL2MessageWriter extends L1ToL2MessageReader { +export class ParentChainToChainMessageWriter extends ParentChainToChainMessageReader { public constructor( - public readonly l2Signer: Signer, + public readonly chainSigner: Signer, chainId: number, sender: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, messageData: RetryableMessageParams ) { super( - l2Signer.provider!, + chainSigner.provider!, chainId, sender, messageNumber, - l1BaseFee, + parentChainBaseFee, messageData ) - if (!l2Signer.provider) + if (!chainSigner.provider) throw new ArbSdkError('Signer not connected to provider.') } /** * Manually redeem the retryable ticket. - * Throws if message status is not L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 + * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async redeem(overrides?: Overrides): Promise { const status = await this.status() - if (status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) { + if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Signer + this.chainSigner ) const redeemTx = await arbRetryableTx.redeem(this.retryableCreationId, { ...overrides, }) - return L2TransactionReceipt.toRedeemTransaction( - L2TransactionReceipt.monkeyPatchWait(redeemTx), - this.l2Provider + return ChainTransactionReceipt.toRedeemTransaction( + ChainTransactionReceipt.monkeyPatchWait(redeemTx), + this.chainProvider ) } else { throw new ArbSdkError( `Cannot redeem as retryable does not exist. Message status: ${ - L1ToL2MessageStatus[status] + ParentChainToChainMessageStatus[status] } must be: ${ - L1ToL2MessageStatus[L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2] + ParentChainToChainMessageStatus[ + ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ] }.` ) } @@ -680,22 +710,24 @@ export class L1ToL2MessageWriter extends L1ToL2MessageReader { /** * Cancel the retryable ticket. - * Throws if message status is not L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 + * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async cancel(overrides?: Overrides): Promise { const status = await this.status() - if (status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) { + if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Signer + this.chainSigner ) return await arbRetryableTx.cancel(this.retryableCreationId, overrides) } else { throw new ArbSdkError( `Cannot cancel as retryable does not exist. Message status: ${ - L1ToL2MessageStatus[status] + ParentChainToChainMessageStatus[status] } must be: ${ - L1ToL2MessageStatus[L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2] + ParentChainToChainMessageStatus[ + ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ] }.` ) } @@ -703,22 +735,24 @@ export class L1ToL2MessageWriter extends L1ToL2MessageReader { /** * Increase the timeout of a retryable ticket. - * Throws if message status is not L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 + * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async keepAlive(overrides?: Overrides): Promise { const status = await this.status() - if (status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) { + if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Signer + this.chainSigner ) return await arbRetryableTx.keepalive(this.retryableCreationId, overrides) } else { throw new ArbSdkError( `Cannot keep alive as retryable does not exist. Message status: ${ - L1ToL2MessageStatus[status] + ParentChainToChainMessageStatus[status] } must be: ${ - L1ToL2MessageStatus[L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2] + ParentChainToChainMessageStatus[ + ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ] }.` ) } @@ -726,14 +760,14 @@ export class L1ToL2MessageWriter extends L1ToL2MessageReader { } /** - * A message for Eth deposits from L1 to L2 + * A message for Eth deposits from ParentChain to Chain */ export class EthDepositMessage { - public readonly l2DepositTxHash: string - private l2DepositTxReceipt: TransactionReceipt | undefined | null + public readonly chainDepositTxHash: string + private chainDepositTxReceipt: TransactionReceipt | undefined | null public static calculateDepositTxId( - l2ChainId: number, + chainChainId: number, messageNumber: BigNumber, fromAddress: string, toAddress: string, @@ -743,7 +777,7 @@ export class EthDepositMessage { return ethers.utils.stripZeros(numberVal.toHexString()) } - const chainId = BigNumber.from(l2ChainId) + const chainId = BigNumber.from(chainChainId) const msgNum = BigNumber.from(messageNumber) // https://github.com/OffchainLabs/go-ethereum/blob/07e017aa73e32be92aadb52fa327c552e1b7b118/core/types/arb_types.go#L302-L308 @@ -774,7 +808,7 @@ export class EthDepositMessage { to: string value: BigNumber } { - // https://github.com/OffchainLabs/nitro/blob/aa84e899cbc902bf6da753b1d66668a1def2c106/contracts/src/bridge/Inbox.sol#L242 + // https://github.com/OffchainLabs/nitro/blob/aa84e899cbc902bf6da753b1d66668a1def2c106/contracts/src/bridge/Inbox.sol#Chain42 // ethers.defaultAbiCoder doesnt decode packed args, so we do a hardcoded parsing const addressEnd = 2 + 20 * 2 const to = getAddress('0x' + eventData.substring(2, addressEnd)) @@ -785,25 +819,25 @@ export class EthDepositMessage { /** * Create an EthDepositMessage from data emitted in event when calling ethDeposit on Inbox.sol - * @param l2Provider + * @param chainProvider * @param messageNumber The message number in the Inbox.InboxMessageDelivered event * @param senderAddr The sender address from Bridge.MessageDelivered event * @param inboxMessageEventData The data field from the Inbox.InboxMessageDelivered event * @returns */ public static async fromEventComponents( - l2Provider: Provider, + chainProvider: Provider, messageNumber: BigNumber, senderAddr: string, inboxMessageEventData: string ) { - const chainId = (await l2Provider.getNetwork()).chainId + const chainId = (await chainProvider.getNetwork()).chainId const { to, value } = EthDepositMessage.parseEthDepositData( inboxMessageEventData ) return new EthDepositMessage( - l2Provider, + chainProvider, chainId, messageNumber, senderAddr, @@ -814,22 +848,22 @@ export class EthDepositMessage { /** * - * @param l2Provider - * @param l2ChainId + * @param chainProvider + * @param chainChainId * @param messageNumber - * @param to Recipient address of the ETH on L2 + * @param to Recipient address of the ETH on Chain * @param value */ constructor( - private readonly l2Provider: Provider, - public readonly l2ChainId: number, + private readonly chainProvider: Provider, + public readonly chainChainId: number, public readonly messageNumber: BigNumber, public readonly from: string, public readonly to: string, public readonly value: BigNumber ) { - this.l2DepositTxHash = EthDepositMessage.calculateDepositTxId( - l2ChainId, + this.chainDepositTxHash = EthDepositMessage.calculateDepositTxId( + chainChainId, messageNumber, from, to, @@ -838,29 +872,29 @@ export class EthDepositMessage { } public async status(): Promise { - const receipt = await this.l2Provider.getTransactionReceipt( - this.l2DepositTxHash + const receipt = await this.chainProvider.getTransactionReceipt( + this.chainDepositTxHash ) if (receipt === null) return EthDepositStatus.PENDING else return EthDepositStatus.DEPOSITED } public async wait(confirmations?: number, timeout?: number) { - const l2Network = await getChainNetwork(this.l2ChainId) + const chainNetwork = await getChainNetwork(this.chainChainId) const chosenTimeout = isDefined(timeout) ? timeout - : l2Network.depositTimeout + : chainNetwork.depositTimeout - if (!this.l2DepositTxReceipt) { - this.l2DepositTxReceipt = await getTransactionReceipt( - this.l2Provider, - this.l2DepositTxHash, + if (!this.chainDepositTxReceipt) { + this.chainDepositTxReceipt = await getTransactionReceipt( + this.chainProvider, + this.chainDepositTxHash, confirmations, chosenTimeout ) } - return this.l2DepositTxReceipt || null + return this.chainDepositTxReceipt || null } } diff --git a/src/lib/message/L1Transaction.ts b/src/lib/message/L1Transaction.ts index 054428a8ad..2f8d5d4ae0 100644 --- a/src/lib/message/L1Transaction.ts +++ b/src/lib/message/L1Transaction.ts @@ -21,13 +21,13 @@ import { Log, Provider } from '@ethersproject/abstract-provider' import { ContractTransaction } from '@ethersproject/contracts' import { BigNumber } from '@ethersproject/bignumber' import { - L1ToL2Message, - L1ToL2MessageReaderOrWriter, - L1ToL2MessageReader, - L1ToL2MessageReaderClassic, - L1ToL2MessageWriter, - L1ToL2MessageStatus, - L1ToL2MessageWaitResult, + ParentChainToChainMessage as L1ToL2Message, + ParentChainToChainMessageReaderOrWriter as L1ToL2MessageReaderOrWriter, + ParentChainToChainMessageReader as L1ToL2MessageReader, + ParentChainToChainMessageReaderClassic as L1ToL2MessageReaderClassic, + ParentChainToChainMessageWriter as L1ToL2MessageWriter, + ParentChainToChainMessageStatus as L1ToL2MessageStatus, + ParentChainToChainMessageWaitResult as L1ToL2MessageWaitResult, EthDepositMessage, EthDepositMessageWaitResult, } from './L1ToL2Message' @@ -372,7 +372,7 @@ export class L1EthDepositTransactionReceipt extends L1TransactionReceipt { return { complete: isDefined(res), - l2TxReceipt: res, + chainTxReceipt: res, message, } } From b338516f08665bc9b8d56428a6413797530f4d89 Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Wed, 27 Sep 2023 10:55:10 -0400 Subject: [PATCH 04/14] chore: renames L2ToL1Message to chain/parentChain --- src/index.ts | 6 +- src/lib/message/L2ToL1Message.ts | 186 +++++++++++++++++-------------- src/lib/message/L2Transaction.ts | 10 +- 3 files changed, 110 insertions(+), 92 deletions(-) diff --git a/src/index.ts b/src/index.ts index f2f0964774..fde6731572 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,9 +23,9 @@ export { L2ContractTransaction, } from './lib/message/L2Transaction' export { - L2ToL1Message, - L2ToL1MessageWriter, - L2ToL1MessageReader, + ChainToParentChainMessage as L2ToL1Message, + ChainToParentChainMessageWriter as L2ToL1MessageWriter, + ChainToParentChainMessageReader as L2ToL1MessageReader, } from './lib/message/L2ToL1Message' export { L1ContractTransaction, diff --git a/src/lib/message/L2ToL1Message.ts b/src/lib/message/L2ToL1Message.ts index 94451924a9..024d9b6b6e 100644 --- a/src/lib/message/L2ToL1Message.ts +++ b/src/lib/message/L2ToL1Message.ts @@ -29,85 +29,94 @@ import { import * as classic from './L2ToL1MessageClassic' import * as nitro from './L2ToL1MessageNitro' import { - L2ToL1TransactionEvent as ClassicL2ToL1TransactionEvent, - L2ToL1TxEvent as NitroL2ToL1TransactionEvent, + L2ToL1TransactionEvent as ClassicChainToParentChainTransactionEvent, + L2ToL1TxEvent as NitroChainToParentChainTransactionEvent, } from '../abi/ArbSys' import { isDefined } from '../utils/lib' import { EventArgs } from '../dataEntities/event' -import { L2ToL1MessageStatus } from '../dataEntities/message' +import { L2ToL1MessageStatus as ChainToParentChainMessageStatus } from '../dataEntities/message' import { getChainNetwork } from '../dataEntities/networks' import { ArbSdkError } from '../dataEntities/errors' -export type L2ToL1TransactionEvent = - | EventArgs - | EventArgs +export type ChainToParentChainTransactionEvent = + | 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. + * then ChainToParentChainMessageReaderOrWriter will be of type ChainToParentChainMessageReader. + * If T is of type Signer then ChainToParentChainMessageReaderOrWriter will be of + * type ChainToParentChainMessageWriter. */ -export type L2ToL1MessageReaderOrWriter = - T extends Provider ? L2ToL1MessageReader : L2ToL1MessageWriter +export type ChainToParentChainMessageReaderOrWriter< + T extends SignerOrProvider +> = T extends Provider + ? ChainToParentChainMessageReader + : ChainToParentChainMessageWriter /** - * Base functionality for L2->L1 messages + * Base functionality for Chain->ParentChain messages */ -export class L2ToL1Message { +export class ChainToParentChainMessage { protected isClassic( - e: L2ToL1TransactionEvent - ): e is EventArgs { + e: ChainToParentChainTransactionEvent + ): e is EventArgs { return isDefined( - (e as EventArgs).indexInBatch + (e as EventArgs).indexInBatch ) } /** - * Instantiates a new `L2ToL1MessageWriter` or `L2ToL1MessageReader` object. + * Instantiates a new `ChainToParentChainMessageWriter` or `ChainToParentChainMessageReader` 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. + * @param {SignerOrProvider} ParentChainSignerOrProvider Signer or provider to be used for executing or reading the Chain-to-ParentChain message. + * @param {ChainToParentChainTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. + * @param {Provider} [ParentChainProvider] Optional. Used to override the Provider which is attached to `ParentChainSignerOrProvider` 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 + ParentChainSignerOrProvider: T, + event: ChainToParentChainTransactionEvent, + ParentChainProvider?: Provider + ): ChainToParentChainMessageReaderOrWriter static fromEvent( - l1SignerOrProvider: T, - event: L2ToL1TransactionEvent, - l1Provider?: Provider - ): L2ToL1MessageReader | L2ToL1MessageWriter { - return SignerProviderUtils.isSigner(l1SignerOrProvider) - ? new L2ToL1MessageWriter(l1SignerOrProvider, event, l1Provider) - : new L2ToL1MessageReader(l1SignerOrProvider, event) + ParentChainSignerOrProvider: T, + event: ChainToParentChainTransactionEvent, + ParentChainProvider?: Provider + ): ChainToParentChainMessageReader | ChainToParentChainMessageWriter { + return SignerProviderUtils.isSigner(ParentChainSignerOrProvider) + ? new ChainToParentChainMessageWriter( + ParentChainSignerOrProvider, + event, + ParentChainProvider + ) + : new ChainToParentChainMessageReader(ParentChainSignerOrProvider, event) } /** - * Get event logs for L2ToL1 transactions. - * @param l2Provider + * Get event logs for ChainToParentChain transactions. + * @param ChainProvider * @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 destination The ParentChain destination of the ChainToParentChain 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, + public static async getChainToParentChainEvents( + ChainProvider: Provider, filter: { fromBlock: BlockTag; toBlock: BlockTag }, position?: BigNumber, destination?: string, hash?: BigNumber, indexInBatch?: BigNumber - ): Promise<(L2ToL1TransactionEvent & { transactionHash: string })[]> { - const l2Network = await getChainNetwork(l2Provider) + ): Promise< + (ChainToParentChainTransactionEvent & { transactionHash: string })[] + > { + const ChainNetwork = await getChainNetwork(ChainProvider) const inClassicRange = (blockTag: BlockTag, nitroGenBlock: number) => { if (typeof blockTag === 'string') { @@ -150,14 +159,17 @@ export class L2ToL1Message { // only fetch nitro events after the genesis block const classicFilter = { - fromBlock: inClassicRange(filter.fromBlock, l2Network.nitroGenesisBlock), - toBlock: inClassicRange(filter.toBlock, l2Network.nitroGenesisBlock), + fromBlock: inClassicRange( + filter.fromBlock, + ChainNetwork.nitroGenesisBlock + ), + toBlock: inClassicRange(filter.toBlock, ChainNetwork.nitroGenesisBlock), } const logQueries = [] if (classicFilter.fromBlock !== classicFilter.toBlock) { logQueries.push( classic.L2ToL1MessageClassic.getL2ToL1Events( - l2Provider, + ChainProvider, classicFilter, position, destination, @@ -168,13 +180,13 @@ export class L2ToL1Message { } const nitroFilter = { - fromBlock: inNitroRange(filter.fromBlock, l2Network.nitroGenesisBlock), - toBlock: inNitroRange(filter.toBlock, l2Network.nitroGenesisBlock), + fromBlock: inNitroRange(filter.fromBlock, ChainNetwork.nitroGenesisBlock), + toBlock: inNitroRange(filter.toBlock, ChainNetwork.nitroGenesisBlock), } if (nitroFilter.fromBlock !== nitroFilter.toBlock) { logQueries.push( nitro.L2ToL1MessageNitro.getL2ToL1Events( - l2Provider, + ChainProvider, nitroFilter, position, destination, @@ -188,34 +200,37 @@ export class L2ToL1Message { } /** - * Provides read-only access for l2-to-l1-messages + * Provides read-only access for Chain-to-ParentChain-messages */ -export class L2ToL1MessageReader extends L2ToL1Message { +export class ChainToParentChainMessageReader extends ChainToParentChainMessage { private readonly classicReader?: classic.L2ToL1MessageReaderClassic private readonly nitroReader?: nitro.L2ToL1MessageReaderNitro constructor( - protected readonly l1Provider: Provider, - event: L2ToL1TransactionEvent + protected readonly ParentChainProvider: Provider, + event: ChainToParentChainTransactionEvent ) { super() if (this.isClassic(event)) { this.classicReader = new classic.L2ToL1MessageReaderClassic( - l1Provider, + ParentChainProvider, event.batchNumber, event.indexInBatch ) } else { - this.nitroReader = new nitro.L2ToL1MessageReaderNitro(l1Provider, event) + this.nitroReader = new nitro.L2ToL1MessageReaderNitro( + ParentChainProvider, + event + ) } } public async getOutboxProof( - l2Provider: Provider + ChainProvider: Provider ): Promise { if (this.nitroReader) { - return await this.nitroReader.getOutboxProof(l2Provider) - } else return await this.classicReader!.tryGetProof(l2Provider) + return await this.nitroReader.getOutboxProof(ChainProvider) + } else return await this.classicReader!.tryGetProof(ChainProvider) } /** @@ -223,10 +238,12 @@ export class L2ToL1MessageReader extends L2ToL1Message { * 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) + public async status( + ChainProvider: Provider + ): Promise { + // can we create an ChainToParentChainmessage here, we need to - the constructor is what we need + if (this.nitroReader) return await this.nitroReader.status(ChainProvider) + else return await this.classicReader!.status(ChainProvider) } /** @@ -237,81 +254,82 @@ export class L2ToL1MessageReader extends L2ToL1Message { * @returns */ public async waitUntilReadyToExecute( - l2Provider: Provider, + ChainProvider: Provider, retryDelay = 500 ): Promise { if (this.nitroReader) - return this.nitroReader.waitUntilReadyToExecute(l2Provider, retryDelay) + return this.nitroReader.waitUntilReadyToExecute(ChainProvider, retryDelay) else return this.classicReader!.waitUntilOutboxEntryCreated( - l2Provider, + ChainProvider, retryDelay ) } /** - * Estimates the L1 block number in which this L2 to L1 tx will be available for execution. + * Estimates the ParentChain block number in which this Chain to ParentChain 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 + * @param ChainProvider + * @returns expected ParentChain block number where the Chain to ParentChain message will be executable. Returns null if the message can or already has been executed */ public async getFirstExecutableBlock( - l2Provider: Provider + ChainProvider: Provider ): Promise { if (this.nitroReader) - return this.nitroReader.getFirstExecutableBlock(l2Provider) - else return this.classicReader!.getFirstExecutableBlock(l2Provider) + return this.nitroReader.getFirstExecutableBlock(ChainProvider) + else return this.classicReader!.getFirstExecutableBlock(ChainProvider) } } /** - * Provides read and write access for l2-to-l1-messages + * Provides read and write access for Chain-to-ParentChain-messages */ -export class L2ToL1MessageWriter extends L2ToL1MessageReader { +export class ChainToParentChainMessageWriter extends ChainToParentChainMessageReader { private readonly classicWriter?: classic.L2ToL1MessageWriterClassic private readonly nitroWriter?: nitro.L2ToL1MessageWriterNitro /** - * Instantiates a new `L2ToL1MessageWriter` object. + * Instantiates a new `ChainToParentChainMessageWriter` 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. + * @param {Signer} ParentChainSigner The signer to be used for executing the Chain-to-ParentChain message. + * @param {ChainToParentChainTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. + * @param {Provider} [ParentChainProvider] Optional. Used to override the Provider which is attached to `ParentChainSigner` 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 + ParentChainSigner: Signer, + event: ChainToParentChainTransactionEvent, + ParentChainProvider?: Provider ) { - super(l1Provider ?? l1Signer.provider!, event) + super(ParentChainProvider ?? ParentChainSigner.provider!, event) if (this.isClassic(event)) { this.classicWriter = new classic.L2ToL1MessageWriterClassic( - l1Signer, + ParentChainSigner, event.batchNumber, event.indexInBatch, - l1Provider + ParentChainProvider ) } else { this.nitroWriter = new nitro.L2ToL1MessageWriterNitro( - l1Signer, + ParentChainSigner, event, - l1Provider + ParentChainProvider ) } } /** - * Executes the L2ToL1Message on L1. + * Executes the ChainToParentChainMessage on ParentChain. * 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, + ChainProvider: Provider, overrides?: Overrides ): Promise { - if (this.nitroWriter) return this.nitroWriter.execute(l2Provider, overrides) - else return await this.classicWriter!.execute(l2Provider, overrides) + if (this.nitroWriter) + return this.nitroWriter.execute(ChainProvider, overrides) + else return await this.classicWriter!.execute(ChainProvider, overrides) } } diff --git a/src/lib/message/L2Transaction.ts b/src/lib/message/L2Transaction.ts index 51ac0fa7b2..9eabd3a7af 100644 --- a/src/lib/message/L2Transaction.ts +++ b/src/lib/message/L2Transaction.ts @@ -25,11 +25,11 @@ import { SignerOrProvider, } from '../dataEntities/signerOrProvider' import { - L2ToL1MessageReader, - L2ToL1MessageReaderOrWriter, - L2ToL1Message, - L2ToL1MessageWriter, - L2ToL1TransactionEvent, + ChainToParentChainMessageReader as L2ToL1MessageReader, + ChainToParentChainMessageReaderOrWriter as L2ToL1MessageReaderOrWriter, + ChainToParentChainMessage as L2ToL1Message, + ChainToParentChainMessageWriter as L2ToL1MessageWriter, + ChainToParentChainTransactionEvent as L2ToL1TransactionEvent, } from './L2ToL1Message' import { ArbSys__factory } from '../abi/factories/ArbSys__factory' import { ArbRetryableTx__factory } from '../abi/factories/ArbRetryableTx__factory' From 42ee74d382eb9ae45dbcafd3d68dbe30ff2c512d Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Wed, 27 Sep 2023 10:26:10 -0400 Subject: [PATCH 05/14] chore: renames L1ToL2Message to parentChain/Chain --- src/index.ts | 10 +- src/lib/message/L1ToL2Message.ts | 390 ++++++++++++++----------- src/lib/message/L1Transaction.ts | 16 +- tests/unit/l1toL2MessageEvents.test.ts | 4 +- 4 files changed, 227 insertions(+), 193 deletions(-) diff --git a/src/index.ts b/src/index.ts index 6ad13a8124..f2f0964774 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,12 +32,12 @@ export { L1TransactionReceipt, } from './lib/message/L1Transaction' export { - L1ToL2MessageStatus, + ParentChainToChainMessageStatus as L1ToL2MessageStatus, EthDepositStatus, - L1ToL2Message, - L1ToL2MessageReader, - L1ToL2MessageReaderClassic, - L1ToL2MessageWriter, + ParentChainToChainMessage as L1ToL2Message, + ParentChainToChainMessageReader as L1ToL2MessageReader, + ParentChainToChainMessageReaderClassic as L1ToL2MessageReaderClassic, + ParentChainToChainMessageWriter as L1ToL2MessageWriter, } from './lib/message/L1ToL2Message' export { L1ToL2MessageGasEstimator } from './lib/message/L1ToL2MessageGasEstimator' export { argSerializerConstructor } from './lib/utils/byte_serialize_params' diff --git a/src/lib/message/L1ToL2Message.ts b/src/lib/message/L1ToL2Message.ts index e0ef44d007..164619b549 100644 --- a/src/lib/message/L1ToL2Message.ts +++ b/src/lib/message/L1ToL2Message.ts @@ -33,33 +33,36 @@ import { } from '../dataEntities/signerOrProvider' import { ArbSdkError } from '../dataEntities/errors' import { ethers, Overrides } from 'ethers' -import { L2TransactionReceipt, RedeemTransaction } from './L2Transaction' +import { + L2TransactionReceipt as ChainTransactionReceipt, + RedeemTransaction, +} from './L2Transaction' import { getChainNetwork } from '../../lib/dataEntities/networks' import { RetryableMessageParams } from '../dataEntities/message' import { getTransactionReceipt, isDefined } from '../utils/lib' import { EventFetcher } from '../utils/eventFetcher' import { ErrorCode, Logger } from '@ethersproject/logger' -export enum L1ToL2MessageStatus { +export enum ParentChainToChainMessageStatus { /** * 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 ParentChain 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_CHAIN = 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, /** @@ -70,11 +73,11 @@ export enum L1ToL2MessageStatus { export enum EthDepositStatus { /** - * 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 +90,19 @@ 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 ParentChainToChainMessageReaderOrWriter will be of type ParentChainToChainMessageReader. + * If T is of type Signer then ParentChainToChainMessageReaderOrWriter will be of + * type ParentChainToChainMessageWriter. */ -export type L1ToL2MessageReaderOrWriter = - T extends Provider ? L1ToL2MessageReader : L1ToL2MessageWriter +export type ParentChainToChainMessageReaderOrWriter< + T extends SignerOrProvider +> = T extends Provider + ? ParentChainToChainMessageReader + : ParentChainToChainMessageWriter -export abstract class L1ToL2Message { +export abstract class ParentChainToChainMessage { /** - * When messages are sent from L1 to L2 a retryable ticket is created on L2. + * When messages are sent from ParentChain to Chain a retryable ticket is created on Chain. * The retryableCreationId can be used to retrieve information about the success or failure of the * creation of the retryable ticket. */ @@ -105,29 +111,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 chainChainId + * @param fromAddress the aliased address that called the ParentChain inbox as emitted in the bridge event. * @param messageNumber - * @param l1BaseFee + * @param parentChainBaseFee * @param destAddress - * @param l2CallValue - * @param l1Value + * @param chainCallValue + * @param parentChainValue * @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 ParentChain inbox aliases this address if it is a ParentChain 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 ParentChain inbox aliases this address if it is a ParentChain 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, + chainChainId: number, fromAddress: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, destAddress: string, - l2CallValue: BigNumber, - l1Value: BigNumber, + chainCallValue: BigNumber, + parentChainValue: BigNumber, maxSubmissionFee: BigNumber, excessFeeRefundAddress: string, callValueRefundAddress: string, @@ -139,21 +145,21 @@ export abstract class L1ToL2Message { return ethers.utils.stripZeros(value.toHexString()) } - const chainId = BigNumber.from(l2ChainId) + const chainId = BigNumber.from(chainChainId) const msgNum = BigNumber.from(messageNumber) const fields: any[] = [ formatNumber(chainId), zeroPad(formatNumber(msgNum), 32), fromAddress, - formatNumber(l1BaseFee), + formatNumber(parentChainBaseFee), - formatNumber(l1Value), + formatNumber(parentChainValue), formatNumber(maxFeePerGas), formatNumber(gasLimit), // when destAddress is 0x0, arbos treat that as nil destAddress === ethers.constants.AddressZero ? '0x' : destAddress, - formatNumber(l2CallValue), + formatNumber(chainCallValue), callValueRefundAddress, formatNumber(maxSubmissionFee), excessFeeRefundAddress, @@ -170,36 +176,36 @@ export abstract class L1ToL2Message { } public static fromEventComponents( - l2SignerOrProvider: T, + chainSignerOrProvider: T, chainId: number, sender: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, messageData: RetryableMessageParams - ): L1ToL2MessageReaderOrWriter + ): ParentChainToChainMessageReaderOrWriter public static fromEventComponents( - l2SignerOrProvider: T, + chainSignerOrProvider: T, chainId: number, sender: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, messageData: RetryableMessageParams - ): L1ToL2MessageReader | L1ToL2MessageWriter { - return SignerProviderUtils.isSigner(l2SignerOrProvider) - ? new L1ToL2MessageWriter( - l2SignerOrProvider, + ): ParentChainToChainMessageReader | ParentChainToChainMessageWriter { + return SignerProviderUtils.isSigner(chainSignerOrProvider) + ? new ParentChainToChainMessageWriter( + chainSignerOrProvider, chainId, sender, messageNumber, - l1BaseFee, + parentChainBaseFee, messageData ) - : new L1ToL2MessageReader( - l2SignerOrProvider, + : new ParentChainToChainMessageReader( + chainSignerOrProvider, chainId, sender, messageNumber, - l1BaseFee, + parentChainBaseFee, messageData ) } @@ -208,55 +214,64 @@ export abstract class L1ToL2Message { public readonly chainId: number, public readonly sender: string, public readonly messageNumber: BigNumber, - public readonly l1BaseFee: BigNumber, + public readonly parentChainBaseFee: BigNumber, public readonly messageData: RetryableMessageParams ) { - this.retryableCreationId = L1ToL2Message.calculateSubmitRetryableId( - chainId, - sender, - messageNumber, - l1BaseFee, - messageData.destAddress, - messageData.l2CallValue, - messageData.l1Value, - messageData.maxSubmissionFee, - messageData.excessFeeRefundAddress, - messageData.callValueRefundAddress, - messageData.gasLimit, - messageData.maxFeePerGas, - messageData.data - ) + this.retryableCreationId = + ParentChainToChainMessage.calculateSubmitRetryableId( + chainId, + sender, + messageNumber, + parentChainBaseFee, + messageData.destAddress, + messageData.l2CallValue, + messageData.l1Value, + messageData.maxSubmissionFee, + messageData.excessFeeRefundAddress, + messageData.callValueRefundAddress, + messageData.gasLimit, + messageData.maxFeePerGas, + messageData.data + ) } } /** - * If the status is redeemed an l2TxReceipt is populated. - * For all other statuses l2TxReceipt is not populated + * If the status is redeemed an chainTxReceipt is populated. + * For all other statuses chainTxReceipt is not populated */ -export type L1ToL2MessageWaitResult = - | { status: L1ToL2MessageStatus.REDEEMED; l2TxReceipt: TransactionReceipt } - | { status: Exclude } +export type ParentChainToChainMessageWaitResult = + | { + status: ParentChainToChainMessageStatus.REDEEMED + chainTxReceipt: TransactionReceipt + } + | { + status: Exclude< + ParentChainToChainMessageStatus, + ParentChainToChainMessageStatus.REDEEMED + > + } export type EthDepositMessageWaitResult = { - l2TxReceipt: TransactionReceipt | null + chainTxReceipt: TransactionReceipt | null } -export class L1ToL2MessageReader extends L1ToL2Message { +export class ParentChainToChainMessageReader extends ParentChainToChainMessage { private retryableCreationReceipt: TransactionReceipt | undefined | null public constructor( - public readonly l2Provider: Provider, + public readonly chainProvider: Provider, chainId: number, sender: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, messageData: RetryableMessageParams ) { - super(chainId, sender, messageNumber, l1BaseFee, messageData) + super(chainId, sender, messageNumber, parentChainBaseFee, 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 +281,7 @@ export class L1ToL2MessageReader extends L1ToL2Message { ): Promise { if (!this.retryableCreationReceipt) { this.retryableCreationReceipt = await getTransactionReceipt( - this.l2Provider, + this.chainProvider, this.retryableCreationId, confirmations, timeout @@ -285,11 +300,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 ChainTransactionReceipt(creationReceipt) + const redeemEvents = chainReceipt.getRedeemScheduledEvents() if (redeemEvents.length === 1) { - return await this.l2Provider.getTransactionReceipt( + return await this.chainProvider.getTransactionReceipt( redeemEvents[0].retryTxHash ) } else if (redeemEvents.length > 1) { @@ -303,34 +318,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 { - const l2Network = await getChainNetwork(this.l2Provider) - const eventFetcher = new EventFetcher(this.l2Provider) + public async getSuccessfulRedeem(): Promise { + const chainNetwork = await getChainNetwork(this.chainProvider) + const eventFetcher = new EventFetcher(this.chainProvider) const creationReceipt = await this.getRetryableCreationReceipt() if (!isDefined(creationReceipt)) { // retryable was never created, or not created yet // therefore it cant have been redeemed or be expired - return { status: L1ToL2MessageStatus.NOT_YET_CREATED } + return { status: ParentChainToChainMessageStatus.NOT_YET_CREATED } } if (creationReceipt.status === 0) { - return { status: L1ToL2MessageStatus.CREATION_FAILED } + return { status: ParentChainToChainMessageStatus.CREATION_FAILED } } // check the auto redeem first to avoid doing costly log queries in the happy case const autoRedeem = await this.getAutoRedeemAttempt() if (autoRedeem && autoRedeem.status === 1) { - return { l2TxReceipt: autoRedeem, status: L1ToL2MessageStatus.REDEEMED } + return { + chainTxReceipt: autoRedeem, + status: ParentChainToChainMessageStatus.REDEEMED, + } } if (await this.retryableExists()) { // the retryable was created and still exists // therefore it cant have been redeemed or be expired - return { status: L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 } + return { + status: ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN, + } } // from this point on we know that the retryable was created but does not exist, @@ -340,10 +360,12 @@ export class L1ToL2MessageReader extends L1ToL2Message { // to do this we need to filter through the whole lifetime of the ticket looking // for relevant redeem scheduled events let increment = 1000 - let fromBlock = await this.l2Provider.getBlock(creationReceipt.blockNumber) - let timeout = fromBlock.timestamp + l2Network.retryableLifetimeSeconds + let fromBlock = await this.chainProvider.getBlock( + creationReceipt.blockNumber + ) + let timeout = fromBlock.timestamp + chainNetwork.retryableLifetimeSeconds const queriedRange: { from: number; to: number }[] = [] - const maxBlock = await this.l2Provider.getBlockNumber() + const maxBlock = await this.chainProvider.getBlockNumber() while (fromBlock.number < maxBlock) { const toBlockNumber = Math.min(fromBlock.number + increment, maxBlock) @@ -363,7 +385,7 @@ export class L1ToL2MessageReader extends L1ToL2Message { const successfulRedeem = ( await Promise.all( redeemEvents.map(e => - this.l2Provider.getTransactionReceipt(e.event.retryTxHash) + this.chainProvider.getTransactionReceipt(e.event.retryTxHash) ) ) ).filter(r => isDefined(r) && r.status === 1) @@ -374,11 +396,11 @@ export class L1ToL2MessageReader extends L1ToL2Message { ) if (successfulRedeem.length == 1) return { - l2TxReceipt: successfulRedeem[0], - status: L1ToL2MessageStatus.REDEEMED, + chainTxReceipt: successfulRedeem[0], + status: ParentChainToChainMessageStatus.REDEEMED, } - const toBlock = await this.l2Provider.getBlock(toBlockNumber) + const toBlock = await this.chainProvider.getBlock(toBlockNumber) if (toBlock.timestamp > timeout) { // Check for LifetimeExtended event while (queriedRange.length > 0) { @@ -418,7 +440,7 @@ export class L1ToL2MessageReader extends L1ToL2Message { // we know from earlier that the retryable no longer exists, so if we havent found the redemption // we know that it must have expired - return { status: L1ToL2MessageStatus.EXPIRED } + return { status: ParentChainToChainMessageStatus.EXPIRED } } /** @@ -432,12 +454,12 @@ export class L1ToL2MessageReader extends L1ToL2Message { private async retryableExists(): Promise { const currentTimestamp = BigNumber.from( - (await this.l2Provider.getBlock('latest')).timestamp + (await this.chainProvider.getBlock('latest')).timestamp ) try { const timeoutTimestamp = await this.getTimeout() // timeoutTimestamp returns the timestamp at which the retryable ticket expires - // it can also return revert if the ticket l2Tx does not exist + // it can also return revert if the ticket chainTx does not exist return currentTimestamp.lte(timeoutTimestamp) } catch (err) { if ( @@ -452,31 +474,31 @@ export class L1ToL2MessageReader extends L1ToL2Message { } } - public async status(): Promise { + public async status(): Promise { return (await this.getSuccessfulRedeem()).status } /** - * Wait for the retryable ticket to be created, for it to be redeemed, and for the l2Tx to be executed. - * Note: The terminal status of a transaction that only does an eth deposit is FUNDS_DEPOSITED_ON_L2 as - * no L2 transaction needs to be executed, however the terminal state of any other transaction is REDEEMED - * which represents that the retryable ticket has been redeemed and the L2 tx has been executed. + * Wait for the retryable ticket to be created, for it to be redeemed, and for the chainTx to be executed. + * Note: The terminal status of a transaction that only does an eth deposit is FUNDS_DEPOSITED_ON_CHAIN as + * no Chain transaction needs to be executed, however the terminal state of any other transaction is REDEEMED + * which represents that the retryable ticket has been redeemed and the Chain tx has been executed. * @param confirmations Amount of confirmations the retryable ticket and the auto redeem receipt should have * @param timeout Amount of time to wait for the retryable ticket to be created - * Defaults to 15 minutes, as by this time all transactions are expected to be included on L2. Throws on timeout. - * @returns The wait result contains a status, and optionally the l2TxReceipt. - * If the status is "REDEEMED" then a l2TxReceipt is also available on the result. - * If the status has any other value then l2TxReceipt is not populated. + * Defaults to 15 minutes, as by this time all transactions are expected to be included on Chain. Throws on timeout. + * @returns The wait result contains a status, and optionally the chainTxReceipt. + * If the status is "REDEEMED" then a chainTxReceipt is also available on the result. + * If the status has any other value then chainTxReceipt is not populated. */ public async waitForStatus( confirmations?: number, timeout?: number - ): Promise { - const l2Network = await getChainNetwork(this.chainId) + ): Promise { + const chainNetwork = await getChainNetwork(this.chainId) const chosenTimeout = isDefined(timeout) ? timeout - : l2Network.depositTimeout + : chainNetwork.depositTimeout // try to wait for the retryable ticket to be created const _retryableCreationReceipt = await this.getRetryableCreationReceipt( @@ -501,10 +523,10 @@ export class L1ToL2MessageReader extends L1ToL2Message { * The minimium lifetime of a retryable tx * @returns */ - public static async getLifetime(l2Provider: Provider): Promise { + public static async getLifetime(chainProvider: Provider): Promise { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - l2Provider + chainProvider ) return await arbRetryableTx.getLifetime() } @@ -516,37 +538,41 @@ export class L1ToL2MessageReader extends L1ToL2Message { public async getTimeout(): Promise { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Provider + this.chainProvider ) return await arbRetryableTx.getTimeout(this.retryableCreationId) } /** - * Address to which CallValue will be credited to on L2 if the retryable ticket times out or is cancelled. + * Address to which CallValue will be credited to on Chain if the retryable ticket times out or is cancelled. * The Beneficiary is also the address with the right to cancel a Retryable Ticket (if the ticket hasn’t been redeemed yet). * @returns */ public getBeneficiary(): Promise { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Provider + this.chainProvider ) return arbRetryableTx.getBeneficiary(this.retryableCreationId) } } -export class L1ToL2MessageReaderClassic { +export class ParentChainToChainMessageReaderClassic { private retryableCreationReceipt: TransactionReceipt | undefined | null public readonly messageNumber: BigNumber public readonly retryableCreationId: string public readonly autoRedeemId: string - public readonly l2TxHash: string - public readonly l2Provider: Provider + public readonly chainTxHash: string + public readonly chainProvider: Provider - constructor(l2Provider: Provider, chainId: number, messageNumber: BigNumber) { + constructor( + chainProvider: Provider, + chainId: number, + messageNumber: BigNumber + ) { const bitFlip = (num: BigNumber) => num.or(BigNumber.from(1).shl(255)) this.messageNumber = messageNumber - this.l2Provider = l2Provider + this.chainProvider = chainProvider this.retryableCreationId = keccak256( concat([ @@ -562,7 +588,7 @@ export class L1ToL2MessageReaderClassic { ]) ) - this.l2TxHash = keccak256( + this.chainTxHash = keccak256( concat([ zeroPad(this.retryableCreationId, 32), zeroPad(BigNumber.from(0).toHexString(), 32), @@ -570,11 +596,11 @@ export class L1ToL2MessageReaderClassic { ) } - private calculateL2DerivedHash(retryableCreationId: string): string { + private calculateChainDerivedHash(retryableCreationId: string): string { return keccak256( concat([ zeroPad(retryableCreationId, 32), - // BN 0 meaning L2 TX + // BN 0 meaning Chain TX zeroPad(BigNumber.from(0).toHexString(), 32), ]) ) @@ -582,7 +608,7 @@ export class L1ToL2MessageReaderClassic { /** * 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 */ @@ -592,7 +618,7 @@ export class L1ToL2MessageReaderClassic { ): Promise { if (!this.retryableCreationReceipt) { this.retryableCreationReceipt = await getTransactionReceipt( - this.l2Provider, + this.chainProvider, this.retryableCreationId, confirmations, timeout @@ -602,77 +628,81 @@ export class L1ToL2MessageReaderClassic { return this.retryableCreationReceipt || null } - public async status(): Promise { + public async status(): Promise { const creationReceipt = await this.getRetryableCreationReceipt() if (!isDefined(creationReceipt)) { - return L1ToL2MessageStatus.NOT_YET_CREATED + return ParentChainToChainMessageStatus.NOT_YET_CREATED } if (creationReceipt.status === 0) { - return L1ToL2MessageStatus.CREATION_FAILED + return ParentChainToChainMessageStatus.CREATION_FAILED } - const l2DerivedHash = this.calculateL2DerivedHash(this.retryableCreationId) - const l2TxReceipt = await this.l2Provider.getTransactionReceipt( - l2DerivedHash + const chainDerivedHash = this.calculateChainDerivedHash( + this.retryableCreationId + ) + const chainTxReceipt = await this.chainProvider.getTransactionReceipt( + chainDerivedHash ) - if (l2TxReceipt && l2TxReceipt.status === 1) { - return L1ToL2MessageStatus.REDEEMED + if (chainTxReceipt && chainTxReceipt.status === 1) { + return ParentChainToChainMessageStatus.REDEEMED } - return L1ToL2MessageStatus.EXPIRED + return ParentChainToChainMessageStatus.EXPIRED } } -export class L1ToL2MessageWriter extends L1ToL2MessageReader { +export class ParentChainToChainMessageWriter extends ParentChainToChainMessageReader { public constructor( - public readonly l2Signer: Signer, + public readonly chainSigner: Signer, chainId: number, sender: string, messageNumber: BigNumber, - l1BaseFee: BigNumber, + parentChainBaseFee: BigNumber, messageData: RetryableMessageParams ) { super( - l2Signer.provider!, + chainSigner.provider!, chainId, sender, messageNumber, - l1BaseFee, + parentChainBaseFee, messageData ) - if (!l2Signer.provider) + if (!chainSigner.provider) throw new ArbSdkError('Signer not connected to provider.') } /** * Manually redeem the retryable ticket. - * Throws if message status is not L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 + * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async redeem(overrides?: Overrides): Promise { const status = await this.status() - if (status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) { + if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Signer + this.chainSigner ) const redeemTx = await arbRetryableTx.redeem(this.retryableCreationId, { ...overrides, }) - return L2TransactionReceipt.toRedeemTransaction( - L2TransactionReceipt.monkeyPatchWait(redeemTx), - this.l2Provider + return ChainTransactionReceipt.toRedeemTransaction( + ChainTransactionReceipt.monkeyPatchWait(redeemTx), + this.chainProvider ) } else { throw new ArbSdkError( `Cannot redeem as retryable does not exist. Message status: ${ - L1ToL2MessageStatus[status] + ParentChainToChainMessageStatus[status] } must be: ${ - L1ToL2MessageStatus[L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2] + ParentChainToChainMessageStatus[ + ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ] }.` ) } @@ -680,22 +710,24 @@ export class L1ToL2MessageWriter extends L1ToL2MessageReader { /** * Cancel the retryable ticket. - * Throws if message status is not L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 + * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async cancel(overrides?: Overrides): Promise { const status = await this.status() - if (status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) { + if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Signer + this.chainSigner ) return await arbRetryableTx.cancel(this.retryableCreationId, overrides) } else { throw new ArbSdkError( `Cannot cancel as retryable does not exist. Message status: ${ - L1ToL2MessageStatus[status] + ParentChainToChainMessageStatus[status] } must be: ${ - L1ToL2MessageStatus[L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2] + ParentChainToChainMessageStatus[ + ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ] }.` ) } @@ -703,22 +735,24 @@ export class L1ToL2MessageWriter extends L1ToL2MessageReader { /** * Increase the timeout of a retryable ticket. - * Throws if message status is not L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 + * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async keepAlive(overrides?: Overrides): Promise { const status = await this.status() - if (status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) { + if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, - this.l2Signer + this.chainSigner ) return await arbRetryableTx.keepalive(this.retryableCreationId, overrides) } else { throw new ArbSdkError( `Cannot keep alive as retryable does not exist. Message status: ${ - L1ToL2MessageStatus[status] + ParentChainToChainMessageStatus[status] } must be: ${ - L1ToL2MessageStatus[L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2] + ParentChainToChainMessageStatus[ + ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ] }.` ) } @@ -726,14 +760,14 @@ export class L1ToL2MessageWriter extends L1ToL2MessageReader { } /** - * A message for Eth deposits from L1 to L2 + * A message for Eth deposits from ParentChain to Chain */ export class EthDepositMessage { - public readonly l2DepositTxHash: string - private l2DepositTxReceipt: TransactionReceipt | undefined | null + public readonly chainDepositTxHash: string + private chainDepositTxReceipt: TransactionReceipt | undefined | null public static calculateDepositTxId( - l2ChainId: number, + chainChainId: number, messageNumber: BigNumber, fromAddress: string, toAddress: string, @@ -743,7 +777,7 @@ export class EthDepositMessage { return ethers.utils.stripZeros(numberVal.toHexString()) } - const chainId = BigNumber.from(l2ChainId) + const chainId = BigNumber.from(chainChainId) const msgNum = BigNumber.from(messageNumber) // https://github.com/OffchainLabs/go-ethereum/blob/07e017aa73e32be92aadb52fa327c552e1b7b118/core/types/arb_types.go#L302-L308 @@ -774,7 +808,7 @@ export class EthDepositMessage { to: string value: BigNumber } { - // https://github.com/OffchainLabs/nitro/blob/aa84e899cbc902bf6da753b1d66668a1def2c106/contracts/src/bridge/Inbox.sol#L242 + // https://github.com/OffchainLabs/nitro/blob/aa84e899cbc902bf6da753b1d66668a1def2c106/contracts/src/bridge/Inbox.sol#Chain42 // ethers.defaultAbiCoder doesnt decode packed args, so we do a hardcoded parsing const addressEnd = 2 + 20 * 2 const to = getAddress('0x' + eventData.substring(2, addressEnd)) @@ -785,25 +819,25 @@ export class EthDepositMessage { /** * Create an EthDepositMessage from data emitted in event when calling ethDeposit on Inbox.sol - * @param l2Provider + * @param chainProvider * @param messageNumber The message number in the Inbox.InboxMessageDelivered event * @param senderAddr The sender address from Bridge.MessageDelivered event * @param inboxMessageEventData The data field from the Inbox.InboxMessageDelivered event * @returns */ public static async fromEventComponents( - l2Provider: Provider, + chainProvider: Provider, messageNumber: BigNumber, senderAddr: string, inboxMessageEventData: string ) { - const chainId = (await l2Provider.getNetwork()).chainId + const chainId = (await chainProvider.getNetwork()).chainId const { to, value } = EthDepositMessage.parseEthDepositData( inboxMessageEventData ) return new EthDepositMessage( - l2Provider, + chainProvider, chainId, messageNumber, senderAddr, @@ -814,22 +848,22 @@ export class EthDepositMessage { /** * - * @param l2Provider - * @param l2ChainId + * @param chainProvider + * @param chainChainId * @param messageNumber - * @param to Recipient address of the ETH on L2 + * @param to Recipient address of the ETH on Chain * @param value */ constructor( - private readonly l2Provider: Provider, - public readonly l2ChainId: number, + private readonly chainProvider: Provider, + public readonly chainChainId: number, public readonly messageNumber: BigNumber, public readonly from: string, public readonly to: string, public readonly value: BigNumber ) { - this.l2DepositTxHash = EthDepositMessage.calculateDepositTxId( - l2ChainId, + this.chainDepositTxHash = EthDepositMessage.calculateDepositTxId( + chainChainId, messageNumber, from, to, @@ -838,29 +872,29 @@ export class EthDepositMessage { } public async status(): Promise { - const receipt = await this.l2Provider.getTransactionReceipt( - this.l2DepositTxHash + const receipt = await this.chainProvider.getTransactionReceipt( + this.chainDepositTxHash ) if (receipt === null) return EthDepositStatus.PENDING else return EthDepositStatus.DEPOSITED } public async wait(confirmations?: number, timeout?: number) { - const l2Network = await getChainNetwork(this.l2ChainId) + const chainNetwork = await getChainNetwork(this.chainChainId) const chosenTimeout = isDefined(timeout) ? timeout - : l2Network.depositTimeout + : chainNetwork.depositTimeout - if (!this.l2DepositTxReceipt) { - this.l2DepositTxReceipt = await getTransactionReceipt( - this.l2Provider, - this.l2DepositTxHash, + if (!this.chainDepositTxReceipt) { + this.chainDepositTxReceipt = await getTransactionReceipt( + this.chainProvider, + this.chainDepositTxHash, confirmations, chosenTimeout ) } - return this.l2DepositTxReceipt || null + return this.chainDepositTxReceipt || null } } diff --git a/src/lib/message/L1Transaction.ts b/src/lib/message/L1Transaction.ts index 054428a8ad..2f8d5d4ae0 100644 --- a/src/lib/message/L1Transaction.ts +++ b/src/lib/message/L1Transaction.ts @@ -21,13 +21,13 @@ import { Log, Provider } from '@ethersproject/abstract-provider' import { ContractTransaction } from '@ethersproject/contracts' import { BigNumber } from '@ethersproject/bignumber' import { - L1ToL2Message, - L1ToL2MessageReaderOrWriter, - L1ToL2MessageReader, - L1ToL2MessageReaderClassic, - L1ToL2MessageWriter, - L1ToL2MessageStatus, - L1ToL2MessageWaitResult, + ParentChainToChainMessage as L1ToL2Message, + ParentChainToChainMessageReaderOrWriter as L1ToL2MessageReaderOrWriter, + ParentChainToChainMessageReader as L1ToL2MessageReader, + ParentChainToChainMessageReaderClassic as L1ToL2MessageReaderClassic, + ParentChainToChainMessageWriter as L1ToL2MessageWriter, + ParentChainToChainMessageStatus as L1ToL2MessageStatus, + ParentChainToChainMessageWaitResult as L1ToL2MessageWaitResult, EthDepositMessage, EthDepositMessageWaitResult, } from './L1ToL2Message' @@ -372,7 +372,7 @@ export class L1EthDepositTransactionReceipt extends L1TransactionReceipt { return { complete: isDefined(res), - l2TxReceipt: res, + chainTxReceipt: res, message, } } diff --git a/tests/unit/l1toL2MessageEvents.test.ts b/tests/unit/l1toL2MessageEvents.test.ts index a4b5e2f330..65639a76eb 100644 --- a/tests/unit/l1toL2MessageEvents.test.ts +++ b/tests/unit/l1toL2MessageEvents.test.ts @@ -184,7 +184,7 @@ describe('L1toL2Message events', () => { 'incorrect message number' ).to.be.true expect( - msg.l1BaseFee.eq(BigNumber.from('0x05e0fc4c58')), + msg.parentChainBaseFee.eq(BigNumber.from('0x05e0fc4c58')), 'incorrect l1 base fee' ).to.be.true expect( @@ -322,7 +322,7 @@ describe('L1toL2Message events', () => { expect(msg.autoRedeemId, 'incorrect auto redeem id').to.be.eq( '0x38c5c31151344c7a1433a849bbc80472786ebe911630255a6e25d6a2efd39526' ) - expect(msg.l2TxHash, 'incorrect l2 tx hash').to.be.eq( + expect(msg.chainTxHash, 'incorrect l2 tx hash').to.be.eq( '0xf91e7d2e7526927e915a2357360a3f1108dce0f9c7fa88a7492669adf5c1e53b' ) }) From 34be52b87d9c951adcc1a7123e7754c6f4a91934 Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Wed, 27 Sep 2023 11:10:38 -0400 Subject: [PATCH 06/14] fix integration test --- tests/integration/eth.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/integration/eth.test.ts b/tests/integration/eth.test.ts index af8ca1c7a6..3e6f7e3955 100644 --- a/tests/integration/eth.test.ts +++ b/tests/integration/eth.test.ts @@ -32,7 +32,7 @@ import { import { L2ToL1Message } from '../../src/lib/message/L2ToL1Message' import { L2ToL1MessageStatus } from '../../src/lib/dataEntities/message' import { L2TransactionReceipt } from '../../src/lib/message/L2Transaction' -import { L1ToL2MessageStatus } from '../../src/lib/message/L1ToL2Message' +import { ParentChainToChainMessageStatus as L1ToL2MessageStatus } from '../../src/lib/message/L1ToL2Message' import { testSetup } from '../../scripts/testSetup' dotenv.config() @@ -113,11 +113,11 @@ describe('Ether', async () => { ethToDeposit.toString() ) - prettyLog('l2TxHash: ' + waitResult.message.l2DepositTxHash) - prettyLog('l2 transaction found!') + prettyLog('chainTxHash: ' + waitResult.message.chainDepositTxHash) + prettyLog('chain transaction found!') expect(waitResult.complete).to.eq(true, 'eth deposit not complete') - expect(waitResult.l2TxReceipt).to.exist - expect(waitResult.l2TxReceipt).to.not.be.null + expect(waitResult.chainTxReceipt).to.exist + expect(waitResult.chainTxReceipt).to.not.be.null const testWalletL2EthBalance = await l2Signer.getBalance() expect(testWalletL2EthBalance.toString(), 'final balance').to.eq( From 87b928373d95bbd508fd35d9537f43135f48776f Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Wed, 27 Sep 2023 11:19:04 -0400 Subject: [PATCH 07/14] fix unit tests --- tests/integration/eth.test.ts | 4 ++-- tests/integration/standarderc20.test.ts | 10 +++++----- tests/unit/l2toL1MessageEvents.test.ts | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/integration/eth.test.ts b/tests/integration/eth.test.ts index 3e6f7e3955..0e7603d42f 100644 --- a/tests/integration/eth.test.ts +++ b/tests/integration/eth.test.ts @@ -29,7 +29,7 @@ import { prettyLog, skipIfMainnet, } from './testHelpers' -import { L2ToL1Message } from '../../src/lib/message/L2ToL1Message' +import { ChainToParentChainMessage as L2ToL1Message } from '../../src/lib/message/L2ToL1Message' import { L2ToL1MessageStatus } from '../../src/lib/dataEntities/message' import { L2TransactionReceipt } from '../../src/lib/message/L2Transaction' import { ParentChainToChainMessageStatus as L1ToL2MessageStatus } from '../../src/lib/message/L1ToL2Message' @@ -231,7 +231,7 @@ describe('Ether', async () => { 'eth withdraw getWithdrawalsInL2Transaction query came back empty' ).to.exist - const withdrawEvents = await L2ToL1Message.getL2ToL1Events( + const withdrawEvents = await L2ToL1Message.getChainToParentChainEvents( l2Signer.provider!, { fromBlock: withdrawEthRec.blockNumber, toBlock: 'latest' }, undefined, diff --git a/tests/integration/standarderc20.test.ts b/tests/integration/standarderc20.test.ts index 4a1ac7ce83..e66c4ad2fb 100644 --- a/tests/integration/standarderc20.test.ts +++ b/tests/integration/standarderc20.test.ts @@ -105,7 +105,7 @@ describe('standard ERC20', () => { expect(retryRec.status, 'tx didnt fail').to.eq(expectedStatus) expect(await message.status(), 'message status').to.eq( expectedStatus === 0 - ? L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 + ? L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN : L1ToL2MessageStatus.REDEEMED ) } @@ -117,7 +117,7 @@ describe('standard ERC20', () => { testState.erc20Bridger, testState.l1Signer, testState.l2Signer, - L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2, + L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN, GatewayType.STANDARD, { gasLimit: { base: BigNumber.from(0) }, @@ -135,7 +135,7 @@ describe('standard ERC20', () => { testState.erc20Bridger, testState.l1Signer, testState.l2Signer, - L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2, + L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN, GatewayType.STANDARD, { gasLimit: { base: BigNumber.from(5) }, @@ -155,7 +155,7 @@ describe('standard ERC20', () => { testState.erc20Bridger, testState.l1Signer, testState.l2Signer, - L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2, + L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN, GatewayType.STANDARD, { gasLimit: { base: BigNumber.from(21000) }, @@ -187,7 +187,7 @@ describe('standard ERC20', () => { testState.erc20Bridger, testState.l1Signer, testState.l2Signer, - L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2, + L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN, GatewayType.STANDARD, { gasLimit: { base: BigNumber.from(5) }, diff --git a/tests/unit/l2toL1MessageEvents.test.ts b/tests/unit/l2toL1MessageEvents.test.ts index 2921c8813f..57725a2c40 100644 --- a/tests/unit/l2toL1MessageEvents.test.ts +++ b/tests/unit/l2toL1MessageEvents.test.ts @@ -59,7 +59,7 @@ describe('L2ToL1Message events', () => { const fromBlock = 0 const toBlock = 1000 - await L2ToL1Message.getL2ToL1Events(l2Provider, { + await L2ToL1Message.getChainToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -82,7 +82,7 @@ describe('L2ToL1Message events', () => { const fromBlock = l2Network.nitroGenesisBlock const toBlock = l2Network.nitroGenesisBlock + 500 - await L2ToL1Message.getL2ToL1Events(l2Provider, { + await L2ToL1Message.getChainToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -105,7 +105,7 @@ describe('L2ToL1Message events', () => { const fromBlock = 0 const toBlock = l2Network.nitroGenesisBlock + 500 - await L2ToL1Message.getL2ToL1Events(l2Provider, { + await L2ToL1Message.getChainToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -138,7 +138,7 @@ describe('L2ToL1Message events', () => { const fromBlock = 'earliest' const toBlock = 'latest' - await L2ToL1Message.getL2ToL1Events(l2Provider, { + await L2ToL1Message.getChainToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -171,7 +171,7 @@ describe('L2ToL1Message events', () => { const fromBlock = l2Network.nitroGenesisBlock + 2 const toBlock = 'latest' - await L2ToL1Message.getL2ToL1Events(l2Provider, { + await L2ToL1Message.getChainToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -194,7 +194,7 @@ describe('L2ToL1Message events', () => { const fromBlock = 'earliest' const toBlock = 'latest' - await L2ToL1Message.getL2ToL1Events(l2Provider, { + await L2ToL1Message.getChainToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) From 2441e4581cc27753ba6b0cf2d1cea14df786d7d1 Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Wed, 27 Sep 2023 11:21:16 -0400 Subject: [PATCH 08/14] fix test --- tests/integration/standarderc20.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/integration/standarderc20.test.ts b/tests/integration/standarderc20.test.ts index 4a1ac7ce83..e66c4ad2fb 100644 --- a/tests/integration/standarderc20.test.ts +++ b/tests/integration/standarderc20.test.ts @@ -105,7 +105,7 @@ describe('standard ERC20', () => { expect(retryRec.status, 'tx didnt fail').to.eq(expectedStatus) expect(await message.status(), 'message status').to.eq( expectedStatus === 0 - ? L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2 + ? L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN : L1ToL2MessageStatus.REDEEMED ) } @@ -117,7 +117,7 @@ describe('standard ERC20', () => { testState.erc20Bridger, testState.l1Signer, testState.l2Signer, - L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2, + L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN, GatewayType.STANDARD, { gasLimit: { base: BigNumber.from(0) }, @@ -135,7 +135,7 @@ describe('standard ERC20', () => { testState.erc20Bridger, testState.l1Signer, testState.l2Signer, - L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2, + L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN, GatewayType.STANDARD, { gasLimit: { base: BigNumber.from(5) }, @@ -155,7 +155,7 @@ describe('standard ERC20', () => { testState.erc20Bridger, testState.l1Signer, testState.l2Signer, - L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2, + L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN, GatewayType.STANDARD, { gasLimit: { base: BigNumber.from(21000) }, @@ -187,7 +187,7 @@ describe('standard ERC20', () => { testState.erc20Bridger, testState.l1Signer, testState.l2Signer, - L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2, + L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_CHAIN, GatewayType.STANDARD, { gasLimit: { base: BigNumber.from(5) }, From eb48d9861db36d5d103b5cb30ee3dd95e9a8fc69 Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Fri, 29 Sep 2023 13:55:50 -0400 Subject: [PATCH 09/14] chore renames: L2ToL1MessageNitro to ChainToParentChain --- src/lib/message/L2ToL1Message.ts | 10 +-- src/lib/message/L2ToL1MessageNitro.ts | 91 ++++++++++++++++----------- 2 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/lib/message/L2ToL1Message.ts b/src/lib/message/L2ToL1Message.ts index 024d9b6b6e..5cd74a46e8 100644 --- a/src/lib/message/L2ToL1Message.ts +++ b/src/lib/message/L2ToL1Message.ts @@ -185,7 +185,7 @@ export class ChainToParentChainMessage { } if (nitroFilter.fromBlock !== nitroFilter.toBlock) { logQueries.push( - nitro.L2ToL1MessageNitro.getL2ToL1Events( + nitro.ChainToParentChainMessageNitro.getChainToParentChainEvents( ChainProvider, nitroFilter, position, @@ -204,7 +204,7 @@ export class ChainToParentChainMessage { */ export class ChainToParentChainMessageReader extends ChainToParentChainMessage { private readonly classicReader?: classic.L2ToL1MessageReaderClassic - private readonly nitroReader?: nitro.L2ToL1MessageReaderNitro + private readonly nitroReader?: nitro.ChainToParentChainMessageReaderNitro constructor( protected readonly ParentChainProvider: Provider, @@ -218,7 +218,7 @@ export class ChainToParentChainMessageReader extends ChainToParentChainMessage { event.indexInBatch ) } else { - this.nitroReader = new nitro.L2ToL1MessageReaderNitro( + this.nitroReader = new nitro.ChainToParentChainMessageReaderNitro( ParentChainProvider, event ) @@ -286,7 +286,7 @@ export class ChainToParentChainMessageReader extends ChainToParentChainMessage { */ export class ChainToParentChainMessageWriter extends ChainToParentChainMessageReader { private readonly classicWriter?: classic.L2ToL1MessageWriterClassic - private readonly nitroWriter?: nitro.L2ToL1MessageWriterNitro + private readonly nitroWriter?: nitro.ChainToParentChainMessageWriterNitro /** * Instantiates a new `ChainToParentChainMessageWriter` object. @@ -310,7 +310,7 @@ export class ChainToParentChainMessageWriter extends ChainToParentChainMessageRe ParentChainProvider ) } else { - this.nitroWriter = new nitro.L2ToL1MessageWriterNitro( + this.nitroWriter = new nitro.ChainToParentChainMessageWriterNitro( ParentChainSigner, event, ParentChainProvider diff --git a/src/lib/message/L2ToL1MessageNitro.ts b/src/lib/message/L2ToL1MessageNitro.ts index 1c1239f259..b3ad191c87 100644 --- a/src/lib/message/L2ToL1MessageNitro.ts +++ b/src/lib/message/L2ToL1MessageNitro.ts @@ -30,7 +30,7 @@ import { RollupUserLogic__factory } from '../abi/factories/RollupUserLogic__fact import { Outbox__factory } from '../abi/factories/Outbox__factory' import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory' -import { L2ToL1TxEvent } from '../abi/ArbSys' +import { L2ToL1TxEvent as ChainToParentChainTxEvent } from '../abi/ArbSys' import { ContractTransaction, Overrides } from 'ethers' import { EventFetcher, FetchedEvent } from '../utils/eventFetcher' import { ArbSdkError } from '../dataEntities/errors' @@ -45,16 +45,19 @@ 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 { L2ToL1MessageStatus as ChainToParentChainMessageStatus } from '../dataEntities/message' /** * 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 ChainToParentChainMessageReaderOrWriter will be of type ChainToParentChainMessageReader. + * If T is of type Signer then ChainToParentChainMessageReaderOrWriter will be of + * type ChainToParentChainMessageWriter. */ -export type L2ToL1MessageReaderOrWriterNitro = - T extends Provider ? L2ToL1MessageReaderNitro : L2ToL1MessageWriterNitro +export type ChainToParentChainMessageReaderOrWriterNitro< + T extends SignerOrProvider +> = T extends Provider + ? ChainToParentChainMessageReaderNitro + : ChainToParentChainMessageWriterNitro // expected number of L1 blocks that it takes for an L2 tx to be included in a L1 assertion const ASSERTION_CREATED_PADDING = 50 @@ -64,38 +67,48 @@ const ASSERTION_CONFIRMED_PADDING = 20 /** * Base functionality for nitro L2->L1 messages */ -export class L2ToL1MessageNitro { - protected constructor(public readonly event: EventArgs) {} +export class ChainToParentChainMessageNitro { + protected constructor( + public readonly event: EventArgs + ) {} /** - * Instantiates a new `L2ToL1MessageWriterNitro` or `L2ToL1MessageReaderNitro` object. + * Instantiates a new `ChainToParentChainMessageWriterNitro` or `ChainToParentChainMessageReaderNitro` 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 {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. */ public static fromEvent( l1SignerOrProvider: T, - event: EventArgs, + event: EventArgs, l1Provider?: Provider - ): L2ToL1MessageReaderOrWriterNitro + ): ChainToParentChainMessageReaderOrWriterNitro public static fromEvent( l1SignerOrProvider: T, - event: EventArgs, + event: EventArgs, l1Provider?: Provider - ): L2ToL1MessageReaderNitro | L2ToL1MessageWriterNitro { + ): + | ChainToParentChainMessageReaderNitro + | ChainToParentChainMessageWriterNitro { return SignerProviderUtils.isSigner(l1SignerOrProvider) - ? new L2ToL1MessageWriterNitro(l1SignerOrProvider, event, l1Provider) - : new L2ToL1MessageReaderNitro(l1SignerOrProvider, event) + ? new ChainToParentChainMessageWriterNitro( + l1SignerOrProvider, + event, + l1Provider + ) + : new ChainToParentChainMessageReaderNitro(l1SignerOrProvider, event) } - public static async getL2ToL1Events( + public static async getChainToParentChainEvents( l2Provider: Provider, filter: { fromBlock: BlockTag; toBlock: BlockTag }, position?: BigNumber, destination?: string, hash?: BigNumber - ): Promise<(EventArgs & { transactionHash: string })[]> { + ): Promise< + (EventArgs & { transactionHash: string })[] + > { const eventFetcher = new EventFetcher(l2Provider) return ( await eventFetcher.getEvents( @@ -110,7 +123,7 @@ export class L2ToL1MessageNitro { /** * Provides read-only access nitro for l2-to-l1-messages */ -export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro { +export class ChainToParentChainMessageReaderNitro extends ChainToParentChainMessageNitro { protected sendRootHash?: string protected sendRootSize?: BigNumber protected sendRootConfirmed?: boolean @@ -119,7 +132,7 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro { constructor( protected readonly l1Provider: Provider, - event: EventArgs + event: EventArgs ) { super(event) } @@ -160,12 +173,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 { + public async status( + l2Provider: Provider + ): Promise { const { sendRootConfirmed } = await this.getSendProps(l2Provider) - if (!sendRootConfirmed) return L2ToL1MessageStatus.UNCONFIRMED + if (!sendRootConfirmed) return ChainToParentChainMessageStatus.UNCONFIRMED return (await this.hasExecuted(l2Provider)) - ? L2ToL1MessageStatus.EXECUTED - : L2ToL1MessageStatus.CONFIRMED + ? ChainToParentChainMessageStatus.EXECUTED + : ChainToParentChainMessageStatus.CONFIRMED } private parseNodeCreatedAssertion(event: FetchedEvent) { @@ -330,8 +345,8 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro { ): Promise { const status = await this.status(l2Provider) if ( - status === L2ToL1MessageStatus.CONFIRMED || - status === L2ToL1MessageStatus.EXECUTED + status === ChainToParentChainMessageStatus.CONFIRMED || + status === ChainToParentChainMessageStatus.EXECUTED ) { return } else { @@ -357,12 +372,12 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro { ) const status = await this.status(l2Provider) - if (status === L2ToL1MessageStatus.EXECUTED) return null - if (status === L2ToL1MessageStatus.CONFIRMED) return null + if (status === ChainToParentChainMessageStatus.EXECUTED) return null + if (status === ChainToParentChainMessageStatus.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 !== ChainToParentChainMessageStatus.UNCONFIRMED) + throw new ArbSdkError('ChainToParentChainMsg expected to be unconfirmed') const latestBlock = await this.l1Provider.getBlockNumber() const eventFetcher = new EventFetcher(this.l1Provider) @@ -433,24 +448,24 @@ export class L2ToL1MessageReaderNitro extends L2ToL1MessageNitro { /** * Provides read and write access for nitro l2-to-l1-messages */ -export class L2ToL1MessageWriterNitro extends L2ToL1MessageReaderNitro { +export class ChainToParentChainMessageWriterNitro extends ChainToParentChainMessageReaderNitro { /** - * Instantiates a new `L2ToL1MessageWriterNitro` object. + * Instantiates a new `ChainToParentChainMessageWriterNitro` 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 {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. */ constructor( private readonly l1Signer: Signer, - event: EventArgs, + event: EventArgs, l1Provider?: Provider ) { super(l1Provider ?? l1Signer.provider!, event) } /** - * Executes the L2ToL1Message on L1. + * Executes the ChainToParentChainMessage on L1. * Will throw an error if the outbox entry has not been created, which happens when the * corresponding assertion is confirmed. * @returns @@ -460,9 +475,9 @@ export class L2ToL1MessageWriterNitro extends L2ToL1MessageReaderNitro { overrides?: Overrides ): Promise { const status = await this.status(l2Provider) - if (status !== L2ToL1MessageStatus.CONFIRMED) { + if (status !== ChainToParentChainMessageStatus.CONFIRMED) { throw new ArbSdkError( - `Cannot execute message. Status is: ${status} but must be ${L2ToL1MessageStatus.CONFIRMED}.` + `Cannot execute message. Status is: ${status} but must be ${ChainToParentChainMessageStatus.CONFIRMED}.` ) } const proof = await this.getOutboxProof(l2Provider) From c7fd2c50008d663e8e45d2bea2ceabcf08a9f8d8 Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Mon, 2 Oct 2023 11:16:14 -0400 Subject: [PATCH 10/14] chore: renames to ChildToParentChain --- src/index.ts | 6 +-- src/lib/message/L2ToL1Message.ts | 74 +++++++++++++------------- src/lib/message/L2Transaction.ts | 10 ++-- tests/integration/eth.test.ts | 4 +- tests/unit/l2toL1MessageEvents.test.ts | 20 +++---- 5 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/index.ts b/src/index.ts index fde6731572..58e43cf5ca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,9 +23,9 @@ export { L2ContractTransaction, } from './lib/message/L2Transaction' export { - ChainToParentChainMessage as L2ToL1Message, - ChainToParentChainMessageWriter as L2ToL1MessageWriter, - ChainToParentChainMessageReader as L2ToL1MessageReader, + ChildToParentChainMessage as L2ToL1Message, + ChildToParentChainMessageWriter as L2ToL1MessageWriter, + ChildToParentChainMessageReader as L2ToL1MessageReader, } from './lib/message/L2ToL1Message' export { L1ContractTransaction, diff --git a/src/lib/message/L2ToL1Message.ts b/src/lib/message/L2ToL1Message.ts index 024d9b6b6e..398c4a2d11 100644 --- a/src/lib/message/L2ToL1Message.ts +++ b/src/lib/message/L2ToL1Message.ts @@ -29,84 +29,84 @@ import { import * as classic from './L2ToL1MessageClassic' import * as nitro from './L2ToL1MessageNitro' import { - L2ToL1TransactionEvent as ClassicChainToParentChainTransactionEvent, - L2ToL1TxEvent as NitroChainToParentChainTransactionEvent, + L2ToL1TransactionEvent as ClassicChildToParentChainTransactionEvent, + L2ToL1TxEvent as NitroChildToParentChainTransactionEvent, } from '../abi/ArbSys' import { isDefined } from '../utils/lib' import { EventArgs } from '../dataEntities/event' -import { L2ToL1MessageStatus as ChainToParentChainMessageStatus } from '../dataEntities/message' +import { L2ToL1MessageStatus as ChildToParentChainMessageStatus } from '../dataEntities/message' import { getChainNetwork } from '../dataEntities/networks' import { ArbSdkError } from '../dataEntities/errors' -export type ChainToParentChainTransactionEvent = - | EventArgs - | EventArgs +export type ChildToParentChainTransactionEvent = + | EventArgs + | EventArgs /** * Conditional type for Signer or Provider. If T is of type Provider - * then ChainToParentChainMessageReaderOrWriter will be of type ChainToParentChainMessageReader. - * If T is of type Signer then ChainToParentChainMessageReaderOrWriter will be of - * type ChainToParentChainMessageWriter. + * then ChildToParentChainMessageReaderOrWriter will be of type ChildToParentChainMessageReader. + * If T is of type Signer then ChildToParentChainMessageReaderOrWriter will be of + * type ChildToParentChainMessageWriter. */ -export type ChainToParentChainMessageReaderOrWriter< +export type ChildToParentChainMessageReaderOrWriter< T extends SignerOrProvider > = T extends Provider - ? ChainToParentChainMessageReader - : ChainToParentChainMessageWriter + ? ChildToParentChainMessageReader + : ChildToParentChainMessageWriter /** * Base functionality for Chain->ParentChain messages */ -export class ChainToParentChainMessage { +export class ChildToParentChainMessage { protected isClassic( - e: ChainToParentChainTransactionEvent - ): e is EventArgs { + e: ChildToParentChainTransactionEvent + ): e is EventArgs { return isDefined( - (e as EventArgs).indexInBatch + (e as EventArgs).indexInBatch ) } /** - * Instantiates a new `ChainToParentChainMessageWriter` or `ChainToParentChainMessageReader` object. + * Instantiates a new `ChildToParentChainMessageWriter` or `ChildToParentChainMessageReader` object. * * @param {SignerOrProvider} ParentChainSignerOrProvider Signer or provider to be used for executing or reading the Chain-to-ParentChain message. - * @param {ChainToParentChainTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. + * @param {ChildToParentChainTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. * @param {Provider} [ParentChainProvider] Optional. Used to override the Provider which is attached to `ParentChainSignerOrProvider` in case you need more control. This will be a required parameter in a future major version update. */ public static fromEvent( ParentChainSignerOrProvider: T, - event: ChainToParentChainTransactionEvent, + event: ChildToParentChainTransactionEvent, ParentChainProvider?: Provider - ): ChainToParentChainMessageReaderOrWriter + ): ChildToParentChainMessageReaderOrWriter static fromEvent( ParentChainSignerOrProvider: T, - event: ChainToParentChainTransactionEvent, + event: ChildToParentChainTransactionEvent, ParentChainProvider?: Provider - ): ChainToParentChainMessageReader | ChainToParentChainMessageWriter { + ): ChildToParentChainMessageReader | ChildToParentChainMessageWriter { return SignerProviderUtils.isSigner(ParentChainSignerOrProvider) - ? new ChainToParentChainMessageWriter( + ? new ChildToParentChainMessageWriter( ParentChainSignerOrProvider, event, ParentChainProvider ) - : new ChainToParentChainMessageReader(ParentChainSignerOrProvider, event) + : new ChildToParentChainMessageReader(ParentChainSignerOrProvider, event) } /** - * Get event logs for ChainToParentChain transactions. + * Get event logs for ChildToParentChain transactions. * @param ChainProvider * @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 ParentChain destination of the ChainToParentChain message + * @param destination The ParentChain destination of the ChildToParentChain 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 getChainToParentChainEvents( + public static async getChildToParentChainEvents( ChainProvider: Provider, filter: { fromBlock: BlockTag; toBlock: BlockTag }, position?: BigNumber, @@ -114,7 +114,7 @@ export class ChainToParentChainMessage { hash?: BigNumber, indexInBatch?: BigNumber ): Promise< - (ChainToParentChainTransactionEvent & { transactionHash: string })[] + (ChildToParentChainTransactionEvent & { transactionHash: string })[] > { const ChainNetwork = await getChainNetwork(ChainProvider) @@ -202,13 +202,13 @@ export class ChainToParentChainMessage { /** * Provides read-only access for Chain-to-ParentChain-messages */ -export class ChainToParentChainMessageReader extends ChainToParentChainMessage { +export class ChildToParentChainMessageReader extends ChildToParentChainMessage { private readonly classicReader?: classic.L2ToL1MessageReaderClassic private readonly nitroReader?: nitro.L2ToL1MessageReaderNitro constructor( protected readonly ParentChainProvider: Provider, - event: ChainToParentChainTransactionEvent + event: ChildToParentChainTransactionEvent ) { super() if (this.isClassic(event)) { @@ -240,8 +240,8 @@ export class ChainToParentChainMessageReader extends ChainToParentChainMessage { */ public async status( ChainProvider: Provider - ): Promise { - // can we create an ChainToParentChainmessage here, we need to - the constructor is what we need + ): Promise { + // can we create an ChildToParentChainmessage here, we need to - the constructor is what we need if (this.nitroReader) return await this.nitroReader.status(ChainProvider) else return await this.classicReader!.status(ChainProvider) } @@ -284,20 +284,20 @@ export class ChainToParentChainMessageReader extends ChainToParentChainMessage { /** * Provides read and write access for Chain-to-ParentChain-messages */ -export class ChainToParentChainMessageWriter extends ChainToParentChainMessageReader { +export class ChildToParentChainMessageWriter extends ChildToParentChainMessageReader { private readonly classicWriter?: classic.L2ToL1MessageWriterClassic private readonly nitroWriter?: nitro.L2ToL1MessageWriterNitro /** - * Instantiates a new `ChainToParentChainMessageWriter` object. + * Instantiates a new `ChildToParentChainMessageWriter` object. * * @param {Signer} ParentChainSigner The signer to be used for executing the Chain-to-ParentChain message. - * @param {ChainToParentChainTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. + * @param {ChildToParentChainTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. * @param {Provider} [ParentChainProvider] Optional. Used to override the Provider which is attached to `ParentChainSigner` in case you need more control. This will be a required parameter in a future major version update. */ constructor( ParentChainSigner: Signer, - event: ChainToParentChainTransactionEvent, + event: ChildToParentChainTransactionEvent, ParentChainProvider?: Provider ) { super(ParentChainProvider ?? ParentChainSigner.provider!, event) @@ -319,7 +319,7 @@ export class ChainToParentChainMessageWriter extends ChainToParentChainMessageRe } /** - * Executes the ChainToParentChainMessage on ParentChain. + * Executes the ChildToParentChainMessage on ParentChain. * Will throw an error if the outbox entry has not been created, which happens when the * corresponding assertion is confirmed. * @returns diff --git a/src/lib/message/L2Transaction.ts b/src/lib/message/L2Transaction.ts index 9eabd3a7af..470d86b075 100644 --- a/src/lib/message/L2Transaction.ts +++ b/src/lib/message/L2Transaction.ts @@ -25,11 +25,11 @@ import { SignerOrProvider, } from '../dataEntities/signerOrProvider' import { - ChainToParentChainMessageReader as L2ToL1MessageReader, - ChainToParentChainMessageReaderOrWriter as L2ToL1MessageReaderOrWriter, - ChainToParentChainMessage as L2ToL1Message, - ChainToParentChainMessageWriter as L2ToL1MessageWriter, - ChainToParentChainTransactionEvent as L2ToL1TransactionEvent, + ChildToParentChainMessageReader as L2ToL1MessageReader, + ChildToParentChainMessageReaderOrWriter as L2ToL1MessageReaderOrWriter, + ChildToParentChainMessage as L2ToL1Message, + ChildToParentChainMessageWriter as L2ToL1MessageWriter, + ChildToParentChainTransactionEvent as L2ToL1TransactionEvent, } from './L2ToL1Message' import { ArbSys__factory } from '../abi/factories/ArbSys__factory' import { ArbRetryableTx__factory } from '../abi/factories/ArbRetryableTx__factory' diff --git a/tests/integration/eth.test.ts b/tests/integration/eth.test.ts index 0e7603d42f..b1c4a4dfa5 100644 --- a/tests/integration/eth.test.ts +++ b/tests/integration/eth.test.ts @@ -29,7 +29,7 @@ import { prettyLog, skipIfMainnet, } from './testHelpers' -import { ChainToParentChainMessage as L2ToL1Message } from '../../src/lib/message/L2ToL1Message' +import { ChildToParentChainMessage as L2ToL1Message } from '../../src/lib/message/L2ToL1Message' import { L2ToL1MessageStatus } from '../../src/lib/dataEntities/message' import { L2TransactionReceipt } from '../../src/lib/message/L2Transaction' import { ParentChainToChainMessageStatus as L1ToL2MessageStatus } from '../../src/lib/message/L1ToL2Message' @@ -231,7 +231,7 @@ describe('Ether', async () => { 'eth withdraw getWithdrawalsInL2Transaction query came back empty' ).to.exist - const withdrawEvents = await L2ToL1Message.getChainToParentChainEvents( + const withdrawEvents = await L2ToL1Message.getChildToParentChainEvents( l2Signer.provider!, { fromBlock: withdrawEthRec.blockNumber, toBlock: 'latest' }, undefined, diff --git a/tests/unit/l2toL1MessageEvents.test.ts b/tests/unit/l2toL1MessageEvents.test.ts index 57725a2c40..3e0ce17e10 100644 --- a/tests/unit/l2toL1MessageEvents.test.ts +++ b/tests/unit/l2toL1MessageEvents.test.ts @@ -18,16 +18,16 @@ import { Logger, LogLevel } from '@ethersproject/logger' Logger.setLogLevel(LogLevel.ERROR) -import { L2ToL1Message } from '../../src' +import { L2ToL1Message as ChildToParentChainMessage } from '../../src' import { getChainNetwork as getL2Network } from '../../src/lib/dataEntities/networks' import { providers } from 'ethers' import { anything, deepEqual, instance, mock, verify, when } from 'ts-mockito' -describe('L2ToL1Message events', () => { - // L2ToL1Transaction +describe('ChildToParentChainMessage events', () => { + // ChildToParentChainTransaction const classicTopic = '0x5baaa87db386365b5c161be377bc3d8e317e8d98d71a3ca7ed7d555340c8f767' - // L2ToL1Tx + // ChildToParentChainTx const nitroTopic = '0x3e7aafa77dbf186b7fd488006beff893744caa3c4f6f299e8a709fa2087374fc' @@ -59,7 +59,7 @@ describe('L2ToL1Message events', () => { const fromBlock = 0 const toBlock = 1000 - await L2ToL1Message.getChainToParentChainEvents(l2Provider, { + await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -82,7 +82,7 @@ describe('L2ToL1Message events', () => { const fromBlock = l2Network.nitroGenesisBlock const toBlock = l2Network.nitroGenesisBlock + 500 - await L2ToL1Message.getChainToParentChainEvents(l2Provider, { + await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -105,7 +105,7 @@ describe('L2ToL1Message events', () => { const fromBlock = 0 const toBlock = l2Network.nitroGenesisBlock + 500 - await L2ToL1Message.getChainToParentChainEvents(l2Provider, { + await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -138,7 +138,7 @@ describe('L2ToL1Message events', () => { const fromBlock = 'earliest' const toBlock = 'latest' - await L2ToL1Message.getChainToParentChainEvents(l2Provider, { + await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -171,7 +171,7 @@ describe('L2ToL1Message events', () => { const fromBlock = l2Network.nitroGenesisBlock + 2 const toBlock = 'latest' - await L2ToL1Message.getChainToParentChainEvents(l2Provider, { + await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -194,7 +194,7 @@ describe('L2ToL1Message events', () => { const fromBlock = 'earliest' const toBlock = 'latest' - await L2ToL1Message.getChainToParentChainEvents(l2Provider, { + await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) From e3c638f1a98a75387df3b1983582010f371ce3fe Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Mon, 2 Oct 2023 13:05:00 -0400 Subject: [PATCH 11/14] chore: renames to ChildToParentChild for Nitro --- src/lib/message/L2ToL1Message.ts | 10 ++-- src/lib/message/L2ToL1MessageNitro.ts | 80 +++++++++++++-------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/lib/message/L2ToL1Message.ts b/src/lib/message/L2ToL1Message.ts index dd9a56abc1..92806c9c03 100644 --- a/src/lib/message/L2ToL1Message.ts +++ b/src/lib/message/L2ToL1Message.ts @@ -185,7 +185,7 @@ export class ChildToParentChainMessage { } if (nitroFilter.fromBlock !== nitroFilter.toBlock) { logQueries.push( - nitro.ChainToParentChainMessageNitro.getChainToParentChainEvents( + nitro.ChildToParentChainMessageNitro.getChildToParentChainEvents( ChainProvider, nitroFilter, position, @@ -204,7 +204,7 @@ export class ChildToParentChainMessage { */ export class ChildToParentChainMessageReader extends ChildToParentChainMessage { private readonly classicReader?: classic.L2ToL1MessageReaderClassic - private readonly nitroReader?: nitro.ChainToParentChainMessageReaderNitro + private readonly nitroReader?: nitro.ChildToParentChainMessageReaderNitro constructor( protected readonly ParentChainProvider: Provider, @@ -218,7 +218,7 @@ export class ChildToParentChainMessageReader extends ChildToParentChainMessage { event.indexInBatch ) } else { - this.nitroReader = new nitro.ChainToParentChainMessageReaderNitro( + this.nitroReader = new nitro.ChildToParentChainMessageReaderNitro( ParentChainProvider, event ) @@ -286,7 +286,7 @@ export class ChildToParentChainMessageReader extends ChildToParentChainMessage { */ export class ChildToParentChainMessageWriter extends ChildToParentChainMessageReader { private readonly classicWriter?: classic.L2ToL1MessageWriterClassic - private readonly nitroWriter?: nitro.ChainToParentChainMessageWriterNitro + private readonly nitroWriter?: nitro.ChildToParentChainMessageWriterNitro /** * Instantiates a new `ChildToParentChainMessageWriter` object. @@ -310,7 +310,7 @@ export class ChildToParentChainMessageWriter extends ChildToParentChainMessageRe ParentChainProvider ) } else { - this.nitroWriter = new nitro.ChainToParentChainMessageWriterNitro( + this.nitroWriter = new nitro.ChildToParentChainMessageWriterNitro( ParentChainSigner, event, ParentChainProvider diff --git a/src/lib/message/L2ToL1MessageNitro.ts b/src/lib/message/L2ToL1MessageNitro.ts index b3ad191c87..afdf1da785 100644 --- a/src/lib/message/L2ToL1MessageNitro.ts +++ b/src/lib/message/L2ToL1MessageNitro.ts @@ -30,7 +30,7 @@ import { RollupUserLogic__factory } from '../abi/factories/RollupUserLogic__fact import { Outbox__factory } from '../abi/factories/Outbox__factory' import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory' -import { L2ToL1TxEvent as ChainToParentChainTxEvent } from '../abi/ArbSys' +import { L2ToL1TxEvent as ChildToParentChainTxEvent } from '../abi/ArbSys' import { ContractTransaction, Overrides } from 'ethers' import { EventFetcher, FetchedEvent } from '../utils/eventFetcher' import { ArbSdkError } from '../dataEntities/errors' @@ -45,19 +45,19 @@ import { ArbitrumProvider } from '../utils/arbProvider' import { ArbBlock } from '../dataEntities/rpc' import { JsonRpcProvider } from '@ethersproject/providers' import { EventArgs } from '../dataEntities/event' -import { L2ToL1MessageStatus as ChainToParentChainMessageStatus } from '../dataEntities/message' +import { L2ToL1MessageStatus as ChildToParentChainMessageStatus } from '../dataEntities/message' /** * Conditional type for Signer or Provider. If T is of type Provider - * then ChainToParentChainMessageReaderOrWriter will be of type ChainToParentChainMessageReader. - * If T is of type Signer then ChainToParentChainMessageReaderOrWriter will be of - * type ChainToParentChainMessageWriter. + * then ChildToParentChainMessageReaderOrWriter will be of type ChildToParentChainMessageReader. + * If T is of type Signer then ChildToParentChainMessageReaderOrWriter will be of + * type ChildToParentChainMessageWriter. */ -export type ChainToParentChainMessageReaderOrWriterNitro< +export type ChildToParentChainMessageReaderOrWriterNitro< T extends SignerOrProvider > = T extends Provider - ? ChainToParentChainMessageReaderNitro - : ChainToParentChainMessageWriterNitro + ? ChildToParentChainMessageReaderNitro + : ChildToParentChainMessageWriterNitro // expected number of L1 blocks that it takes for an L2 tx to be included in a L1 assertion const ASSERTION_CREATED_PADDING = 50 @@ -67,47 +67,47 @@ const ASSERTION_CONFIRMED_PADDING = 20 /** * Base functionality for nitro L2->L1 messages */ -export class ChainToParentChainMessageNitro { +export class ChildToParentChainMessageNitro { protected constructor( - public readonly event: EventArgs + public readonly event: EventArgs ) {} /** - * Instantiates a new `ChainToParentChainMessageWriterNitro` or `ChainToParentChainMessageReaderNitro` object. + * Instantiates a new `ChildToParentChainMessageWriterNitro` or `ChildToParentChainMessageReaderNitro` 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 {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. */ public static fromEvent( l1SignerOrProvider: T, - event: EventArgs, + event: EventArgs, l1Provider?: Provider - ): ChainToParentChainMessageReaderOrWriterNitro + ): ChildToParentChainMessageReaderOrWriterNitro public static fromEvent( l1SignerOrProvider: T, - event: EventArgs, + event: EventArgs, l1Provider?: Provider ): - | ChainToParentChainMessageReaderNitro - | ChainToParentChainMessageWriterNitro { + | ChildToParentChainMessageReaderNitro + | ChildToParentChainMessageWriterNitro { return SignerProviderUtils.isSigner(l1SignerOrProvider) - ? new ChainToParentChainMessageWriterNitro( + ? new ChildToParentChainMessageWriterNitro( l1SignerOrProvider, event, l1Provider ) - : new ChainToParentChainMessageReaderNitro(l1SignerOrProvider, event) + : new ChildToParentChainMessageReaderNitro(l1SignerOrProvider, event) } - public static async getChainToParentChainEvents( + public static async getChildToParentChainEvents( l2Provider: Provider, filter: { fromBlock: BlockTag; toBlock: BlockTag }, position?: BigNumber, destination?: string, hash?: BigNumber ): Promise< - (EventArgs & { transactionHash: string })[] + (EventArgs & { transactionHash: string })[] > { const eventFetcher = new EventFetcher(l2Provider) return ( @@ -123,7 +123,7 @@ export class ChainToParentChainMessageNitro { /** * Provides read-only access nitro for l2-to-l1-messages */ -export class ChainToParentChainMessageReaderNitro extends ChainToParentChainMessageNitro { +export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMessageNitro { protected sendRootHash?: string protected sendRootSize?: BigNumber protected sendRootConfirmed?: boolean @@ -132,7 +132,7 @@ export class ChainToParentChainMessageReaderNitro extends ChainToParentChainMess constructor( protected readonly l1Provider: Provider, - event: EventArgs + event: EventArgs ) { super(event) } @@ -175,12 +175,12 @@ export class ChainToParentChainMessageReaderNitro extends ChainToParentChainMess */ public async status( l2Provider: Provider - ): Promise { + ): Promise { const { sendRootConfirmed } = await this.getSendProps(l2Provider) - if (!sendRootConfirmed) return ChainToParentChainMessageStatus.UNCONFIRMED + if (!sendRootConfirmed) return ChildToParentChainMessageStatus.UNCONFIRMED return (await this.hasExecuted(l2Provider)) - ? ChainToParentChainMessageStatus.EXECUTED - : ChainToParentChainMessageStatus.CONFIRMED + ? ChildToParentChainMessageStatus.EXECUTED + : ChildToParentChainMessageStatus.CONFIRMED } private parseNodeCreatedAssertion(event: FetchedEvent) { @@ -345,8 +345,8 @@ export class ChainToParentChainMessageReaderNitro extends ChainToParentChainMess ): Promise { const status = await this.status(l2Provider) if ( - status === ChainToParentChainMessageStatus.CONFIRMED || - status === ChainToParentChainMessageStatus.EXECUTED + status === ChildToParentChainMessageStatus.CONFIRMED || + status === ChildToParentChainMessageStatus.EXECUTED ) { return } else { @@ -372,12 +372,12 @@ export class ChainToParentChainMessageReaderNitro extends ChainToParentChainMess ) const status = await this.status(l2Provider) - if (status === ChainToParentChainMessageStatus.EXECUTED) return null - if (status === ChainToParentChainMessageStatus.CONFIRMED) return null + if (status === ChildToParentChainMessageStatus.EXECUTED) return null + if (status === ChildToParentChainMessageStatus.CONFIRMED) return null // consistency check in case we change the enum in the future - if (status !== ChainToParentChainMessageStatus.UNCONFIRMED) - throw new ArbSdkError('ChainToParentChainMsg expected to be unconfirmed') + if (status !== ChildToParentChainMessageStatus.UNCONFIRMED) + throw new ArbSdkError('ChildToParentChainMsg expected to be unconfirmed') const latestBlock = await this.l1Provider.getBlockNumber() const eventFetcher = new EventFetcher(this.l1Provider) @@ -448,24 +448,24 @@ export class ChainToParentChainMessageReaderNitro extends ChainToParentChainMess /** * Provides read and write access for nitro l2-to-l1-messages */ -export class ChainToParentChainMessageWriterNitro extends ChainToParentChainMessageReaderNitro { +export class ChildToParentChainMessageWriterNitro extends ChildToParentChainMessageReaderNitro { /** - * Instantiates a new `ChainToParentChainMessageWriterNitro` object. + * Instantiates a new `ChildToParentChainMessageWriterNitro` 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 {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. */ constructor( private readonly l1Signer: Signer, - event: EventArgs, + event: EventArgs, l1Provider?: Provider ) { super(l1Provider ?? l1Signer.provider!, event) } /** - * Executes the ChainToParentChainMessage on L1. + * Executes the ChildToParentChainMessage on L1. * Will throw an error if the outbox entry has not been created, which happens when the * corresponding assertion is confirmed. * @returns @@ -475,9 +475,9 @@ export class ChainToParentChainMessageWriterNitro extends ChainToParentChainMess overrides?: Overrides ): Promise { const status = await this.status(l2Provider) - if (status !== ChainToParentChainMessageStatus.CONFIRMED) { + if (status !== ChildToParentChainMessageStatus.CONFIRMED) { throw new ArbSdkError( - `Cannot execute message. Status is: ${status} but must be ${ChainToParentChainMessageStatus.CONFIRMED}.` + `Cannot execute message. Status is: ${status} but must be ${ChildToParentChainMessageStatus.CONFIRMED}.` ) } const proof = await this.getOutboxProof(l2Provider) From 9c4d896e9907df06c378faea265297aadb8382e8 Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Mon, 2 Oct 2023 14:03:55 -0400 Subject: [PATCH 12/14] chore: rename to ParentToChildMessage --- src/index.ts | 10 +- src/lib/message/L1ToL2Message.ts | 128 ++++++++++++------------- src/lib/message/L1Transaction.ts | 14 +-- tests/integration/eth.test.ts | 2 +- tests/unit/l1toL2MessageEvents.test.ts | 2 +- 5 files changed, 76 insertions(+), 80 deletions(-) diff --git a/src/index.ts b/src/index.ts index f2f0964774..485b2027cf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,12 +32,12 @@ export { L1TransactionReceipt, } from './lib/message/L1Transaction' export { - ParentChainToChainMessageStatus as L1ToL2MessageStatus, + ParentToChildMessageStatus as L1ToL2MessageStatus, EthDepositStatus, - ParentChainToChainMessage as L1ToL2Message, - ParentChainToChainMessageReader as L1ToL2MessageReader, - ParentChainToChainMessageReaderClassic as L1ToL2MessageReaderClassic, - ParentChainToChainMessageWriter as L1ToL2MessageWriter, + ParentToChildMessage as L1ToL2Message, + ParentToChildMessageReader as L1ToL2MessageReader, + ParentToChildMessageReaderClassic as L1ToL2MessageReaderClassic, + ParentToChildMessageWriter as L1ToL2MessageWriter, } from './lib/message/L1ToL2Message' export { L1ToL2MessageGasEstimator } from './lib/message/L1ToL2MessageGasEstimator' export { argSerializerConstructor } from './lib/utils/byte_serialize_params' diff --git a/src/lib/message/L1ToL2Message.ts b/src/lib/message/L1ToL2Message.ts index 164619b549..406dba83cd 100644 --- a/src/lib/message/L1ToL2Message.ts +++ b/src/lib/message/L1ToL2Message.ts @@ -43,7 +43,7 @@ import { getTransactionReceipt, isDefined } from '../utils/lib' import { EventFetcher } from '../utils/eventFetcher' import { ErrorCode, Logger } from '@ethersproject/logger' -export enum ParentChainToChainMessageStatus { +export enum ParentToChildMessageStatus { /** * The retryable ticket has yet to be created */ @@ -90,17 +90,14 @@ interface RetryableExistsError extends Error { /** * Conditional type for Signer or Provider. If T is of type Provider - * then ParentChainToChainMessageReaderOrWriter will be of type ParentChainToChainMessageReader. - * If T is of type Signer then ParentChainToChainMessageReaderOrWriter will be of - * type ParentChainToChainMessageWriter. + * then ParentToChildMessageReaderOrWriter will be of type ParentToChildMessageReader. + * If T is of type Signer then ParentToChildMessageReaderOrWriter will be of + * type ParentToChildMessageWriter. */ -export type ParentChainToChainMessageReaderOrWriter< - T extends SignerOrProvider -> = T extends Provider - ? ParentChainToChainMessageReader - : ParentChainToChainMessageWriter +export type ParentToChildMessageReaderOrWriter = + T extends Provider ? ParentToChildMessageReader : ParentToChildMessageWriter -export abstract class ParentChainToChainMessage { +export abstract class ParentToChildMessage { /** * When messages are sent from ParentChain to Chain a retryable ticket is created on Chain. * The retryableCreationId can be used to retrieve information about the success or failure of the @@ -182,7 +179,7 @@ export abstract class ParentChainToChainMessage { messageNumber: BigNumber, parentChainBaseFee: BigNumber, messageData: RetryableMessageParams - ): ParentChainToChainMessageReaderOrWriter + ): ParentToChildMessageReaderOrWriter public static fromEventComponents( chainSignerOrProvider: T, chainId: number, @@ -190,9 +187,9 @@ export abstract class ParentChainToChainMessage { messageNumber: BigNumber, parentChainBaseFee: BigNumber, messageData: RetryableMessageParams - ): ParentChainToChainMessageReader | ParentChainToChainMessageWriter { + ): ParentToChildMessageReader | ParentToChildMessageWriter { return SignerProviderUtils.isSigner(chainSignerOrProvider) - ? new ParentChainToChainMessageWriter( + ? new ParentToChildMessageWriter( chainSignerOrProvider, chainId, sender, @@ -200,7 +197,7 @@ export abstract class ParentChainToChainMessage { parentChainBaseFee, messageData ) - : new ParentChainToChainMessageReader( + : new ParentToChildMessageReader( chainSignerOrProvider, chainId, sender, @@ -217,22 +214,21 @@ export abstract class ParentChainToChainMessage { public readonly parentChainBaseFee: BigNumber, public readonly messageData: RetryableMessageParams ) { - this.retryableCreationId = - ParentChainToChainMessage.calculateSubmitRetryableId( - chainId, - sender, - messageNumber, - parentChainBaseFee, - messageData.destAddress, - messageData.l2CallValue, - messageData.l1Value, - messageData.maxSubmissionFee, - messageData.excessFeeRefundAddress, - messageData.callValueRefundAddress, - messageData.gasLimit, - messageData.maxFeePerGas, - messageData.data - ) + this.retryableCreationId = ParentToChildMessage.calculateSubmitRetryableId( + chainId, + sender, + messageNumber, + parentChainBaseFee, + messageData.destAddress, + messageData.l2CallValue, + messageData.l1Value, + messageData.maxSubmissionFee, + messageData.excessFeeRefundAddress, + messageData.callValueRefundAddress, + messageData.gasLimit, + messageData.maxFeePerGas, + messageData.data + ) } } @@ -240,15 +236,15 @@ export abstract class ParentChainToChainMessage { * If the status is redeemed an chainTxReceipt is populated. * For all other statuses chainTxReceipt is not populated */ -export type ParentChainToChainMessageWaitResult = +export type ParentToChildMessageWaitResult = | { - status: ParentChainToChainMessageStatus.REDEEMED + status: ParentToChildMessageStatus.REDEEMED chainTxReceipt: TransactionReceipt } | { status: Exclude< - ParentChainToChainMessageStatus, - ParentChainToChainMessageStatus.REDEEMED + ParentToChildMessageStatus, + ParentToChildMessageStatus.REDEEMED > } @@ -256,7 +252,7 @@ export type EthDepositMessageWaitResult = { chainTxReceipt: TransactionReceipt | null } -export class ParentChainToChainMessageReader extends ParentChainToChainMessage { +export class ParentToChildMessageReader extends ParentToChildMessage { private retryableCreationReceipt: TransactionReceipt | undefined | null public constructor( public readonly chainProvider: Provider, @@ -321,7 +317,7 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { * 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 { + public async getSuccessfulRedeem(): Promise { const chainNetwork = await getChainNetwork(this.chainProvider) const eventFetcher = new EventFetcher(this.chainProvider) const creationReceipt = await this.getRetryableCreationReceipt() @@ -329,11 +325,11 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { if (!isDefined(creationReceipt)) { // retryable was never created, or not created yet // therefore it cant have been redeemed or be expired - return { status: ParentChainToChainMessageStatus.NOT_YET_CREATED } + return { status: ParentToChildMessageStatus.NOT_YET_CREATED } } if (creationReceipt.status === 0) { - return { status: ParentChainToChainMessageStatus.CREATION_FAILED } + return { status: ParentToChildMessageStatus.CREATION_FAILED } } // check the auto redeem first to avoid doing costly log queries in the happy case @@ -341,7 +337,7 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { if (autoRedeem && autoRedeem.status === 1) { return { chainTxReceipt: autoRedeem, - status: ParentChainToChainMessageStatus.REDEEMED, + status: ParentToChildMessageStatus.REDEEMED, } } @@ -349,7 +345,7 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { // the retryable was created and still exists // therefore it cant have been redeemed or be expired return { - status: ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN, + status: ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN, } } @@ -397,7 +393,7 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { if (successfulRedeem.length == 1) return { chainTxReceipt: successfulRedeem[0], - status: ParentChainToChainMessageStatus.REDEEMED, + status: ParentToChildMessageStatus.REDEEMED, } const toBlock = await this.chainProvider.getBlock(toBlockNumber) @@ -440,7 +436,7 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { // we know from earlier that the retryable no longer exists, so if we havent found the redemption // we know that it must have expired - return { status: ParentChainToChainMessageStatus.EXPIRED } + return { status: ParentToChildMessageStatus.EXPIRED } } /** @@ -474,7 +470,7 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { } } - public async status(): Promise { + public async status(): Promise { return (await this.getSuccessfulRedeem()).status } @@ -493,7 +489,7 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { public async waitForStatus( confirmations?: number, timeout?: number - ): Promise { + ): Promise { const chainNetwork = await getChainNetwork(this.chainId) const chosenTimeout = isDefined(timeout) @@ -557,7 +553,7 @@ export class ParentChainToChainMessageReader extends ParentChainToChainMessage { } } -export class ParentChainToChainMessageReaderClassic { +export class ParentToChildMessageReaderClassic { private retryableCreationReceipt: TransactionReceipt | undefined | null public readonly messageNumber: BigNumber public readonly retryableCreationId: string @@ -628,15 +624,15 @@ export class ParentChainToChainMessageReaderClassic { return this.retryableCreationReceipt || null } - public async status(): Promise { + public async status(): Promise { const creationReceipt = await this.getRetryableCreationReceipt() if (!isDefined(creationReceipt)) { - return ParentChainToChainMessageStatus.NOT_YET_CREATED + return ParentToChildMessageStatus.NOT_YET_CREATED } if (creationReceipt.status === 0) { - return ParentChainToChainMessageStatus.CREATION_FAILED + return ParentToChildMessageStatus.CREATION_FAILED } const chainDerivedHash = this.calculateChainDerivedHash( @@ -647,14 +643,14 @@ export class ParentChainToChainMessageReaderClassic { ) if (chainTxReceipt && chainTxReceipt.status === 1) { - return ParentChainToChainMessageStatus.REDEEMED + return ParentToChildMessageStatus.REDEEMED } - return ParentChainToChainMessageStatus.EXPIRED + return ParentToChildMessageStatus.EXPIRED } } -export class ParentChainToChainMessageWriter extends ParentChainToChainMessageReader { +export class ParentToChildMessageWriter extends ParentToChildMessageReader { public constructor( public readonly chainSigner: Signer, chainId: number, @@ -677,11 +673,11 @@ export class ParentChainToChainMessageWriter extends ParentChainToChainMessageRe /** * Manually redeem the retryable ticket. - * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + * Throws if message status is not ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async redeem(overrides?: Overrides): Promise { const status = await this.status() - if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { + if (status === ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, this.chainSigner @@ -698,10 +694,10 @@ export class ParentChainToChainMessageWriter extends ParentChainToChainMessageRe } else { throw new ArbSdkError( `Cannot redeem as retryable does not exist. Message status: ${ - ParentChainToChainMessageStatus[status] + ParentToChildMessageStatus[status] } must be: ${ - ParentChainToChainMessageStatus[ - ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ParentToChildMessageStatus[ + ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN ] }.` ) @@ -710,11 +706,11 @@ export class ParentChainToChainMessageWriter extends ParentChainToChainMessageRe /** * Cancel the retryable ticket. - * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + * Throws if message status is not ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async cancel(overrides?: Overrides): Promise { const status = await this.status() - if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { + if (status === ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, this.chainSigner @@ -723,10 +719,10 @@ export class ParentChainToChainMessageWriter extends ParentChainToChainMessageRe } else { throw new ArbSdkError( `Cannot cancel as retryable does not exist. Message status: ${ - ParentChainToChainMessageStatus[status] + ParentToChildMessageStatus[status] } must be: ${ - ParentChainToChainMessageStatus[ - ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ParentToChildMessageStatus[ + ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN ] }.` ) @@ -735,11 +731,11 @@ export class ParentChainToChainMessageWriter extends ParentChainToChainMessageRe /** * Increase the timeout of a retryable ticket. - * Throws if message status is not ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + * Throws if message status is not ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN */ public async keepAlive(overrides?: Overrides): Promise { const status = await this.status() - if (status === ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { + if (status === ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN) { const arbRetryableTx = ArbRetryableTx__factory.connect( ARB_RETRYABLE_TX_ADDRESS, this.chainSigner @@ -748,10 +744,10 @@ export class ParentChainToChainMessageWriter extends ParentChainToChainMessageRe } else { throw new ArbSdkError( `Cannot keep alive as retryable does not exist. Message status: ${ - ParentChainToChainMessageStatus[status] + ParentToChildMessageStatus[status] } must be: ${ - ParentChainToChainMessageStatus[ - ParentChainToChainMessageStatus.FUNDS_DEPOSITED_ON_CHAIN + ParentToChildMessageStatus[ + ParentToChildMessageStatus.FUNDS_DEPOSITED_ON_CHAIN ] }.` ) diff --git a/src/lib/message/L1Transaction.ts b/src/lib/message/L1Transaction.ts index 2f8d5d4ae0..9351ecb5bf 100644 --- a/src/lib/message/L1Transaction.ts +++ b/src/lib/message/L1Transaction.ts @@ -21,13 +21,13 @@ import { Log, Provider } from '@ethersproject/abstract-provider' import { ContractTransaction } from '@ethersproject/contracts' import { BigNumber } from '@ethersproject/bignumber' import { - ParentChainToChainMessage as L1ToL2Message, - ParentChainToChainMessageReaderOrWriter as L1ToL2MessageReaderOrWriter, - ParentChainToChainMessageReader as L1ToL2MessageReader, - ParentChainToChainMessageReaderClassic as L1ToL2MessageReaderClassic, - ParentChainToChainMessageWriter as L1ToL2MessageWriter, - ParentChainToChainMessageStatus as L1ToL2MessageStatus, - ParentChainToChainMessageWaitResult as L1ToL2MessageWaitResult, + ParentToChildMessage as L1ToL2Message, + ParentToChildMessageReaderOrWriter as L1ToL2MessageReaderOrWriter, + ParentToChildMessageReader as L1ToL2MessageReader, + ParentToChildMessageReaderClassic as L1ToL2MessageReaderClassic, + ParentToChildMessageWriter as L1ToL2MessageWriter, + ParentToChildMessageStatus as L1ToL2MessageStatus, + ParentToChildMessageWaitResult as L1ToL2MessageWaitResult, EthDepositMessage, EthDepositMessageWaitResult, } from './L1ToL2Message' diff --git a/tests/integration/eth.test.ts b/tests/integration/eth.test.ts index 3e6f7e3955..8cb4d8e09f 100644 --- a/tests/integration/eth.test.ts +++ b/tests/integration/eth.test.ts @@ -32,7 +32,7 @@ import { import { L2ToL1Message } from '../../src/lib/message/L2ToL1Message' import { L2ToL1MessageStatus } from '../../src/lib/dataEntities/message' import { L2TransactionReceipt } from '../../src/lib/message/L2Transaction' -import { ParentChainToChainMessageStatus as L1ToL2MessageStatus } from '../../src/lib/message/L1ToL2Message' +import { ParentToChildMessageStatus as L1ToL2MessageStatus } from '../../src/lib/message/L1ToL2Message' import { testSetup } from '../../scripts/testSetup' dotenv.config() diff --git a/tests/unit/l1toL2MessageEvents.test.ts b/tests/unit/l1toL2MessageEvents.test.ts index 65639a76eb..8e01e4c2b9 100644 --- a/tests/unit/l1toL2MessageEvents.test.ts +++ b/tests/unit/l1toL2MessageEvents.test.ts @@ -3,7 +3,7 @@ import { BigNumber, constants, providers } from 'ethers' import { JsonRpcProvider } from '@ethersproject/providers' import { expect } from 'chai' -describe('L1toL2Message events', () => { +describe('ParentToChildMessage events', () => { it('does call for nitro events', async () => { // Receipt from mainnet tx: 0x00000a61331187be51ab9ae792d74f601a5a21fb112f5b9ac5bccb23d4d5aaba const receipt: providers.TransactionReceipt = { From 1b00e27bfc9a4816b5ea9e6a3eb0994a8891f73b Mon Sep 17 00:00:00 2001 From: Doug Lance Date: Mon, 2 Oct 2023 14:10:49 -0400 Subject: [PATCH 13/14] chore: rename to ParentToChild --- src/index.ts | 6 +- src/lib/message/L2ToL1Message.ts | 77 ++++++++++++-------------- src/lib/message/L2Transaction.ts | 10 ++-- tests/integration/eth.test.ts | 4 +- tests/unit/l2toL1MessageEvents.test.ts | 20 +++---- 5 files changed, 56 insertions(+), 61 deletions(-) diff --git a/src/index.ts b/src/index.ts index 3a808e6242..f34a892d76 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,9 +23,9 @@ export { L2ContractTransaction, } from './lib/message/L2Transaction' export { - ChildToParentChainMessage as L2ToL1Message, - ChildToParentChainMessageWriter as L2ToL1MessageWriter, - ChildToParentChainMessageReader as L2ToL1MessageReader, + ChildToParentMessage as L2ToL1Message, + ChildToParentMessageWriter as L2ToL1MessageWriter, + ChildToParentMessageReader as L2ToL1MessageReader, } from './lib/message/L2ToL1Message' export { L1ContractTransaction, diff --git a/src/lib/message/L2ToL1Message.ts b/src/lib/message/L2ToL1Message.ts index 398c4a2d11..16167b4173 100644 --- a/src/lib/message/L2ToL1Message.ts +++ b/src/lib/message/L2ToL1Message.ts @@ -29,93 +29,88 @@ import { import * as classic from './L2ToL1MessageClassic' import * as nitro from './L2ToL1MessageNitro' import { - L2ToL1TransactionEvent as ClassicChildToParentChainTransactionEvent, - L2ToL1TxEvent as NitroChildToParentChainTransactionEvent, + L2ToL1TransactionEvent as ClassicChildToParentTransactionEvent, + L2ToL1TxEvent as NitroChildToParentTransactionEvent, } from '../abi/ArbSys' import { isDefined } from '../utils/lib' import { EventArgs } from '../dataEntities/event' -import { L2ToL1MessageStatus as ChildToParentChainMessageStatus } from '../dataEntities/message' +import { L2ToL1MessageStatus as ChildToParentMessageStatus } from '../dataEntities/message' import { getChainNetwork } from '../dataEntities/networks' import { ArbSdkError } from '../dataEntities/errors' -export type ChildToParentChainTransactionEvent = - | EventArgs - | EventArgs +export type ChildToParentTransactionEvent = + | EventArgs + | EventArgs /** * Conditional type for Signer or Provider. If T is of type Provider - * then ChildToParentChainMessageReaderOrWriter will be of type ChildToParentChainMessageReader. - * If T is of type Signer then ChildToParentChainMessageReaderOrWriter will be of - * type ChildToParentChainMessageWriter. + * then ChildToParentMessageReaderOrWriter will be of type ChildToParentMessageReader. + * If T is of type Signer then ChildToParentMessageReaderOrWriter will be of + * type ChildToParentMessageWriter. */ -export type ChildToParentChainMessageReaderOrWriter< - T extends SignerOrProvider -> = T extends Provider - ? ChildToParentChainMessageReader - : ChildToParentChainMessageWriter +export type ChildToParentMessageReaderOrWriter = + T extends Provider ? ChildToParentMessageReader : ChildToParentMessageWriter /** * Base functionality for Chain->ParentChain messages */ -export class ChildToParentChainMessage { +export class ChildToParentMessage { protected isClassic( - e: ChildToParentChainTransactionEvent - ): e is EventArgs { + e: ChildToParentTransactionEvent + ): e is EventArgs { return isDefined( - (e as EventArgs).indexInBatch + (e as EventArgs).indexInBatch ) } /** - * Instantiates a new `ChildToParentChainMessageWriter` or `ChildToParentChainMessageReader` object. + * Instantiates a new `ChildToParentMessageWriter` or `ChildToParentMessageReader` object. * * @param {SignerOrProvider} ParentChainSignerOrProvider Signer or provider to be used for executing or reading the Chain-to-ParentChain message. - * @param {ChildToParentChainTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. + * @param {ChildToParentTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. * @param {Provider} [ParentChainProvider] Optional. Used to override the Provider which is attached to `ParentChainSignerOrProvider` in case you need more control. This will be a required parameter in a future major version update. */ public static fromEvent( ParentChainSignerOrProvider: T, - event: ChildToParentChainTransactionEvent, + event: ChildToParentTransactionEvent, ParentChainProvider?: Provider - ): ChildToParentChainMessageReaderOrWriter + ): ChildToParentMessageReaderOrWriter static fromEvent( ParentChainSignerOrProvider: T, - event: ChildToParentChainTransactionEvent, + event: ChildToParentTransactionEvent, ParentChainProvider?: Provider - ): ChildToParentChainMessageReader | ChildToParentChainMessageWriter { + ): ChildToParentMessageReader | ChildToParentMessageWriter { return SignerProviderUtils.isSigner(ParentChainSignerOrProvider) - ? new ChildToParentChainMessageWriter( + ? new ChildToParentMessageWriter( ParentChainSignerOrProvider, event, ParentChainProvider ) - : new ChildToParentChainMessageReader(ParentChainSignerOrProvider, event) + : new ChildToParentMessageReader(ParentChainSignerOrProvider, event) } /** - * Get event logs for ChildToParentChain transactions. + * Get event logs for ChildToParent transactions. * @param ChainProvider * @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 ParentChain destination of the ChildToParentChain message + * @param destination The ParentChain 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 getChildToParentChainEvents( + public static async getChildToParentEvents( ChainProvider: Provider, filter: { fromBlock: BlockTag; toBlock: BlockTag }, position?: BigNumber, destination?: string, hash?: BigNumber, indexInBatch?: BigNumber - ): Promise< - (ChildToParentChainTransactionEvent & { transactionHash: string })[] - > { + ): Promise<(ChildToParentTransactionEvent & { transactionHash: string })[]> { const ChainNetwork = await getChainNetwork(ChainProvider) const inClassicRange = (blockTag: BlockTag, nitroGenBlock: number) => { @@ -202,13 +197,13 @@ export class ChildToParentChainMessage { /** * Provides read-only access for Chain-to-ParentChain-messages */ -export class ChildToParentChainMessageReader extends ChildToParentChainMessage { +export class ChildToParentMessageReader extends ChildToParentMessage { private readonly classicReader?: classic.L2ToL1MessageReaderClassic private readonly nitroReader?: nitro.L2ToL1MessageReaderNitro constructor( protected readonly ParentChainProvider: Provider, - event: ChildToParentChainTransactionEvent + event: ChildToParentTransactionEvent ) { super() if (this.isClassic(event)) { @@ -240,8 +235,8 @@ export class ChildToParentChainMessageReader extends ChildToParentChainMessage { */ public async status( ChainProvider: Provider - ): Promise { - // can we create an ChildToParentChainmessage here, we need to - the constructor is what we need + ): Promise { + // can we create an ChildToParentmessage here, we need to - the constructor is what we need if (this.nitroReader) return await this.nitroReader.status(ChainProvider) else return await this.classicReader!.status(ChainProvider) } @@ -284,20 +279,20 @@ export class ChildToParentChainMessageReader extends ChildToParentChainMessage { /** * Provides read and write access for Chain-to-ParentChain-messages */ -export class ChildToParentChainMessageWriter extends ChildToParentChainMessageReader { +export class ChildToParentMessageWriter extends ChildToParentMessageReader { private readonly classicWriter?: classic.L2ToL1MessageWriterClassic private readonly nitroWriter?: nitro.L2ToL1MessageWriterNitro /** - * Instantiates a new `ChildToParentChainMessageWriter` object. + * Instantiates a new `ChildToParentMessageWriter` object. * * @param {Signer} ParentChainSigner The signer to be used for executing the Chain-to-ParentChain message. - * @param {ChildToParentChainTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. + * @param {ChildToParentTransactionEvent} event The event containing the data of the Chain-to-ParentChain message. * @param {Provider} [ParentChainProvider] Optional. Used to override the Provider which is attached to `ParentChainSigner` in case you need more control. This will be a required parameter in a future major version update. */ constructor( ParentChainSigner: Signer, - event: ChildToParentChainTransactionEvent, + event: ChildToParentTransactionEvent, ParentChainProvider?: Provider ) { super(ParentChainProvider ?? ParentChainSigner.provider!, event) @@ -319,7 +314,7 @@ export class ChildToParentChainMessageWriter extends ChildToParentChainMessageRe } /** - * Executes the ChildToParentChainMessage on ParentChain. + * Executes the ChildToParentMessage on ParentChain. * Will throw an error if the outbox entry has not been created, which happens when the * corresponding assertion is confirmed. * @returns diff --git a/src/lib/message/L2Transaction.ts b/src/lib/message/L2Transaction.ts index 470d86b075..30804921bb 100644 --- a/src/lib/message/L2Transaction.ts +++ b/src/lib/message/L2Transaction.ts @@ -25,11 +25,11 @@ import { SignerOrProvider, } from '../dataEntities/signerOrProvider' import { - ChildToParentChainMessageReader as L2ToL1MessageReader, - ChildToParentChainMessageReaderOrWriter as L2ToL1MessageReaderOrWriter, - ChildToParentChainMessage as L2ToL1Message, - ChildToParentChainMessageWriter as L2ToL1MessageWriter, - ChildToParentChainTransactionEvent as L2ToL1TransactionEvent, + ChildToParentMessageReader as L2ToL1MessageReader, + ChildToParentMessageReaderOrWriter as L2ToL1MessageReaderOrWriter, + ChildToParentMessage as L2ToL1Message, + ChildToParentMessageWriter as L2ToL1MessageWriter, + ChildToParentTransactionEvent as L2ToL1TransactionEvent, } from './L2ToL1Message' import { ArbSys__factory } from '../abi/factories/ArbSys__factory' import { ArbRetryableTx__factory } from '../abi/factories/ArbRetryableTx__factory' diff --git a/tests/integration/eth.test.ts b/tests/integration/eth.test.ts index 7185c408fc..5e48ef3bfb 100644 --- a/tests/integration/eth.test.ts +++ b/tests/integration/eth.test.ts @@ -29,7 +29,7 @@ import { prettyLog, skipIfMainnet, } from './testHelpers' -import { ChildToParentChainMessage as L2ToL1Message } from '../../src/lib/message/L2ToL1Message' +import { ChildToParentMessage as L2ToL1Message } from '../../src/lib/message/L2ToL1Message' import { L2ToL1MessageStatus } from '../../src/lib/dataEntities/message' import { L2TransactionReceipt } from '../../src/lib/message/L2Transaction' import { ParentToChildMessageStatus as L1ToL2MessageStatus } from '../../src/lib/message/L1ToL2Message' @@ -231,7 +231,7 @@ describe('Ether', async () => { 'eth withdraw getWithdrawalsInL2Transaction query came back empty' ).to.exist - const withdrawEvents = await L2ToL1Message.getChildToParentChainEvents( + const withdrawEvents = await L2ToL1Message.getChildToParentEvents( l2Signer.provider!, { fromBlock: withdrawEthRec.blockNumber, toBlock: 'latest' }, undefined, diff --git a/tests/unit/l2toL1MessageEvents.test.ts b/tests/unit/l2toL1MessageEvents.test.ts index 3e0ce17e10..a6c5fc9278 100644 --- a/tests/unit/l2toL1MessageEvents.test.ts +++ b/tests/unit/l2toL1MessageEvents.test.ts @@ -18,16 +18,16 @@ import { Logger, LogLevel } from '@ethersproject/logger' Logger.setLogLevel(LogLevel.ERROR) -import { L2ToL1Message as ChildToParentChainMessage } from '../../src' +import { L2ToL1Message as ChildToParentMessage } from '../../src' import { getChainNetwork as getL2Network } from '../../src/lib/dataEntities/networks' import { providers } from 'ethers' import { anything, deepEqual, instance, mock, verify, when } from 'ts-mockito' -describe('ChildToParentChainMessage events', () => { - // ChildToParentChainTransaction +describe('ChildToParentMessage events', () => { + // ChildToParentTransaction const classicTopic = '0x5baaa87db386365b5c161be377bc3d8e317e8d98d71a3ca7ed7d555340c8f767' - // ChildToParentChainTx + // ChildToParentTx const nitroTopic = '0x3e7aafa77dbf186b7fd488006beff893744caa3c4f6f299e8a709fa2087374fc' @@ -59,7 +59,7 @@ describe('ChildToParentChainMessage events', () => { const fromBlock = 0 const toBlock = 1000 - await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { + await ChildToParentMessage.getChildToParentEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -82,7 +82,7 @@ describe('ChildToParentChainMessage events', () => { const fromBlock = l2Network.nitroGenesisBlock const toBlock = l2Network.nitroGenesisBlock + 500 - await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { + await ChildToParentMessage.getChildToParentEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -105,7 +105,7 @@ describe('ChildToParentChainMessage events', () => { const fromBlock = 0 const toBlock = l2Network.nitroGenesisBlock + 500 - await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { + await ChildToParentMessage.getChildToParentEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -138,7 +138,7 @@ describe('ChildToParentChainMessage events', () => { const fromBlock = 'earliest' const toBlock = 'latest' - await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { + await ChildToParentMessage.getChildToParentEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -171,7 +171,7 @@ describe('ChildToParentChainMessage events', () => { const fromBlock = l2Network.nitroGenesisBlock + 2 const toBlock = 'latest' - await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { + await ChildToParentMessage.getChildToParentEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) @@ -194,7 +194,7 @@ describe('ChildToParentChainMessage events', () => { const fromBlock = 'earliest' const toBlock = 'latest' - await ChildToParentChainMessage.getChildToParentChainEvents(l2Provider, { + await ChildToParentMessage.getChildToParentEvents(l2Provider, { fromBlock: fromBlock, toBlock: toBlock, }) From 37a84cb6b8144ba9b0806605d66d45722266815e Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 13 Dec 2023 07:39:30 -0500 Subject: [PATCH 14/14] rename more function internals --- src/lib/message/L2ToL1Message.ts | 6 +- src/lib/message/L2ToL1MessageNitro.ts | 254 +++++++++++++------------- 2 files changed, 133 insertions(+), 127 deletions(-) diff --git a/src/lib/message/L2ToL1Message.ts b/src/lib/message/L2ToL1Message.ts index 736203b3ae..882ed0dfa1 100644 --- a/src/lib/message/L2ToL1Message.ts +++ b/src/lib/message/L2ToL1Message.ts @@ -177,7 +177,7 @@ export class ChildToParentMessage { } if (nitroFilter.fromBlock !== nitroFilter.toBlock) { logQueries.push( - nitro.L2ToL1MessageNitro.getL2ToL1Events( + nitro.ChildToParentChainMessageNitro.getChildToParentChainEvents( childChainProvider, nitroFilter, position, @@ -210,7 +210,7 @@ export class ChildToParentMessageReader extends ChildToParentMessage { event.indexInBatch ) } else { - this.nitroReader = new nitro.L2ToL1MessageReaderNitro( + this.nitroReader = new nitro.ChildToParentChainMessageReaderNitro( parentChainProvider, event ) @@ -306,7 +306,7 @@ export class ChildToParentMessageWriter extends ChildToParentMessageReader { parentChainProvider ) } else { - this.nitroWriter = new nitro.L2ToL1MessageWriterNitro( + this.nitroWriter = new nitro.ChildToParentChainMessageWriterNitro( parentChainSigner, event, parentChainProvider diff --git a/src/lib/message/L2ToL1MessageNitro.ts b/src/lib/message/L2ToL1MessageNitro.ts index 7bdf3509ea..d6e082ea1f 100644 --- a/src/lib/message/L2ToL1MessageNitro.ts +++ b/src/lib/message/L2ToL1MessageNitro.ts @@ -60,71 +60,75 @@ export type ChildToParentChainMessageReaderOrWriterNitro< ? ChildToParentChainMessageReaderNitro : ChildToParentChainMessageWriterNitro -// 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 node deadline is passed +// expected number of parent chain blocks that it takes for a validator to confirm an parent chain block after the node deadline is passed const ASSERTION_CONFIRMED_PADDING = 20 -const l2BlockRangeCache: { [key in string]: (number | undefined)[] } = {} +const childChainBlockRangeCache: { [key in string]: (number | undefined)[] } = + {} const mutex = new Mutex() -function getL2BlockRangeCacheKey({ - l2ChainId, - l1BlockNumber, +function getChildChainBlockRangeCacheKey({ + childChainId, + parentChainBlockNumber, }: { - l2ChainId: number - l1BlockNumber: number + childChainId: number + parentChainBlockNumber: number }) { - return `${l2ChainId}-${l1BlockNumber}` + return `${childChainId}-${parentChainBlockNumber}` } -function setL2BlockRangeCache(key: string, value: (number | undefined)[]) { - l2BlockRangeCache[key] = value +function setChildChainBlockRangeCache( + key: string, + value: (number | undefined)[] +) { + childChainBlockRangeCache[key] = value } async function getBlockRangesForL1BlockWithCache({ - l1Provider, - l2Provider, - forL1Block, + parentProvider, + childProvider, + forParentChainBlock, }: { - l1Provider: JsonRpcProvider - l2Provider: JsonRpcProvider - forL1Block: number + parentProvider: JsonRpcProvider + childProvider: JsonRpcProvider + forParentChainBlock: number }) { - const l2ChainId = (await l2Provider.getNetwork()).chainId - const key = getL2BlockRangeCacheKey({ - l2ChainId, - l1BlockNumber: forL1Block, + const childChainId = (await childProvider.getNetwork()).chainId + const key = getChildChainBlockRangeCacheKey({ + childChainId, + parentChainBlockNumber: forParentChainBlock, }) - if (l2BlockRangeCache[key]) { - return l2BlockRangeCache[key] + if (childChainBlockRangeCache[key]) { + return childChainBlockRangeCache[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 (childChainBlockRangeCache[key]) { release() - return l2BlockRangeCache[key] + return childChainBlockRangeCache[key] } try { - const l2BlockRange = await getBlockRangesForL1Block({ - forL1Block, - provider: l1Provider, + const childChainBlockRange = await getBlockRangesForL1Block({ + forL1Block: forParentChainBlock, + provider: parentProvider, }) - setL2BlockRangeCache(key, l2BlockRange) + setChildChainBlockRangeCache(key, childChainBlockRange) } finally { release() } - return l2BlockRangeCache[key] + return childChainBlockRangeCache[key] } /** - * Base functionality for nitro L2->L1 messages + * Base functionality for nitro Child->Parent messages */ export class ChildToParentChainMessageNitro { protected constructor( @@ -134,33 +138,33 @@ export class ChildToParentChainMessageNitro { /** * Instantiates a new `ChildToParentChainMessageWriterNitro` or `ChildToParentChainMessageReaderNitro` 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, + parentSignerOrProvider: T, event: EventArgs, - l1Provider?: Provider + parentProvider?: Provider ): ChildToParentChainMessageReaderOrWriterNitro public static fromEvent( - l1SignerOrProvider: T, + parentSignerOrProvider: T, event: EventArgs, - l1Provider?: Provider + parentProvider?: Provider ): | ChildToParentChainMessageReaderNitro | ChildToParentChainMessageWriterNitro { - return SignerProviderUtils.isSigner(l1SignerOrProvider) + return SignerProviderUtils.isSigner(parentSignerOrProvider) ? new ChildToParentChainMessageWriterNitro( - l1SignerOrProvider, + parentSignerOrProvider, event, - l1Provider + parentProvider ) - : new ChildToParentChainMessageReaderNitro(l1SignerOrProvider, event) + : new ChildToParentChainMessageReaderNitro(parentSignerOrProvider, event) } public static async getChildToParentChainEvents( - l2Provider: Provider, + childProvider: Provider, filter: { fromBlock: BlockTag; toBlock: BlockTag }, position?: BigNumber, destination?: string, @@ -168,7 +172,7 @@ export class ChildToParentChainMessageNitro { ): Promise< (EventArgs & { transactionHash: string })[] > { - const eventFetcher = new EventFetcher(l2Provider) + const eventFetcher = new EventFetcher(childProvider) return ( await eventFetcher.getEvents( ArbSys__factory, @@ -180,7 +184,7 @@ export class ChildToParentChainMessageNitro { } /** - * Provides read-only access nitro for l2-to-l1-messages + * Provides read-only access nitro for child-to-parent-messages */ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMessageNitro { protected sendRootHash?: string @@ -190,19 +194,19 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess protected l1BatchNumber?: number constructor( - protected readonly l1Provider: Provider, + 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('Node not yet created, cannot get proof.') const nodeInterface = NodeInterface__factory.connect( NODE_INTERFACE_ADDRESS, - l2Provider + childProvider ) const outboxProofParams = @@ -217,11 +221,11 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess /** * Check if this message has already been executed in the Outbox */ - protected async hasExecuted(l2Provider: Provider): Promise { - const l2Network = await getChildChain(l2Provider) + protected async hasExecuted(childProvider: Provider): Promise { + const childChain = await getChildChain(childProvider) const outbox = Outbox__factory.connect( - l2Network.ethBridge.outbox, - this.l1Provider + childChain.ethBridge.outbox, + this.parentProvider ) return outbox.callStatic.isSpent(this.event.position) @@ -233,11 +237,11 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess * @returns */ public async status( - l2Provider: Provider + childProvider: Provider ): Promise { - const { sendRootConfirmed } = await this.getSendProps(l2Provider) + const { sendRootConfirmed } = await this.getSendProps(childProvider) if (!sendRootConfirmed) return ChildToParentChainMessageStatus.UNCONFIRMED - return (await this.hasExecuted(l2Provider)) + return (await this.hasExecuted(childProvider)) ? ChildToParentChainMessageStatus.EXECUTED : ChildToParentChainMessageStatus.CONFIRMED } @@ -252,10 +256,10 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess } private async getBlockFromNodeLog( - l2Provider: JsonRpcProvider, + childProvider: JsonRpcProvider, log: FetchedEvent | undefined ) { - const arbitrumProvider = new ArbitrumProvider(l2Provider) + const arbitrumProvider = new ArbitrumProvider(childProvider) if (!log) { console.warn('No NodeCreated events found, defaulting to block 0') @@ -263,42 +267,42 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess } const parsedLog = this.parseNodeCreatedAssertion(log) - const l2Block = await arbitrumProvider.getBlock( + const childChainBlock = await arbitrumProvider.getBlock( parsedLog.afterState.blockHash ) - if (!l2Block) { + if (!childChainBlock) { throw new ArbSdkError( `Block not found. ${parsedLog.afterState.blockHash}` ) } - if (l2Block.sendRoot !== parsedLog.afterState.sendRoot) { + if (childChainBlock.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. ${childChainBlock.sendRoot} ${parsedLog.afterState.sendRoot}` ) } - return l2Block + return childChainBlock } private async getBlockFromNodeNum( rollup: RollupUserLogic, nodeNum: BigNumber, - l2Provider: Provider + childProvider: Provider ): Promise { const { createdAtBlock } = await rollup.getNode(nodeNum) let createdFromBlock = createdAtBlock let createdToBlock = createdAtBlock - // If L1 is Arbitrum, then L2 is an Orbit chain. - if (await isArbitrumChain(this.l1Provider)) { + // If Parent is Arbitrum, then Child is an Orbit chain. + if (await isArbitrumChain(this.parentProvider)) { try { - const l2BlockRange = await getBlockRangesForL1BlockWithCache({ - l1Provider: this.l1Provider as JsonRpcProvider, - l2Provider: l2Provider as JsonRpcProvider, - forL1Block: createdAtBlock.toNumber(), + const childChainBlockRange = await getBlockRangesForL1BlockWithCache({ + parentProvider: this.parentProvider as JsonRpcProvider, + childProvider: childProvider as JsonRpcProvider, + forParentChainBlock: createdAtBlock.toNumber(), }) - const startBlock = l2BlockRange[0] - const endBlock = l2BlockRange[1] + const startBlock = childChainBlockRange[0] + const endBlock = childChainBlockRange[1] if (!startBlock || !endBlock) { throw new Error() } @@ -329,18 +333,18 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess ) return await this.getBlockFromNodeLog( - 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 @@ -354,26 +358,28 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess return this.l1BatchNumber } - protected async getSendProps(l2Provider: Provider) { + protected async getSendProps(childProvider: Provider) { if (!this.sendRootConfirmed) { - const l2Network = await getChildChain(l2Provider) + const childChain = await getChildChain(childProvider) const rollup = RollupUserLogic__factory.connect( - l2Network.ethBridge.rollup, - this.l1Provider + childChain.ethBridge.rollup, + this.parentProvider ) const latestConfirmedNodeNum = await rollup.callStatic.latestConfirmed() - const l2BlockConfirmed = await this.getBlockFromNodeNum( + const childChainBlockConfirmed = await this.getBlockFromNodeNum( rollup, latestConfirmedNodeNum, - l2Provider + childProvider ) - const sendRootSizeConfirmed = BigNumber.from(l2BlockConfirmed.sendCount) + const sendRootSizeConfirmed = BigNumber.from( + childChainBlockConfirmed.sendCount + ) if (sendRootSizeConfirmed.gt(this.event.position)) { this.sendRootSize = sendRootSizeConfirmed - this.sendRootHash = l2BlockConfirmed.sendRoot + this.sendRootHash = childChainBlockConfirmed.sendRoot this.sendRootConfirmed = true } else { // if the node has yet to be confirmed we'll still try to find proof info from unconfirmed nodes @@ -381,16 +387,16 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess if (latestNodeNum.gt(latestConfirmedNodeNum)) { // 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.getBlockFromNodeNum( + const childChainBlock = await this.getBlockFromNodeNum( rollup, latestNodeNum, - l2Provider + childProvider ) - const sendRootSize = BigNumber.from(l2Block.sendCount) + const sendRootSize = BigNumber.from(childChainBlock.sendCount) if (sendRootSize.gt(this.event.position)) { this.sendRootSize = sendRootSize - this.sendRootHash = l2Block.sendRoot + this.sendRootHash = childChainBlock.sendRoot } } } @@ -410,10 +416,10 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess * @returns */ public async waitUntilReadyToExecute( - l2Provider: Provider, + childProvider: Provider, retryDelay = 500 ): Promise { - const status = await this.status(l2Provider) + const status = await this.status(childProvider) if ( status === ChildToParentChainMessageStatus.CONFIRMED || status === ChildToParentChainMessageStatus.EXECUTED @@ -421,27 +427,27 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess return } else { await wait(retryDelay) - await this.waitUntilReadyToExecute(l2Provider, retryDelay) + await this.waitUntilReadyToExecute(childProvider, retryDelay) } } /** - * Estimates the L1 block number in which this L2 to L1 tx will be available for execution. + * Estimates the parent chain block number in which this child chain to parent chain 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 getChildChain(l2Provider) + const childChain = await getChildChain(childProvider) const rollup = RollupUserLogic__factory.connect( - l2Network.ethBridge.rollup, - this.l1Provider + childChain.ethBridge.rollup, + this.parentProvider ) - const status = await this.status(l2Provider) + const status = await this.status(childProvider) if (status === ChildToParentChainMessageStatus.EXECUTED) return null if (status === ChildToParentChainMessageStatus.CONFIRMED) return null @@ -449,8 +455,8 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess if (status !== ChildToParentChainMessageStatus.UNCONFIRMED) throw new ArbSdkError('ChildToParentChainMsg 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) const logs = ( await eventFetcher.getEvents( RollupUserLogic__factory, @@ -458,7 +464,7 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess { fromBlock: Math.max( latestBlock - - BigNumber.from(l2Network.confirmPeriodBlocks) + BigNumber.from(childChain.confirmPeriodBlocks) .add(ASSERTION_CONFIRMED_PADDING) .toNumber(), 0 @@ -469,21 +475,21 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess ) ).sort((a, b) => a.event.nodeNum.toNumber() - b.event.nodeNum.toNumber()) - const lastL2Block = + const lastChildChainBlock = logs.length === 0 ? undefined : await this.getBlockFromNodeLog( - l2Provider as JsonRpcProvider, + childProvider as JsonRpcProvider, logs[logs.length - 1] ) - const lastSendCount = lastL2Block - ? BigNumber.from(lastL2Block.sendCount) + const lastSendCount = lastChildChainBlock + ? BigNumber.from(lastChildChainBlock.sendCount) : BigNumber.from(0) - // here we assume the L2 to L1 tx is actually valid, so the user needs to wait the max time + // 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 node that includes this message yet if (lastSendCount.lte(this.event.position)) - return BigNumber.from(l2Network.confirmPeriodBlocks) + return BigNumber.from(childChain.confirmPeriodBlocks) .add(ASSERTION_CREATED_PADDING) .add(ASSERTION_CONFIRMED_PADDING) .add(latestBlock) @@ -496,11 +502,11 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess while (left <= right) { const mid = Math.floor((left + right) / 2) const log = logs[mid] - const l2Block = await this.getBlockFromNodeLog( - l2Provider as JsonRpcProvider, + const childChainBlock = await this.getBlockFromNodeLog( + childProvider as JsonRpcProvider, log ) - const sendCount = BigNumber.from(l2Block.sendCount) + const sendCount = BigNumber.from(childChainBlock.sendCount) if (sendCount.gt(this.event.position)) { foundLog = log right = mid - 1 @@ -516,45 +522,45 @@ export class ChildToParentChainMessageReaderNitro extends ChildToParentChainMess } /** - * Provides read and write access for nitro l2-to-l1-messages + * Provides read and write access for nitro child-to-Parent-messages */ export class ChildToParentChainMessageWriterNitro extends ChildToParentChainMessageReaderNitro { /** * Instantiates a new `ChildToParentChainMessageWriterNitro` 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, + private readonly parentSigner: Signer, event: EventArgs, - l1Provider?: Provider + parentProvider?: Provider ) { - super(l1Provider ?? l1Signer.provider!, event) + super(parentProvider ?? parentSigner.provider!, event) } /** - * Executes the ChildToParentChainMessage on L1. + * Executes the ChildToParentChainMessage 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) + const status = await this.status(childProvider) if (status !== ChildToParentChainMessageStatus.CONFIRMED) { throw new ArbSdkError( `Cannot execute message. Status is: ${status} but must be ${ChildToParentChainMessageStatus.CONFIRMED}.` ) } - const proof = await this.getOutboxProof(l2Provider) - const l2Network = await getChildChain(l2Provider) + const proof = await this.getOutboxProof(childProvider) + const childChain = await getChildChain(childProvider) const outbox = Outbox__factory.connect( - l2Network.ethBridge.outbox, - this.l1Signer + childChain.ethBridge.outbox, + this.parentSigner ) return await outbox.executeTransaction(