diff --git a/src/createTokenBridge-ethers.ts b/src/createTokenBridge-ethers.ts index 6ea79b36..b7c18221 100644 --- a/src/createTokenBridge-ethers.ts +++ b/src/createTokenBridge-ethers.ts @@ -1,20 +1,15 @@ /* eslint-disable no-empty */ -import { Address } from 'viem'; +import { Address, PublicClient } from 'viem'; import { BigNumber, ContractFactory, ethers } from 'ethers'; -import { JsonRpcProvider } from '@ethersproject/providers'; -import { - L1Network, - L1ToL2MessageGasEstimator, - L2Network, - addCustomNetwork, - constants as arbitrumSdkConstants, -} from '@arbitrum/sdk'; +import { L1ToL2MessageGasEstimator } from '@arbitrum/sdk'; import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib'; import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory'; import L1AtomicTokenBridgeCreator from '@arbitrum/token-bridge-contracts/build/contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol/L1AtomicTokenBridgeCreator.json'; import L2AtomicTokenBridgeFactory from '@arbitrum/token-bridge-contracts/build/contracts/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol/L2AtomicTokenBridgeFactory.json'; import { applyPercentIncrease } from './utils/gasOverrides'; import { TransactionRequestRetryableGasOverrides } from './createTokenBridgePrepareTransactionRequest'; +import { registerNewNetwork } from './utils/registerNewNetwork'; +import { publicClientToProvider } from './ethers-compat/publicClientToProvider'; type NamedFactory = ContractFactory & { contractName: string }; const NamedFactoryInstance = (contractJson: { @@ -39,12 +34,15 @@ export type CreateTokenBridgeGetInputsResult = { export const createTokenBridgeGetInputs = async ( l1DeployerAddress: string, - l1Provider: ethers.providers.JsonRpcProvider, - l2Provider: ethers.providers.JsonRpcProvider, + l1PublicClient: PublicClient, + l2PublicClient: PublicClient, l1TokenBridgeCreatorAddress: string, rollupAddress: string, retryableGasOverrides?: TransactionRequestRetryableGasOverrides, ): Promise => { + const l1Provider = publicClientToProvider(l1PublicClient); + const l2Provider = publicClientToProvider(l2PublicClient); + await registerNewNetwork(l1Provider, l2Provider, rollupAddress); const L1AtomicTokenBridgeCreator__factory = new ethers.Contract( @@ -197,11 +195,15 @@ export const getEstimateForSettingGateway = async ( l1UpgradeExecutorAddress: Address, l1GatewayRouterAddress: Address, setGatewaysCalldata: `0x${string}`, - l1Provider: ethers.providers.Provider, - l2Provider: ethers.providers.Provider, + parentChainPublicClient: PublicClient, + orbitChainPublicClient: PublicClient, ) => { - //// run retryable estimate for setting a token gateway in the router - const l1ToL2MsgGasEstimate = new L1ToL2MessageGasEstimator(l2Provider); + // ethers providers + const parentChainProvider = publicClientToProvider(parentChainPublicClient); + const orbitChainProvider = publicClientToProvider(orbitChainPublicClient); + + // run retryable estimate for setting a token gateway in the router + const l1ToL2MsgGasEstimate = new L1ToL2MessageGasEstimator(orbitChainProvider); const setGatewaysGasParams = await l1ToL2MsgGasEstimate.estimateAll( { @@ -212,8 +214,8 @@ export const getEstimateForSettingGateway = async ( callValueRefundAddress: l1ChainOwnerAddress, data: setGatewaysCalldata, }, - await getBaseFee(l1Provider), - l1Provider, + await getBaseFee(parentChainProvider), + parentChainProvider, ); return { @@ -223,76 +225,3 @@ export const getEstimateForSettingGateway = async ( deposit: setGatewaysGasParams.deposit.toBigInt(), }; }; - -const registerNewNetwork = async ( - l1Provider: JsonRpcProvider, - l2Provider: JsonRpcProvider, - rollupAddress: string, -): Promise<{ - l1Network: L1Network; - l2Network: Omit; -}> => { - const l1NetworkInfo = await l1Provider.getNetwork(); - const l2NetworkInfo = await l2Provider.getNetwork(); - - const l1Network: L1Network = { - blockTime: 10, - chainID: l1NetworkInfo.chainId, - explorerUrl: '', - isCustom: true, - name: l1NetworkInfo.name, - partnerChainIDs: [l2NetworkInfo.chainId], - isArbitrum: false, - }; - - const rollup = RollupAdminLogic__factory.connect(rollupAddress, l1Provider); - const l2Network: L2Network = { - chainID: l2NetworkInfo.chainId, - confirmPeriodBlocks: (await rollup.confirmPeriodBlocks()).toNumber(), - ethBridge: { - bridge: await rollup.bridge(), - inbox: await rollup.inbox(), - outbox: await rollup.outbox(), - rollup: rollup.address, - sequencerInbox: await rollup.sequencerInbox(), - }, - explorerUrl: '', - isArbitrum: true, - isCustom: true, - name: 'OrbitChain', - partnerChainID: l1NetworkInfo.chainId, - partnerChainIDs: [], - retryableLifetimeSeconds: 7 * 24 * 60 * 60, - nitroGenesisBlock: 0, - nitroGenesisL1Block: 0, - depositTimeout: 900000, - tokenBridge: { - l1CustomGateway: '', - l1ERC20Gateway: '', - l1GatewayRouter: '', - l1MultiCall: '', - l1ProxyAdmin: '', - l1Weth: '', - l1WethGateway: '', - l2CustomGateway: '', - l2ERC20Gateway: '', - l2GatewayRouter: '', - l2Multicall: '', - l2ProxyAdmin: '', - l2Weth: '', - l2WethGateway: '', - }, - blockTime: arbitrumSdkConstants.ARB_MINIMUM_BLOCK_TIME_IN_SECONDS, - }; - - // register - needed for retryables - addCustomNetwork({ - customL1Network: l1Network, - customL2Network: l2Network, - }); - - return { - l1Network, - l2Network, - }; -}; diff --git a/src/createTokenBridgePrepareSetWethGatewayTransactionRequest.ts b/src/createTokenBridgePrepareSetWethGatewayTransactionRequest.ts index 36c56a54..a2ee0b09 100644 --- a/src/createTokenBridgePrepareSetWethGatewayTransactionRequest.ts +++ b/src/createTokenBridgePrepareSetWethGatewayTransactionRequest.ts @@ -4,7 +4,6 @@ import { isCustomFeeTokenChain } from './utils/isCustomFeeTokenChain'; import { upgradeExecutorEncodeFunctionData } from './upgradeExecutor'; import { createTokenBridgeFetchTokenBridgeContracts } from './createTokenBridgeFetchTokenBridgeContracts'; import { createRollupFetchCoreContracts } from './createRollupFetchCoreContracts'; -import { publicClientToProvider } from './ethers-compat/publicClientToProvider'; import { getEstimateForSettingGateway } from './createTokenBridge-ethers'; import { GasOverrideOptions, applyPercentIncrease } from './utils/gasOverrides'; import { Prettify } from './types/utils'; @@ -138,10 +137,6 @@ export async function createTokenBridgePrepareSetWethGatewayTransactionRequest({ publicClient: parentChainPublicClient, }); - // ethers providers - const parentChainProvider = publicClientToProvider(parentChainPublicClient); - const orbitChainProvider = publicClientToProvider(orbitChainPublicClient); - // encode data for the setGateways call // (we first encode dummy data, to get the retryable message estimates) const setGatewaysDummyCalldata = encodeFunctionData({ @@ -160,8 +155,8 @@ export async function createTokenBridgePrepareSetWethGatewayTransactionRequest({ rollupCoreContracts.upgradeExecutor, tokenBridgeContracts.parentChainContracts.router, setGatewaysDummyCalldata, - parentChainProvider, - orbitChainProvider, + parentChainPublicClient, + orbitChainPublicClient, ); //// apply gas overrides diff --git a/src/createTokenBridgePrepareTransactionRequest.ts b/src/createTokenBridgePrepareTransactionRequest.ts index ba8b4798..5bfd7546 100644 --- a/src/createTokenBridgePrepareTransactionRequest.ts +++ b/src/createTokenBridgePrepareTransactionRequest.ts @@ -3,7 +3,6 @@ import { Address, PublicClient, encodeFunctionData } from 'viem'; import { tokenBridgeCreator } from './contracts'; import { validateParentChain } from './types/ParentChain'; import { createTokenBridgeGetInputs } from './createTokenBridge-ethers'; -import { publicClientToProvider } from './ethers-compat/publicClientToProvider'; import { isCustomFeeTokenChain } from './utils/isCustomFeeTokenChain'; import { GasOverrideOptions, @@ -48,13 +47,10 @@ export async function createTokenBridgePrepareTransactionRequest({ const tokenBridgeCreatorAddress = tokenBridgeCreatorAddressOverride ?? getTokenBridgeCreatorAddress(parentChainPublicClient); - const parentChainProvider = publicClientToProvider(parentChainPublicClient); - const orbitChainProvider = publicClientToProvider(orbitChainPublicClient); - const { inbox, maxGasForContracts, gasPrice, retryableFee } = await createTokenBridgeGetInputs( account, - parentChainProvider, - orbitChainProvider, + parentChainPublicClient, + orbitChainPublicClient, tokenBridgeCreatorAddress, params.rollup, retryableGasOverrides, diff --git a/src/package.json b/src/package.json index 2852fa6d..237ffe75 100644 --- a/src/package.json +++ b/src/package.json @@ -51,7 +51,7 @@ "viem": "^1.20.0" }, "dependencies": { - "@arbitrum/sdk": "^3.2.0", + "@arbitrum/sdk": "^3.3.2", "@arbitrum/token-bridge-contracts": "^1.2.1", "ethers": "^5.7.2" } diff --git a/src/utils/registerNewNetwork.ts b/src/utils/registerNewNetwork.ts new file mode 100644 index 00000000..3106d2cb --- /dev/null +++ b/src/utils/registerNewNetwork.ts @@ -0,0 +1,111 @@ +import { JsonRpcProvider } from '@ethersproject/providers'; +import { + L1Network, + L2Network, + addCustomNetwork, + constants as arbitrumSdkConstants, +} from '@arbitrum/sdk'; +import { + getL1Network, + getL2Network, + l1Networks, + l2Networks, +} from '@arbitrum/sdk/dist/lib/dataEntities/networks'; +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory'; + +export const registerNewNetwork = async ( + l1Provider: JsonRpcProvider, + l2Provider: JsonRpcProvider, + rollupAddress: string, +): Promise<{ + l1Network: L1Network; + l2Network: Omit; +}> => { + const l1NetworkInfo = await l1Provider.getNetwork(); + const l2NetworkInfo = await l2Provider.getNetwork(); + + const l1Network: L1Network = { + blockTime: 10, + chainID: l1NetworkInfo.chainId, + explorerUrl: '', + isCustom: true, + name: l1NetworkInfo.name, + partnerChainIDs: [l2NetworkInfo.chainId], + isArbitrum: false, + }; + + const rollup = RollupAdminLogic__factory.connect(rollupAddress, l1Provider); + const l2Network: L2Network = { + chainID: l2NetworkInfo.chainId, + confirmPeriodBlocks: (await rollup.confirmPeriodBlocks()).toNumber(), + ethBridge: { + bridge: await rollup.bridge(), + inbox: await rollup.inbox(), + outbox: await rollup.outbox(), + rollup: rollup.address, + sequencerInbox: await rollup.sequencerInbox(), + }, + explorerUrl: '', + isArbitrum: true, + isCustom: true, + name: 'OrbitChain', + partnerChainID: l1NetworkInfo.chainId, + partnerChainIDs: [], + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, + blockTime: arbitrumSdkConstants.ARB_MINIMUM_BLOCK_TIME_IN_SECONDS, + }; + + let isL1NetworkRegistered = false; + try { + await getL1Network(l1Provider); + isL1NetworkRegistered = true; + } catch { + isL1NetworkRegistered = false; + } + + let isL2NetworkRegistered = false; + try { + await getL2Network(l2Provider); + isL2NetworkRegistered = true; + } catch { + isL2NetworkRegistered = false; + } + + // both networks are already registered, do nothing + if (isL1NetworkRegistered && isL2NetworkRegistered) { + return { l1Network, l2Network }; + } + + if (!isL1NetworkRegistered) { + // we can assume if parent is not registered, that means the child isn't either, because of this check: + // https://github.com/OffchainLabs/arbitrum-sdk/blob/main/src/lib/dataEntities/networks.ts#L519 + addCustomNetwork({ customL1Network: l1Network, customL2Network: l2Network }); + } else if (!isL2NetworkRegistered) { + // parent is already registered, only register the child + addCustomNetwork({ customL2Network: l2Network }); + } + + return { + l1Network, + l2Network, + }; +}; diff --git a/yarn.lock b/yarn.lock index f132f223..f35132cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,10 +17,10 @@ "@openzeppelin/contracts-upgradeable" "4.5.2" patch-package "^6.4.7" -"@arbitrum/sdk@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.2.0.tgz#9cc2d2d1df929c7a1702f366a444d1439d17dc08" - integrity sha512-Y8NyL1EgWE8SGRFFxtqYIedQzKe7pMS9P9j0iDQ3eL1xvOf0t0WKb8vcta0cP2TcAOOpRZ3TWKPVfpBtwMsXCg== +"@arbitrum/sdk@^3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.3.2.tgz#7560548c144bdefec9831502ccc6fdc1bb8eecfa" + integrity sha512-kK7Kt8yrSe/ArOBOawdiXWKhtsrGE70svAPLkQ8aouzwALkjbF0Gs/KpQxeQpq8k6kyuIRYfgv+yS0zjnghALQ== dependencies: "@ethersproject/address" "^5.0.8" "@ethersproject/bignumber" "^5.1.1"