From 422ccdbf2f4bfd6e68070826f32d8b20cf63be81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Sun, 8 Sep 2024 13:07:21 +0200 Subject: [PATCH 01/41] refactor: split getters --- src/createRollup.ts | 2 +- ...createRollupEnoughCustomFeeTokenAllowance.ts | 2 +- ...eCustomFeeTokenApprovalTransactionRequest.ts | 2 +- src/createRollupPrepareTransactionRequest.ts | 2 +- src/createTokenBridge.ts | 5 +---- ...eTokenBridgeEnoughCustomFeeTokenAllowance.ts | 2 +- ...reateTokenBridgeFetchTokenBridgeContracts.ts | 2 +- ...eCustomFeeTokenApprovalTransactionRequest.ts | 2 +- ...reateTokenBridgePrepareTransactionRequest.ts | 2 +- src/utils/getBlockExplorerUrl.ts | 5 +++++ src/utils/getRollupCreatorAddress.ts | 16 ++++++++++++++++ ...tters.ts => getTokenBridgeCreatorAddress.ts} | 17 ----------------- src/utils/index.ts | 3 ++- 13 files changed, 32 insertions(+), 30 deletions(-) create mode 100644 src/utils/getBlockExplorerUrl.ts create mode 100644 src/utils/getRollupCreatorAddress.ts rename src/utils/{getters.ts => getTokenBridgeCreatorAddress.ts} (51%) diff --git a/src/createRollup.ts b/src/createRollup.ts index eeb20b37..fab36b79 100644 --- a/src/createRollup.ts +++ b/src/createRollup.ts @@ -8,7 +8,7 @@ import { } from './createRollupPrepareTransactionReceipt'; import { createRollupEnoughCustomFeeTokenAllowance } from './createRollupEnoughCustomFeeTokenAllowance'; import { createRollupPrepareCustomFeeTokenApprovalTransactionRequest } from './createRollupPrepareCustomFeeTokenApprovalTransactionRequest'; -import { getBlockExplorerUrl } from './utils/getters'; +import { getBlockExplorerUrl } from './utils/getBlockExplorerUrl'; import { CreateRollupTransaction, createRollupPrepareTransaction, diff --git a/src/createRollupEnoughCustomFeeTokenAllowance.ts b/src/createRollupEnoughCustomFeeTokenAllowance.ts index 1fa8e5e0..5ff4f2e4 100644 --- a/src/createRollupEnoughCustomFeeTokenAllowance.ts +++ b/src/createRollupEnoughCustomFeeTokenAllowance.ts @@ -1,7 +1,7 @@ import { Address, PublicClient, Transport, Chain } from 'viem'; import { fetchAllowance } from './utils/erc20'; -import { getRollupCreatorAddress } from './utils/getters'; +import { getRollupCreatorAddress } from './utils/getRollupCreatorAddress'; import { createRollupDefaultRetryablesFees } from './constants'; import { Prettify } from './types/utils'; diff --git a/src/createRollupPrepareCustomFeeTokenApprovalTransactionRequest.ts b/src/createRollupPrepareCustomFeeTokenApprovalTransactionRequest.ts index 6961882d..752d5433 100644 --- a/src/createRollupPrepareCustomFeeTokenApprovalTransactionRequest.ts +++ b/src/createRollupPrepareCustomFeeTokenApprovalTransactionRequest.ts @@ -2,7 +2,7 @@ import { Address, PublicClient, Transport, Chain } from 'viem'; import { approvePrepareTransactionRequest } from './utils/erc20'; import { validateParentChain } from './types/ParentChain'; -import { getRollupCreatorAddress } from './utils/getters'; +import { getRollupCreatorAddress } from './utils/getRollupCreatorAddress'; import { createRollupDefaultRetryablesFees } from './constants'; import { Prettify } from './types/utils'; diff --git a/src/createRollupPrepareTransactionRequest.ts b/src/createRollupPrepareTransactionRequest.ts index 76eee497..fa790d05 100644 --- a/src/createRollupPrepareTransactionRequest.ts +++ b/src/createRollupPrepareTransactionRequest.ts @@ -8,7 +8,7 @@ import { validateParentChain } from './types/ParentChain'; import { isCustomFeeTokenAddress } from './utils/isCustomFeeTokenAddress'; import { ChainConfig } from './types/ChainConfig'; import { isAnyTrustChainConfig } from './utils/isAnyTrustChainConfig'; -import { getRollupCreatorAddress } from './utils/getters'; +import { getRollupCreatorAddress } from './utils/getRollupCreatorAddress'; import { fetchDecimals } from './utils/erc20'; import { TransactionRequestGasOverrides, applyPercentIncrease } from './utils/gasOverrides'; diff --git a/src/createTokenBridge.ts b/src/createTokenBridge.ts index cc4291e7..25cea9ed 100644 --- a/src/createTokenBridge.ts +++ b/src/createTokenBridge.ts @@ -33,10 +33,7 @@ import { import { isCustomFeeTokenAddress } from './utils/isCustomFeeTokenAddress'; import { WithTokenBridgeCreatorAddressOverride } from './types/createTokenBridgeTypes'; import { TransactionRequestGasOverrides } from './utils/gasOverrides'; - -function getBlockExplorerUrl(chain: Chain | undefined) { - return chain?.blockExplorers?.default.url; -} +import { getBlockExplorerUrl } from './utils/getBlockExplorerUrl'; export type CreateTokenBridgeParams< TParentChain extends Chain | undefined, diff --git a/src/createTokenBridgeEnoughCustomFeeTokenAllowance.ts b/src/createTokenBridgeEnoughCustomFeeTokenAllowance.ts index 85daacbb..1d4fbb87 100644 --- a/src/createTokenBridgeEnoughCustomFeeTokenAllowance.ts +++ b/src/createTokenBridgeEnoughCustomFeeTokenAllowance.ts @@ -5,7 +5,7 @@ import { createTokenBridgeDefaultRetryablesFees } from './constants'; import { Prettify } from './types/utils'; import { WithTokenBridgeCreatorAddressOverride } from './types/createTokenBridgeTypes'; -import { getTokenBridgeCreatorAddress } from './utils/getters'; +import { getTokenBridgeCreatorAddress } from './utils/getTokenBridgeCreatorAddress'; export type CreateTokenBridgeEnoughCustomFeeTokenAllowanceParams = Prettify< diff --git a/src/createTokenBridgeFetchTokenBridgeContracts.ts b/src/createTokenBridgeFetchTokenBridgeContracts.ts index f4121be8..b1fff792 100644 --- a/src/createTokenBridgeFetchTokenBridgeContracts.ts +++ b/src/createTokenBridgeFetchTokenBridgeContracts.ts @@ -5,7 +5,7 @@ import { tokenBridgeCreatorABI } from './contracts/TokenBridgeCreator'; import { Prettify } from './types/utils'; import { WithTokenBridgeCreatorAddressOverride } from './types/createTokenBridgeTypes'; import { TokenBridgeContracts } from './types/TokenBridgeContracts'; -import { getTokenBridgeCreatorAddress } from './utils/getters'; +import { getTokenBridgeCreatorAddress } from './utils/getTokenBridgeCreatorAddress'; export type CreateTokenBridgeFetchTokenBridgeContractsParams = Prettify< diff --git a/src/createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest.ts b/src/createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest.ts index 814e8812..090258e7 100644 --- a/src/createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest.ts +++ b/src/createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest.ts @@ -5,7 +5,7 @@ import { approvePrepareTransactionRequest } from './utils/erc20'; import { Prettify } from './types/utils'; import { validateParentChain } from './types/ParentChain'; import { WithTokenBridgeCreatorAddressOverride } from './types/createTokenBridgeTypes'; -import { getTokenBridgeCreatorAddress } from './utils/getters'; +import { getTokenBridgeCreatorAddress } from './utils/getTokenBridgeCreatorAddress'; export type CreateTokenBridgePrepareCustomFeeTokenApprovalTransactionRequestParams< TChain extends Chain | undefined, diff --git a/src/createTokenBridgePrepareTransactionRequest.ts b/src/createTokenBridgePrepareTransactionRequest.ts index e357bf9f..b5c04f34 100644 --- a/src/createTokenBridgePrepareTransactionRequest.ts +++ b/src/createTokenBridgePrepareTransactionRequest.ts @@ -12,7 +12,7 @@ import { import { Prettify } from './types/utils'; import { WithTokenBridgeCreatorAddressOverride } from './types/createTokenBridgeTypes'; -import { getTokenBridgeCreatorAddress } from './utils/getters'; +import { getTokenBridgeCreatorAddress } from './utils/getTokenBridgeCreatorAddress'; export type TransactionRequestRetryableGasOverrides = { maxSubmissionCostForFactory?: GasOverrideOptions; diff --git a/src/utils/getBlockExplorerUrl.ts b/src/utils/getBlockExplorerUrl.ts new file mode 100644 index 00000000..11e45e43 --- /dev/null +++ b/src/utils/getBlockExplorerUrl.ts @@ -0,0 +1,5 @@ +import { Chain } from 'viem'; + +export function getBlockExplorerUrl(chain: Chain | undefined) { + return chain?.blockExplorers?.default.url; +} diff --git a/src/utils/getRollupCreatorAddress.ts b/src/utils/getRollupCreatorAddress.ts new file mode 100644 index 00000000..c3515c38 --- /dev/null +++ b/src/utils/getRollupCreatorAddress.ts @@ -0,0 +1,16 @@ +import { Client, Transport, Chain } from 'viem'; + +import { rollupCreatorAddress } from '../contracts/RollupCreator'; +import { validateParentChain } from '../types/ParentChain'; + +export function getRollupCreatorAddress( + client: Client, +) { + const chainId = validateParentChain(client); + + if (!rollupCreatorAddress[chainId]) { + throw new Error(`Parent chain not supported: ${chainId}`); + } + + return rollupCreatorAddress[chainId]; +} diff --git a/src/utils/getters.ts b/src/utils/getTokenBridgeCreatorAddress.ts similarity index 51% rename from src/utils/getters.ts rename to src/utils/getTokenBridgeCreatorAddress.ts index e22fa15f..5fe88893 100644 --- a/src/utils/getters.ts +++ b/src/utils/getTokenBridgeCreatorAddress.ts @@ -1,21 +1,8 @@ import { Client, Transport, Chain } from 'viem'; -import { rollupCreatorAddress } from '../contracts/RollupCreator'; import { tokenBridgeCreatorAddress } from '../contracts/TokenBridgeCreator'; import { validateParentChain } from '../types/ParentChain'; -export function getRollupCreatorAddress( - client: Client, -) { - const chainId = validateParentChain(client); - - if (!rollupCreatorAddress[chainId]) { - throw new Error(`Parent chain not supported: ${chainId}`); - } - - return rollupCreatorAddress[chainId]; -} - export function getTokenBridgeCreatorAddress( client: Client, ) { @@ -27,7 +14,3 @@ export function getTokenBridgeCreatorAddress( return tokenBridgeCreatorAddress[chainId]; } - -export function getBlockExplorerUrl(chain: Chain) { - return chain.blockExplorers?.default.url; -} diff --git a/src/utils/index.ts b/src/utils/index.ts index f9af6393..72b138ab 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -4,7 +4,8 @@ import { getParentChainLayer } from './getParentChainLayer'; import { sanitizePrivateKey } from './sanitizePrivateKey'; import { getArbOSVersion } from './getArbOSVersion'; import { getClientVersion } from './getClientVersion'; -import { getRollupCreatorAddress, getTokenBridgeCreatorAddress } from './getters'; +import { getRollupCreatorAddress } from './getRollupCreatorAddress'; +import { getTokenBridgeCreatorAddress } from './getTokenBridgeCreatorAddress'; export { generateChainId, From 615cecd4180fca3fa34dcd09b495ff2218404a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Sun, 8 Sep 2024 13:08:10 +0200 Subject: [PATCH 02/41] init custom parent chain --- src/customChains.ts | 9 +++++++++ src/customChains.unit.test.ts | 17 +++++++++++++++++ src/types/ParentChain.ts | 6 ++++-- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/customChains.ts create mode 100644 src/customChains.unit.test.ts diff --git a/src/customChains.ts b/src/customChains.ts new file mode 100644 index 00000000..902d6970 --- /dev/null +++ b/src/customChains.ts @@ -0,0 +1,9 @@ +type LooksLikeChain = { + id: number; +}; + +export const customChains: LooksLikeChain[] = []; + +export function registerCustomParentChain(chain: LooksLikeChain) { + customChains.push(chain); +} diff --git a/src/customChains.unit.test.ts b/src/customChains.unit.test.ts new file mode 100644 index 00000000..c07f7aca --- /dev/null +++ b/src/customChains.unit.test.ts @@ -0,0 +1,17 @@ +import { describe, it, expect } from 'vitest'; + +import { isValidParentChainId } from './types/ParentChain'; +import { registerCustomParentChain } from './customChains'; + +describe(`isValidParentChainId`, () => { + it(`returns "false" for an unregistered custom parent chain`, () => { + expect(isValidParentChainId(456_789)).toEqual(false); + }); + + it(`returns "true" for a registered custom parent chain`, () => { + const chainId = 123_456; + + registerCustomParentChain({ id: chainId }); + expect(isValidParentChainId(chainId)).toEqual(true); + }); +}); diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index 261a24cb..6616a0cf 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -1,8 +1,10 @@ import { Client, PublicClient, Transport, Chain } from 'viem'; -import { chains, nitroTestnodeL3 } from '../chains'; import { Prettify } from './utils'; +import { chains, nitroTestnodeL3 } from '../chains'; +import { customChains } from '../customChains'; + // exclude nitro-testnode L3 from the list of parent chains export type ParentChain = Exclude<(typeof chains)[number], { id: typeof nitroTestnodeL3.id }>; export type ParentChainId = ParentChain['id']; @@ -14,7 +16,7 @@ export type ParentChainPublicClient = Prettify export function isValidParentChainId( parentChainId: number | undefined, ): parentChainId is ParentChainId { - const ids = chains + const ids = [...chains, ...customChains] // exclude nitro-testnode L3 from the list of parent chains .filter((chain) => chain.id !== nitroTestnodeL3.id) .map((chain) => chain.id) as Number[]; From 9605b75f42026a2e4e8fc4d167ff2cce67a62424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Sun, 8 Sep 2024 13:10:35 +0200 Subject: [PATCH 03/41] hmm --- src/customChains.ts | 6 ++++-- src/utils/getParentChainFromId.ts | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/customChains.ts b/src/customChains.ts index 902d6970..f525ee44 100644 --- a/src/customChains.ts +++ b/src/customChains.ts @@ -1,9 +1,11 @@ +import { Chain } from 'viem'; + type LooksLikeChain = { id: number; }; -export const customChains: LooksLikeChain[] = []; +export const customChains: Chain[] = []; export function registerCustomParentChain(chain: LooksLikeChain) { - customChains.push(chain); + customChains.push(chain as Chain); } diff --git a/src/utils/getParentChainFromId.ts b/src/utils/getParentChainFromId.ts index 1ca8631f..c7de7eef 100644 --- a/src/utils/getParentChainFromId.ts +++ b/src/utils/getParentChainFromId.ts @@ -1,6 +1,9 @@ import { extractChain } from 'viem'; + import { ParentChain, isValidParentChainId } from '../types/ParentChain'; + import { chains } from '../chains'; +import { customChains } from '../customChains'; export function getParentChainFromId(chainId: number): ParentChain { // Just throws if the chainId is not valid @@ -9,7 +12,7 @@ export function getParentChainFromId(chainId: number): ParentChain { } return extractChain({ - chains, + chains: [...chains, ...customChains], id: chainId, }) as ParentChain; } From c0544131dbce8723f225110784b1f4267256d405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Mon, 9 Sep 2024 12:09:44 +0200 Subject: [PATCH 04/41] temp --- src/customChains.ts | 14 ++++-- src/customChainsTestHelpers.ts | 22 +++++++++ src/utils/getRollupCreatorAddress.ts | 5 ++ .../getRollupCreatorAddress.unit.test.ts | 47 +++++++++++++++++++ 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 src/customChainsTestHelpers.ts create mode 100644 src/utils/getRollupCreatorAddress.unit.test.ts diff --git a/src/customChains.ts b/src/customChains.ts index f525ee44..953fc620 100644 --- a/src/customChains.ts +++ b/src/customChains.ts @@ -1,11 +1,15 @@ -import { Chain } from 'viem'; +import { Address, Chain, ChainContract } from 'viem'; -type LooksLikeChain = { - id: number; +export type CustomParentChain = Chain & { + contracts: { + rollupCreator: ChainContract; + tokenBridgeCreator: ChainContract; + }; }; export const customChains: Chain[] = []; -export function registerCustomParentChain(chain: LooksLikeChain) { - customChains.push(chain as Chain); +export function registerCustomParentChain(chain: CustomParentChain) { + // todo: don't duplicate + customChains.push(chain); } diff --git a/src/customChainsTestHelpers.ts b/src/customChainsTestHelpers.ts new file mode 100644 index 00000000..ba4c02f4 --- /dev/null +++ b/src/customChainsTestHelpers.ts @@ -0,0 +1,22 @@ +import { Chain } from 'viem'; + +export function createCustomChain({ id }: { id: number }): Chain { + return { + id, + name: `Custom Chain (${id})`, + network: `custom-chain-${id}`, + nativeCurrency: { + name: 'Ether', + symbol: 'ETH', + decimals: 18, + }, + rpcUrls: { + public: { + http: ['http://localhost:3000'], + }, + default: { + http: ['http://localhost:3000'], + }, + }, + }; +} diff --git a/src/utils/getRollupCreatorAddress.ts b/src/utils/getRollupCreatorAddress.ts index c3515c38..920a7265 100644 --- a/src/utils/getRollupCreatorAddress.ts +++ b/src/utils/getRollupCreatorAddress.ts @@ -8,6 +8,11 @@ export function getRollupCreatorAddress( ) { const chainId = validateParentChain(client); + // check if it's a custom parent chain + if (client.chain?.contracts?.rollupCreator?.address) { + return client.chain?.contracts?.rollupCreator?.address; + } + if (!rollupCreatorAddress[chainId]) { throw new Error(`Parent chain not supported: ${chainId}`); } diff --git a/src/utils/getRollupCreatorAddress.unit.test.ts b/src/utils/getRollupCreatorAddress.unit.test.ts new file mode 100644 index 00000000..b399c762 --- /dev/null +++ b/src/utils/getRollupCreatorAddress.unit.test.ts @@ -0,0 +1,47 @@ +import { expect, it } from 'vitest'; +import { createPublicClient, http } from 'viem'; +import { sepolia } from 'viem/chains'; + +import { getRollupCreatorAddress } from './getRollupCreatorAddress'; +import { CustomParentChain, registerCustomParentChain } from '../customChains'; +import { createCustomChain } from '../customChainsTestHelpers'; + +it(`successfully returns address for Sepolia`, () => { + const client = createPublicClient({ + chain: sepolia, + transport: http(), + }); + + expect(getRollupCreatorAddress(client)).toEqual('0xfb774eA8A92ae528A596c8D90CBCF1bdBC4Cee79'); +}); + +it(`fails to return address for an unrecognized parent chain`, () => { + const client = createPublicClient({ + chain: createCustomChain({ id: 123 }), + transport: http(), + }); + + expect(() => getRollupCreatorAddress(client)).toThrowError('Parent chain not supported: 123'); +}); + +it(`successfully returns address for a registered custom parent chain`, () => { + const rollupCreator = '0x1000000000000000000000000000000000000000'; + const tokenBridgeCreator = '0x2000000000000000000000000000000000000000'; + + const chain: CustomParentChain = { + ...createCustomChain({ id: 123 }), + contracts: { + rollupCreator: { address: rollupCreator }, + tokenBridgeCreator: { address: tokenBridgeCreator }, + }, + }; + + const client = createPublicClient({ + chain, + transport: http(), + }); + + registerCustomParentChain(chain); + + expect(getRollupCreatorAddress(client)).toEqual(rollupCreator); +}); From ed0cefa7d45348d52a249b0ffc2bef7f7a9895b6 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Mon, 9 Sep 2024 18:44:58 +0200 Subject: [PATCH 05/41] add test --- src/utils/getTokenBridgeCreatorAddress.ts | 5 ++ .../getTokenBridgeCreatorAddress.unit.test.ts | 51 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/utils/getTokenBridgeCreatorAddress.unit.test.ts diff --git a/src/utils/getTokenBridgeCreatorAddress.ts b/src/utils/getTokenBridgeCreatorAddress.ts index 5fe88893..19fd0831 100644 --- a/src/utils/getTokenBridgeCreatorAddress.ts +++ b/src/utils/getTokenBridgeCreatorAddress.ts @@ -8,6 +8,11 @@ export function getTokenBridgeCreatorAddress( ) { const chainId = validateParentChain(client); + // check if it's a custom parent chain + if (client.chain?.contracts?.tokenBridgeCreator?.address) { + return client.chain?.contracts?.tokenBridgeCreator?.address; + } + if (!tokenBridgeCreatorAddress[chainId]) { throw new Error(`Parent chain not supported: ${chainId}`); } diff --git a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts new file mode 100644 index 00000000..bc586de6 --- /dev/null +++ b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts @@ -0,0 +1,51 @@ +import { expect, it } from 'vitest'; +import { createPublicClient, http } from 'viem'; +import { sepolia } from 'viem/chains'; + +import { getTokenBridgeCreatorAddress } from './getTokenBridgeCreatorAddress'; +import { CustomParentChain, registerCustomParentChain } from '../customChains'; +import { createCustomChain } from '../customChainsTestHelpers'; + +it(`successfully returns address for Sepolia`, () => { + const client = createPublicClient({ + chain: sepolia, + transport: http(), + }); + + expect(getTokenBridgeCreatorAddress(client)).toEqual( + '0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570', + ); +}); + +it(`fails to return address for an unrecognized parent chain`, () => { + const client = createPublicClient({ + chain: createCustomChain({ id: 123 }), + transport: http(), + }); + + expect(() => getTokenBridgeCreatorAddress(client)).toThrowError( + 'Parent chain not supported: 123', + ); +}); + +it(`successfully returns address for a registered custom parent chain`, () => { + const rollupCreator = '0x1000000000000000000000000000000000000000'; + const tokenBridgeCreator = '0x2000000000000000000000000000000000000000'; + + const chain: CustomParentChain = { + ...createCustomChain({ id: 123 }), + contracts: { + rollupCreator: { address: rollupCreator }, + tokenBridgeCreator: { address: tokenBridgeCreator }, + }, + }; + + const client = createPublicClient({ + chain, + transport: http(), + }); + + registerCustomParentChain(chain); + + expect(getTokenBridgeCreatorAddress(client)).toEqual(tokenBridgeCreator); +}); From 88d1a210b4778ba14dc015f1dc3d96683e75badd Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 10 Sep 2024 11:47:41 +0200 Subject: [PATCH 06/41] more --- src/createRollupPrepareTransactionRequest.ts | 7 +- ...llupPrepareTransactionRequest.unit.test.ts | 93 +++++++++++++++++++ src/customChains.ts | 16 +++- 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/src/createRollupPrepareTransactionRequest.ts b/src/createRollupPrepareTransactionRequest.ts index fa790d05..24514812 100644 --- a/src/createRollupPrepareTransactionRequest.ts +++ b/src/createRollupPrepareTransactionRequest.ts @@ -18,6 +18,7 @@ import { CreateRollupParams, WithRollupCreatorAddressOverride, } from './types/createRollupTypes'; +import { isCustomParentChain } from './customChains'; function createRollupEncodeFunctionData(args: CreateRollupFunctionInputs) { return encodeFunctionData({ @@ -72,7 +73,11 @@ export async function createRollupPrepareTransactionRequest { + // generate a random chain id + const chainId = generateChainId(); + + // create the chain config + const chainConfig = prepareChainConfig({ + chainId, + arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, + }); + + const chain: CustomParentChain = { + ...createCustomChain({ id: 123 }), + contracts: { + rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, + tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, + }, + }; + + const publicClient = createPublicClient({ + chain, + transport: http(), + }); + + registerCustomParentChain(chain); + + // prepare the transaction for deploying the core contracts + await expect( + createRollupPrepareTransactionRequest({ + params: { + config: createRollupPrepareDeploymentParamsConfig(publicClient, { + chainId: BigInt(chainId), + owner: deployer.address, + chainConfig, + }), + batchPosters: [deployer.address], + validators: [deployer.address], + }, + account: deployer.address, + publicClient, + }), + ).rejects.toThrowError(`"params.maxDataSize" must be provided when using a custom parent chain.`); +}); + it(`successfully prepares a transaction request with the default rollup creator and a gas limit override`, async () => { // generate a random chain id const chainId = generateChainId(); @@ -261,3 +306,51 @@ it(`successfully prepares a transaction request with a custom rollup creator and expect(txRequest.chainId).toEqual(arbitrumSepolia.id); expect(txRequest.gas).toEqual(1_200n); }); + +it(`successfully prepares a transaction request with a custom parent chain`, async () => { + // generate a random chain id + const chainId = generateChainId(); + + // create the chain config + const chainConfig = prepareChainConfig({ + chainId, + arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, + }); + + const chain: CustomParentChain = { + ...createCustomChain({ id: 123 }), + contracts: { + rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, + tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, + }, + }; + + const publicClient = createPublicClient({ + chain, + transport: http('https://sepolia-rollup.arbitrum.io/rpc'), + }); + + registerCustomParentChain(chain); + + const txRequest = await createRollupPrepareTransactionRequest({ + params: { + config: createRollupPrepareDeploymentParamsConfig(publicClient, { + chainId: BigInt(chainId), + owner: deployer.address, + chainConfig, + }), + batchPosters: [deployer.address], + validators: [deployer.address], + maxDataSize: 123_456n, + }, + account: deployer.address, + publicClient, + gasOverrides: { gasLimit: { base: 1_000n } }, + }); + + expect(txRequest.account).toEqual(deployer.address); + expect(txRequest.from).toEqual(deployer.address); + expect(txRequest.to).toEqual('0x1000000000000000000000000000000000000000'); + expect(txRequest.chainId).toEqual(123); + expect(txRequest.gas).toEqual(1_000n); +}); diff --git a/src/customChains.ts b/src/customChains.ts index 953fc620..3df045cb 100644 --- a/src/customChains.ts +++ b/src/customChains.ts @@ -1,4 +1,4 @@ -import { Address, Chain, ChainContract } from 'viem'; +import { Chain, ChainContract, Client } from 'viem'; export type CustomParentChain = Chain & { contracts: { @@ -13,3 +13,17 @@ export function registerCustomParentChain(chain: CustomParentChain) { // todo: don't duplicate customChains.push(chain); } + +export function isCustomParentChain(clientOrChainOrChainId: Client | Chain | number): boolean { + let chainId = -1; + + if (typeof clientOrChainOrChainId === 'number') { + chainId = clientOrChainOrChainId; + } else if (typeof (clientOrChainOrChainId as Chain).id === 'number') { + chainId = (clientOrChainOrChainId as Chain).id; + } else if (typeof (clientOrChainOrChainId as Client).chain?.id === 'number') { + chainId = (clientOrChainOrChainId as Client).chain!.id; + } + + return customChains.map((chain) => chain.id).includes(chainId); +} From b45ca098045d8c9bd50dec6b034393c63de88a70 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 10 Sep 2024 11:59:28 +0200 Subject: [PATCH 07/41] more --- ...reDeploymentParamsConfig.unit.test.ts.snap | 21 +++++ ...eateRollupPrepareDeploymentParamsConfig.ts | 13 +++ ...PrepareDeploymentParamsConfig.unit.test.ts | 84 +++++++++++++++++++ ...llupPrepareTransactionRequest.unit.test.ts | 14 ++++ 4 files changed, 132 insertions(+) diff --git a/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap b/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap index cc2e0d3d..8c259de8 100644 --- a/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap +++ b/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap @@ -1,5 +1,26 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`creates a config for a chain on top of a custom parent chain 1`] = ` +{ + "baseStake": 100000000000000000n, + "chainConfig": "{\\"homesteadBlock\\":0,\\"daoForkBlock\\":null,\\"daoForkSupport\\":true,\\"eip150Block\\":0,\\"eip150Hash\\":\\"0x0000000000000000000000000000000000000000000000000000000000000000\\",\\"eip155Block\\":0,\\"eip158Block\\":0,\\"byzantiumBlock\\":0,\\"constantinopleBlock\\":0,\\"petersburgBlock\\":0,\\"istanbulBlock\\":0,\\"muirGlacierBlock\\":0,\\"berlinBlock\\":0,\\"londonBlock\\":0,\\"clique\\":{\\"period\\":0,\\"epoch\\":0},\\"arbitrum\\":{\\"EnableArbOS\\":true,\\"AllowDebugPrecompiles\\":false,\\"DataAvailabilityCommittee\\":false,\\"InitialArbOSVersion\\":20,\\"GenesisBlockNum\\":0,\\"MaxCodeSize\\":24576,\\"MaxInitCodeSize\\":49152,\\"InitialChainOwner\\":\\"0xd8da6bf26964af9d7eed9e03e53415d37aa96045\\"},\\"chainId\\":123}", + "chainId": 123n, + "confirmPeriodBlocks": 1n, + "extraChallengeTimeBlocks": 0n, + "genesisBlockNum": 0n, + "loserStakeEscrow": "0x0000000000000000000000000000000000000000", + "owner": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", + "sequencerInboxMaxTimeVariation": { + "delayBlocks": 2n, + "delaySeconds": 4n, + "futureBlocks": 3n, + "futureSeconds": 5n, + }, + "stakeToken": "0x0000000000000000000000000000000000000000", + "wasmModuleRoot": "0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69", +} +`; + exports[`creates config for a chain on top of arbitrum one with defaults 1`] = ` { "baseStake": 100000000000000000n, diff --git a/src/createRollupPrepareDeploymentParamsConfig.ts b/src/createRollupPrepareDeploymentParamsConfig.ts index 198baff3..a28ff0d1 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.ts @@ -11,6 +11,7 @@ import { prepareChainConfig } from './prepareChainConfig'; import { defaults } from './createRollupPrepareDeploymentParamsConfigDefaults'; import { getDefaultConfirmPeriodBlocks } from './getDefaultConfirmPeriodBlocks'; import { getDefaultSequencerInboxMaxTimeVariation } from './getDefaultSequencerInboxMaxTimeVariation'; +import { isCustomParentChain } from './customChains'; export type CreateRollupPrepareDeploymentParamsConfigResult = CreateRollupFunctionInputs[0]['config']; @@ -69,6 +70,18 @@ export function createRollupPrepareDeploymentParamsConfig { }), ).toMatchSnapshot(); }); + +it('fails to create a config for a chain on top of a custom parent chain if "confirmPeriodBlocks" is not provided', () => { + const chain: CustomParentChain = { + ...createCustomChain({ id: 123 }), + contracts: { + rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, + tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, + }, + }; + + const publicClient = createPublicClient({ + chain, + transport: http('https://sepolia-rollup.arbitrum.io/rpc'), + }); + + registerCustomParentChain(chain); + + expect(() => + createRollupPrepareDeploymentParamsConfig(publicClient, { + owner: vitalik, + chainId: BigInt(chain.id), + }), + ).toThrowError('"params.confirmPeriodBlocks" must be provided when using a custom parent chain'); +}); + +it('fails to create a config for a chain on top of a custom parent chain if "sequencerInboxMaxTimeVariation" is not provided', () => { + const chain: CustomParentChain = { + ...createCustomChain({ id: 123 }), + contracts: { + rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, + tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, + }, + }; + + const publicClient = createPublicClient({ + chain, + transport: http('https://sepolia-rollup.arbitrum.io/rpc'), + }); + + registerCustomParentChain(chain); + + expect(() => + createRollupPrepareDeploymentParamsConfig(publicClient, { + owner: vitalik, + chainId: BigInt(chain.id), + confirmPeriodBlocks: 1n, + }), + ).toThrowError( + '"params.sequencerInboxMaxTimeVariation" must be provided when using a custom parent chain.', + ); +}); + +it('creates a config for a chain on top of a custom parent chain', () => { + const chain: CustomParentChain = { + ...createCustomChain({ id: 123 }), + contracts: { + rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, + tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, + }, + }; + + const publicClient = createPublicClient({ + chain, + transport: http('https://sepolia-rollup.arbitrum.io/rpc'), + }); + + registerCustomParentChain(chain); + + expect( + createRollupPrepareDeploymentParamsConfig(publicClient, { + owner: vitalik, + chainId: BigInt(chain.id), + confirmPeriodBlocks: 1n, + sequencerInboxMaxTimeVariation: { + delayBlocks: 2n, + futureBlocks: 3n, + delaySeconds: 4n, + futureSeconds: 5n, + }, + }), + ).toMatchSnapshot(); +}); diff --git a/src/createRollupPrepareTransactionRequest.unit.test.ts b/src/createRollupPrepareTransactionRequest.unit.test.ts index 079ad3dc..7cc40297 100644 --- a/src/createRollupPrepareTransactionRequest.unit.test.ts +++ b/src/createRollupPrepareTransactionRequest.unit.test.ts @@ -232,6 +232,13 @@ it(`fails to prepare transaction request if "params.maxDataSize" is not provided chainId: BigInt(chainId), owner: deployer.address, chainConfig, + confirmPeriodBlocks: 1n, + sequencerInboxMaxTimeVariation: { + delayBlocks: 2n, + futureBlocks: 3n, + delaySeconds: 4n, + futureSeconds: 5n, + }, }), batchPosters: [deployer.address], validators: [deployer.address], @@ -338,6 +345,13 @@ it(`successfully prepares a transaction request with a custom parent chain`, asy chainId: BigInt(chainId), owner: deployer.address, chainConfig, + confirmPeriodBlocks: 1n, + sequencerInboxMaxTimeVariation: { + delayBlocks: 2n, + futureBlocks: 3n, + delaySeconds: 4n, + futureSeconds: 5n, + }, }), batchPosters: [deployer.address], validators: [deployer.address], From 4bb418dbc5e94f5e6e3a2b817f3fdc9ba27fce28 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 10 Sep 2024 14:48:56 +0200 Subject: [PATCH 08/41] fix --- src/createRollupPrepareTransactionRequest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/createRollupPrepareTransactionRequest.ts b/src/createRollupPrepareTransactionRequest.ts index 24514812..4ed84b6b 100644 --- a/src/createRollupPrepareTransactionRequest.ts +++ b/src/createRollupPrepareTransactionRequest.ts @@ -77,7 +77,7 @@ export async function createRollupPrepareTransactionRequest Date: Tue, 10 Sep 2024 14:52:20 +0200 Subject: [PATCH 09/41] stuff --- src/customChains.unit.test.ts | 14 ++++++++++++-- src/utils/getRollupCreatorAddress.ts | 2 ++ src/utils/getTokenBridgeCreatorAddress.ts | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/customChains.unit.test.ts b/src/customChains.unit.test.ts index c07f7aca..c290a33f 100644 --- a/src/customChains.unit.test.ts +++ b/src/customChains.unit.test.ts @@ -1,7 +1,8 @@ import { describe, it, expect } from 'vitest'; import { isValidParentChainId } from './types/ParentChain'; -import { registerCustomParentChain } from './customChains'; +import { CustomParentChain, registerCustomParentChain } from './customChains'; +import { createCustomChain } from './customChainsTestHelpers'; describe(`isValidParentChainId`, () => { it(`returns "false" for an unregistered custom parent chain`, () => { @@ -11,7 +12,16 @@ describe(`isValidParentChainId`, () => { it(`returns "true" for a registered custom parent chain`, () => { const chainId = 123_456; - registerCustomParentChain({ id: chainId }); + const chain: CustomParentChain = { + ...createCustomChain({ id: chainId }), + contracts: { + rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, + tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, + }, + }; + + registerCustomParentChain(chain); + expect(isValidParentChainId(chainId)).toEqual(true); }); }); diff --git a/src/utils/getRollupCreatorAddress.ts b/src/utils/getRollupCreatorAddress.ts index 920a7265..f18990d8 100644 --- a/src/utils/getRollupCreatorAddress.ts +++ b/src/utils/getRollupCreatorAddress.ts @@ -9,7 +9,9 @@ export function getRollupCreatorAddress( const chainId = validateParentChain(client); // check if it's a custom parent chain + // @ts-ignore todo: fix(spsjvc) if (client.chain?.contracts?.rollupCreator?.address) { + // @ts-ignore todo: fix(spsjvc) return client.chain?.contracts?.rollupCreator?.address; } diff --git a/src/utils/getTokenBridgeCreatorAddress.ts b/src/utils/getTokenBridgeCreatorAddress.ts index 19fd0831..d49b3560 100644 --- a/src/utils/getTokenBridgeCreatorAddress.ts +++ b/src/utils/getTokenBridgeCreatorAddress.ts @@ -9,7 +9,9 @@ export function getTokenBridgeCreatorAddress( const chainId = validateParentChain(client); // check if it's a custom parent chain + // @ts-ignore todo: fix(spsjvc) if (client.chain?.contracts?.tokenBridgeCreator?.address) { + // @ts-ignore todo: fix(spsjvc) return client.chain?.contracts?.tokenBridgeCreator?.address; } From 8d4069c4d029a40748dfa350d1f45b6359498643 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 10 Sep 2024 14:55:03 +0200 Subject: [PATCH 10/41] export --- src/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/index.ts b/src/index.ts index 5cbd3c94..1faf1acd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -143,6 +143,7 @@ import { getConsensusReleaseByWasmModuleRoot, GetConsensusReleaseByWasmModuleRoot, } from './wasmModuleRoot'; +import { CustomParentChain, registerCustomParentChain } from './customChains'; export * from './actions'; export { @@ -262,4 +263,7 @@ export { isKnownWasmModuleRoot, getConsensusReleaseByWasmModuleRoot, GetConsensusReleaseByWasmModuleRoot, + // + CustomParentChain, + registerCustomParentChain, }; From b455803a9a964204f8882af6444a94b6b5a19bbf Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 10 Sep 2024 15:08:30 +0200 Subject: [PATCH 11/41] bump --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 014cd073..ac2670e4 100644 --- a/src/package.json +++ b/src/package.json @@ -1,7 +1,7 @@ { "name": "@arbitrum/orbit-sdk", "description": "TypeScript SDK for building Arbitrum Orbit chains", - "version": "0.19.0", + "version": "0.20.0-beta.0", "main": "./dist/index.js", "files": [ "./dist" From 31253669d2b3244c2b231633f4dc075994e3a7e1 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 1 Oct 2024 11:15:26 +0200 Subject: [PATCH 12/41] clean up --- src/utils/getRollupCreatorAddress.ts | 16 +++++++++------- src/utils/getTokenBridgeCreatorAddress.ts | 16 +++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/utils/getRollupCreatorAddress.ts b/src/utils/getRollupCreatorAddress.ts index f18990d8..6ab9c488 100644 --- a/src/utils/getRollupCreatorAddress.ts +++ b/src/utils/getRollupCreatorAddress.ts @@ -1,4 +1,4 @@ -import { Client, Transport, Chain } from 'viem'; +import { Client, Transport, Chain, ChainContract } from 'viem'; import { rollupCreatorAddress } from '../contracts/RollupCreator'; import { validateParentChain } from '../types/ParentChain'; @@ -6,15 +6,17 @@ import { validateParentChain } from '../types/ParentChain'; export function getRollupCreatorAddress( client: Client, ) { - const chainId = validateParentChain(client); + const customParentChainRollupCreator = client.chain?.contracts?.rollupCreator as + | ChainContract + | undefined; - // check if it's a custom parent chain - // @ts-ignore todo: fix(spsjvc) - if (client.chain?.contracts?.rollupCreator?.address) { - // @ts-ignore todo: fix(spsjvc) - return client.chain?.contracts?.rollupCreator?.address; + // check if it's a custom parent chain with the factory address provided + if (customParentChainRollupCreator?.address) { + return customParentChainRollupCreator.address; } + const chainId = validateParentChain(client); + if (!rollupCreatorAddress[chainId]) { throw new Error(`Parent chain not supported: ${chainId}`); } diff --git a/src/utils/getTokenBridgeCreatorAddress.ts b/src/utils/getTokenBridgeCreatorAddress.ts index d49b3560..2e3187b2 100644 --- a/src/utils/getTokenBridgeCreatorAddress.ts +++ b/src/utils/getTokenBridgeCreatorAddress.ts @@ -1,4 +1,4 @@ -import { Client, Transport, Chain } from 'viem'; +import { Client, Transport, Chain, ChainContract } from 'viem'; import { tokenBridgeCreatorAddress } from '../contracts/TokenBridgeCreator'; import { validateParentChain } from '../types/ParentChain'; @@ -6,15 +6,17 @@ import { validateParentChain } from '../types/ParentChain'; export function getTokenBridgeCreatorAddress( client: Client, ) { - const chainId = validateParentChain(client); + const customParentChainTokenBridgeCreator = client.chain?.contracts?.tokenBridgeCreator as + | ChainContract + | undefined; - // check if it's a custom parent chain - // @ts-ignore todo: fix(spsjvc) - if (client.chain?.contracts?.tokenBridgeCreator?.address) { - // @ts-ignore todo: fix(spsjvc) - return client.chain?.contracts?.tokenBridgeCreator?.address; + // check if it's a custom parent chain with the factory address provided + if (customParentChainTokenBridgeCreator?.address) { + return customParentChainTokenBridgeCreator?.address; } + const chainId = validateParentChain(client); + if (!tokenBridgeCreatorAddress[chainId]) { throw new Error(`Parent chain not supported: ${chainId}`); } From c2abe88f74e33f293073b873966a621ae2e53d0b Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 1 Oct 2024 11:19:39 +0200 Subject: [PATCH 13/41] update snapshot --- ...reateRollupPrepareDeploymentParamsConfig.unit.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap b/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap index 28910276..75e231b6 100644 --- a/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap +++ b/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap @@ -3,7 +3,7 @@ exports[`creates a config for a chain on top of a custom parent chain 1`] = ` { "baseStake": 100000000000000000n, - "chainConfig": "{\\"homesteadBlock\\":0,\\"daoForkBlock\\":null,\\"daoForkSupport\\":true,\\"eip150Block\\":0,\\"eip150Hash\\":\\"0x0000000000000000000000000000000000000000000000000000000000000000\\",\\"eip155Block\\":0,\\"eip158Block\\":0,\\"byzantiumBlock\\":0,\\"constantinopleBlock\\":0,\\"petersburgBlock\\":0,\\"istanbulBlock\\":0,\\"muirGlacierBlock\\":0,\\"berlinBlock\\":0,\\"londonBlock\\":0,\\"clique\\":{\\"period\\":0,\\"epoch\\":0},\\"arbitrum\\":{\\"EnableArbOS\\":true,\\"AllowDebugPrecompiles\\":false,\\"DataAvailabilityCommittee\\":false,\\"InitialArbOSVersion\\":20,\\"GenesisBlockNum\\":0,\\"MaxCodeSize\\":24576,\\"MaxInitCodeSize\\":49152,\\"InitialChainOwner\\":\\"0xd8da6bf26964af9d7eed9e03e53415d37aa96045\\"},\\"chainId\\":123}", + "chainConfig": "{\\"homesteadBlock\\":0,\\"daoForkBlock\\":null,\\"daoForkSupport\\":true,\\"eip150Block\\":0,\\"eip150Hash\\":\\"0x0000000000000000000000000000000000000000000000000000000000000000\\",\\"eip155Block\\":0,\\"eip158Block\\":0,\\"byzantiumBlock\\":0,\\"constantinopleBlock\\":0,\\"petersburgBlock\\":0,\\"istanbulBlock\\":0,\\"muirGlacierBlock\\":0,\\"berlinBlock\\":0,\\"londonBlock\\":0,\\"clique\\":{\\"period\\":0,\\"epoch\\":0},\\"arbitrum\\":{\\"EnableArbOS\\":true,\\"AllowDebugPrecompiles\\":false,\\"DataAvailabilityCommittee\\":false,\\"InitialArbOSVersion\\":32,\\"GenesisBlockNum\\":0,\\"MaxCodeSize\\":24576,\\"MaxInitCodeSize\\":49152,\\"InitialChainOwner\\":\\"0xd8da6bf26964af9d7eed9e03e53415d37aa96045\\"},\\"chainId\\":123}", "chainId": 123n, "confirmPeriodBlocks": 1n, "extraChallengeTimeBlocks": 0n, @@ -17,7 +17,7 @@ exports[`creates a config for a chain on top of a custom parent chain 1`] = ` "futureSeconds": 5n, }, "stakeToken": "0x0000000000000000000000000000000000000000", - "wasmModuleRoot": "0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69", + "wasmModuleRoot": "0x184884e1eb9fefdc158f6c8ac912bb183bf3cf83f0090317e0bc4ac5860baa39", } `; From 1d7174c6f69b6f941ecae06cadc0a8240bf2e158 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Thu, 3 Oct 2024 13:11:41 +0200 Subject: [PATCH 14/41] clean up a bit --- src/utils/getRollupCreatorAddress.unit.test.ts | 6 +++--- src/utils/getTokenBridgeCreatorAddress.unit.test.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/utils/getRollupCreatorAddress.unit.test.ts b/src/utils/getRollupCreatorAddress.unit.test.ts index b399c762..998bd18b 100644 --- a/src/utils/getRollupCreatorAddress.unit.test.ts +++ b/src/utils/getRollupCreatorAddress.unit.test.ts @@ -29,19 +29,19 @@ it(`successfully returns address for a registered custom parent chain`, () => { const tokenBridgeCreator = '0x2000000000000000000000000000000000000000'; const chain: CustomParentChain = { - ...createCustomChain({ id: 123 }), + ...createCustomChain({ id: 123_456 }), contracts: { rollupCreator: { address: rollupCreator }, tokenBridgeCreator: { address: tokenBridgeCreator }, }, }; + registerCustomParentChain(chain); + const client = createPublicClient({ chain, transport: http(), }); - registerCustomParentChain(chain); - expect(getRollupCreatorAddress(client)).toEqual(rollupCreator); }); diff --git a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts index bc586de6..d67bbe12 100644 --- a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts +++ b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts @@ -33,19 +33,19 @@ it(`successfully returns address for a registered custom parent chain`, () => { const tokenBridgeCreator = '0x2000000000000000000000000000000000000000'; const chain: CustomParentChain = { - ...createCustomChain({ id: 123 }), + ...createCustomChain({ id: 123_456 }), contracts: { rollupCreator: { address: rollupCreator }, tokenBridgeCreator: { address: tokenBridgeCreator }, }, }; + registerCustomParentChain(chain); + const client = createPublicClient({ chain, transport: http(), }); - registerCustomParentChain(chain); - expect(getTokenBridgeCreatorAddress(client)).toEqual(tokenBridgeCreator); }); From ea0d34d886e12daca26adbba2ca97bb519602949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 13:20:05 +0200 Subject: [PATCH 15/41] wip --- ...eateRollupPrepareDeploymentParamsConfig.ts | 39 +++++++++++++------ src/getDefaultConfirmPeriodBlocks.ts | 2 +- src/types/ParentChain.ts | 33 +++++++++++++--- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/createRollupPrepareDeploymentParamsConfig.ts b/src/createRollupPrepareDeploymentParamsConfig.ts index 2b64f9b5..2bbdf12f 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.ts @@ -10,8 +10,10 @@ import { prepareChainConfig } from './prepareChainConfig'; import { defaults } from './createRollupPrepareDeploymentParamsConfigDefaults'; import { getDefaultConfirmPeriodBlocks } from './getDefaultConfirmPeriodBlocks'; -import { getDefaultSequencerInboxMaxTimeVariation } from './getDefaultSequencerInboxMaxTimeVariation'; -import { isCustomParentChain } from './customChains'; +import { + SequencerInboxMaxTimeVariation, + getDefaultSequencerInboxMaxTimeVariation, +} from './getDefaultSequencerInboxMaxTimeVariation'; export type CreateRollupPrepareDeploymentParamsConfigResult = CreateRollupFunctionInputs[0]['config']; @@ -66,30 +68,45 @@ export type CreateRollupPrepareDeploymentParamsConfigParams = Prettify< */ export function createRollupPrepareDeploymentParamsConfig( client: Client, - { chainConfig, ...params }: CreateRollupPrepareDeploymentParamsConfigParams, + { + chainConfig, + confirmPeriodBlocks, + sequencerInboxMaxTimeVariation, + ...params + }: CreateRollupPrepareDeploymentParamsConfigParams, ): CreateRollupPrepareDeploymentParamsConfigResult { - const { chainId: parentChainId } = validateParentChain(client); + const { chainId: parentChainId, isCustom: parentChainIsCustom } = validateParentChain(client); - if (isCustomParentChain(client) && typeof params.confirmPeriodBlocks === 'undefined') { + if (parentChainIsCustom && typeof confirmPeriodBlocks === 'undefined') { throw new Error( `"params.confirmPeriodBlocks" must be provided when using a custom parent chain.`, ); } - if (isCustomParentChain(client) && typeof params.sequencerInboxMaxTimeVariation === 'undefined') { + if (parentChainIsCustom && typeof sequencerInboxMaxTimeVariation === 'undefined') { throw new Error( `"params.sequencerInboxMaxTimeVariation" must be provided when using a custom parent chain.`, ); } - const defaultsBasedOnParentChain = { - confirmPeriodBlocks: getDefaultConfirmPeriodBlocks(parentChainId), - sequencerInboxMaxTimeVariation: getDefaultSequencerInboxMaxTimeVariation(parentChainId), - }; + const paramsByParentBlockTime: { + confirmPeriodBlocks: bigint; + sequencerInboxMaxTimeVariation: SequencerInboxMaxTimeVariation; + } = parentChainIsCustom + ? { + // ok to use non-null assertion here because we already checked for undefined + confirmPeriodBlocks: confirmPeriodBlocks!, + // ok to use non-null assertion here because we already checked for undefined + sequencerInboxMaxTimeVariation: sequencerInboxMaxTimeVariation!, + } + : { + confirmPeriodBlocks: getDefaultConfirmPeriodBlocks(parentChainId), + sequencerInboxMaxTimeVariation: getDefaultSequencerInboxMaxTimeVariation(parentChainId), + }; return { ...defaults, - ...defaultsBasedOnParentChain, + ...paramsByParentBlockTime, ...params, chainConfig: JSON.stringify( chainConfig ?? diff --git a/src/getDefaultConfirmPeriodBlocks.ts b/src/getDefaultConfirmPeriodBlocks.ts index b3bd33eb..dbe1d64e 100644 --- a/src/getDefaultConfirmPeriodBlocks.ts +++ b/src/getDefaultConfirmPeriodBlocks.ts @@ -7,7 +7,7 @@ import { base, baseSepolia } from './chains'; export function getDefaultConfirmPeriodBlocks( parentChainIdOrClient: ParentChainId | Client, ): bigint { - const { chainId: parentChainId } = validateParentChain(parentChainIdOrClient); + const { chainId: parentChainId } = validateParentChain(parentChainIdOrClient, { custom: false }); const isMainnet = parentChainIsMainnet(parentChainId); const confirmPeriodBlocks = isMainnet ? 45_818n : 150n; diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index ee044ff1..c71c32d9 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -7,22 +7,45 @@ import { customChains } from '../customChains'; export type ParentChain = Exclude<(typeof chains)[number], { id: typeof nitroTestnodeL3.id }>; export type ParentChainId = ParentChain['id']; -function isValidParentChainId(parentChainId: number | undefined): parentChainId is ParentChainId { - const ids = [...chains, ...customChains] +function isCustomParentChain(chainId: number) { + return customChains.map((chain) => chain.id).includes(chainId); +} + +function isValidParentChainId( + parentChainId: number | undefined, + options?: { custom?: TCustom }, +): parentChainId is TCustom extends true ? number : ParentChainId { + const defaultIds = chains // exclude nitro-testnode L3 from the list of parent chains .filter((chain) => chain.id !== nitroTestnodeL3.id) .map((chain) => chain.id) as Number[]; - return ids.includes(Number(parentChainId)); + + // default to allowing custom parent chains + const custom = options?.custom ?? true; + const customIds = customChains.map((chain) => chain.id); + + if (!custom) { + return defaultIds.includes(Number(parentChainId)); + } + + return [...defaultIds, ...customIds].includes(Number(parentChainId)); } -export function validateParentChain( +export function validateParentChain< + TChain extends Chain | undefined, + TCustom extends boolean = true, +>( chainIdOrClient: number | Client, -): { chainId: ParentChainId } { + options?: { custom?: TCustom }, +): TCustom extends true + ? { chainId: number; isCustom: true } | { chainId: ParentChainId; isCustom: false } + : { chainId: ParentChainId; isCustom: false } { const chainId = typeof chainIdOrClient === 'number' ? chainIdOrClient : chainIdOrClient.chain?.id; if (!isValidParentChainId(chainId)) { throw new Error(`Parent chain not supported: ${chainId}`); } + // @ts-ignore return { chainId }; } From 7ede7308f06a98327c7758b463cbbfd2fe841e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 13:26:42 +0200 Subject: [PATCH 16/41] nice --- src/createRollupPrepareDeploymentParamsConfig.ts | 4 ++-- src/createRollupPrepareTransactionRequest.ts | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/createRollupPrepareDeploymentParamsConfig.ts b/src/createRollupPrepareDeploymentParamsConfig.ts index 2bbdf12f..4219968e 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.ts @@ -94,9 +94,9 @@ export function createRollupPrepareDeploymentParamsConfig) { - const { chainId } = validateParentChain(publicClient); + const { chainId: parentChainId, isCustom: parentChainIsCustom } = + validateParentChain(publicClient); if (params.batchPosters.length === 0 || params.batchPosters.includes(zeroAddress)) { throw new Error(`"params.batchPosters" can't be empty or contain the zero address.`); @@ -76,7 +77,7 @@ export async function createRollupPrepareTransactionRequest Date: Tue, 8 Oct 2024 13:27:06 +0200 Subject: [PATCH 17/41] remove --- src/createRollupPrepareTransactionRequest.ts | 1 - src/customChains.ts | 14 -------------- 2 files changed, 15 deletions(-) diff --git a/src/createRollupPrepareTransactionRequest.ts b/src/createRollupPrepareTransactionRequest.ts index e568bce9..a5d8ffb0 100644 --- a/src/createRollupPrepareTransactionRequest.ts +++ b/src/createRollupPrepareTransactionRequest.ts @@ -18,7 +18,6 @@ import { CreateRollupParams, WithRollupCreatorAddressOverride, } from './types/createRollupTypes'; -import { isCustomParentChain } from './customChains'; import { isKnownWasmModuleRoot, getConsensusReleaseByWasmModuleRoot } from './wasmModuleRoot'; function createRollupEncodeFunctionData(args: CreateRollupFunctionInputs) { diff --git a/src/customChains.ts b/src/customChains.ts index 3df045cb..2969de21 100644 --- a/src/customChains.ts +++ b/src/customChains.ts @@ -13,17 +13,3 @@ export function registerCustomParentChain(chain: CustomParentChain) { // todo: don't duplicate customChains.push(chain); } - -export function isCustomParentChain(clientOrChainOrChainId: Client | Chain | number): boolean { - let chainId = -1; - - if (typeof clientOrChainOrChainId === 'number') { - chainId = clientOrChainOrChainId; - } else if (typeof (clientOrChainOrChainId as Chain).id === 'number') { - chainId = (clientOrChainOrChainId as Chain).id; - } else if (typeof (clientOrChainOrChainId as Client).chain?.id === 'number') { - chainId = (clientOrChainOrChainId as Client).chain!.id; - } - - return customChains.map((chain) => chain.id).includes(chainId); -} From 5f73c3da9382546eb941844735d8892d97d424eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 13:30:27 +0200 Subject: [PATCH 18/41] tmp --- src/types/ParentChain.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index c71c32d9..969174b2 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -7,7 +7,7 @@ import { customChains } from '../customChains'; export type ParentChain = Exclude<(typeof chains)[number], { id: typeof nitroTestnodeL3.id }>; export type ParentChainId = ParentChain['id']; -function isCustomParentChain(chainId: number) { +function isCustom(chainId: number) { return customChains.map((chain) => chain.id).includes(chainId); } @@ -42,10 +42,9 @@ export function validateParentChain< : { chainId: ParentChainId; isCustom: false } { const chainId = typeof chainIdOrClient === 'number' ? chainIdOrClient : chainIdOrClient.chain?.id; - if (!isValidParentChainId(chainId)) { + if (!isValidParentChainId(chainId, options)) { throw new Error(`Parent chain not supported: ${chainId}`); } - // @ts-ignore - return { chainId }; + return { chainId, isCustom: isCustom(chainId) } as any; } From e44f7e914658690992265c59521ae2b39e52b036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 13:34:36 +0200 Subject: [PATCH 19/41] update test --- src/customChains.unit.test.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/customChains.unit.test.ts b/src/customChains.unit.test.ts index c290a33f..520c1764 100644 --- a/src/customChains.unit.test.ts +++ b/src/customChains.unit.test.ts @@ -1,19 +1,21 @@ import { describe, it, expect } from 'vitest'; -import { isValidParentChainId } from './types/ParentChain'; +import { validateParentChain } from './types/ParentChain'; import { CustomParentChain, registerCustomParentChain } from './customChains'; import { createCustomChain } from './customChainsTestHelpers'; -describe(`isValidParentChainId`, () => { - it(`returns "false" for an unregistered custom parent chain`, () => { - expect(isValidParentChainId(456_789)).toEqual(false); +describe(`validateParentChain`, () => { + it(`throws for an unregistered custom parent chain`, () => { + const id = 456_789; + + expect(() => validateParentChain(id)).toThrowError(`Parent chain not supported: ${id}`); }); - it(`returns "true" for a registered custom parent chain`, () => { - const chainId = 123_456; + it(`works for a registered custom parent chain`, () => { + const id = 123_456; const chain: CustomParentChain = { - ...createCustomChain({ id: chainId }), + ...createCustomChain({ id }), contracts: { rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, @@ -22,6 +24,9 @@ describe(`isValidParentChainId`, () => { registerCustomParentChain(chain); - expect(isValidParentChainId(chainId)).toEqual(true); + const result = validateParentChain(id); + + expect(result.chainId).toEqual(id); + expect(result.isCustom).toEqual(true); }); }); From 28b3ded8079bb4ad1fee051573f1d01236f69771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 13:38:17 +0200 Subject: [PATCH 20/41] fix --- src/prepareNodeConfig.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/prepareNodeConfig.ts b/src/prepareNodeConfig.ts index a5481e83..9f37a3ed 100644 --- a/src/prepareNodeConfig.ts +++ b/src/prepareNodeConfig.ts @@ -31,6 +31,7 @@ export type PrepareNodeConfigParams = { batchPosterPrivateKey: string; validatorPrivateKey: string; parentChainId: ParentChainId; + parentChainIsArbitrum?: boolean; parentChainRpcUrl: string; parentChainBeaconRpcUrl?: string; dasServerUrl?: string; @@ -51,6 +52,7 @@ export function prepareNodeConfig({ batchPosterPrivateKey, validatorPrivateKey, parentChainId, + parentChainIsArbitrum: parentChainIsArbitrumParam, parentChainRpcUrl, parentChainBeaconRpcUrl, dasServerUrl, @@ -60,7 +62,14 @@ export function prepareNodeConfig({ throw new Error(`"parentChainBeaconRpcUrl" is required for L2 Orbit chains.`); } - const { chainId: parentChainIdValidated } = validateParentChain(parentChainId); + const { chainId: parentChainIdValidated, isCustom: parentChainIsCustom } = + validateParentChain(parentChainId); + + if (parentChainIsCustom && typeof parentChainIsArbitrumParam === 'undefined') { + throw new Error( + `"params.parentChainIsArbitrumParam" must be provided when using a custom parent chain.`, + ); + } const config: NodeConfig = { 'chain': { @@ -68,7 +77,9 @@ export function prepareNodeConfig({ { 'chain-id': chainConfig.chainId, 'parent-chain-id': parentChainId, - 'parent-chain-is-arbitrum': parentChainIsArbitrum(parentChainIdValidated), + 'parent-chain-is-arbitrum': parentChainIsCustom + ? parentChainIsArbitrumParam! + : parentChainIsArbitrum(parentChainIdValidated), 'chain-name': chainName, 'chain-config': chainConfig, 'rollup': { From 8e8b42068c08ca358fb5312de4f84afb3aca9ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 13:41:29 +0200 Subject: [PATCH 21/41] fix --- src/createRollupFetchTransactionHash.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/createRollupFetchTransactionHash.ts b/src/createRollupFetchTransactionHash.ts index c1c2e8b9..a61866eb 100644 --- a/src/createRollupFetchTransactionHash.ts +++ b/src/createRollupFetchTransactionHash.ts @@ -1,7 +1,7 @@ import { Address, PublicClient, Transport, Chain } from 'viem'; import { AbiEvent } from 'abitype'; -import { validateParentChain } from './types/ParentChain'; +import { ParentChainId, validateParentChain } from './types/ParentChain'; import { mainnet, arbitrumOne, @@ -40,7 +40,9 @@ const RollupInitializedEventAbi: AbiEvent = { type: 'event', }; -const earliestRollupCreatorDeploymentBlockNumber = { +const earliestRollupCreatorDeploymentBlockNumber: { + [Key in ParentChainId]: bigint; +} = { // mainnet L1 [mainnet.id]: 18736164n, // mainnet L2 @@ -62,12 +64,12 @@ export async function createRollupFetchTransactionHash) { - const { chainId } = validateParentChain(publicClient); + const { chainId: parentChainId, isCustom: parentChainIsCustom } = + validateParentChain(publicClient); - const fromBlock = - chainId in earliestRollupCreatorDeploymentBlockNumber - ? earliestRollupCreatorDeploymentBlockNumber[chainId] - : 'earliest'; + const fromBlock = parentChainIsCustom + ? 'earliest' + : earliestRollupCreatorDeploymentBlockNumber[parentChainId]; // Find the RollupInitialized event from that Rollup contract const rollupInitializedEvents = await publicClient.getLogs({ From b7cb59d94b71d9c691df05d899050194a45d547c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 13:45:45 +0200 Subject: [PATCH 22/41] fixes --- src/utils/getRollupCreatorAddress.ts | 27 ++++++++++++----------- src/utils/getTokenBridgeCreatorAddress.ts | 23 ++++++++++--------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/utils/getRollupCreatorAddress.ts b/src/utils/getRollupCreatorAddress.ts index 6ccba897..950ee64f 100644 --- a/src/utils/getRollupCreatorAddress.ts +++ b/src/utils/getRollupCreatorAddress.ts @@ -1,25 +1,26 @@ -import { Client, Transport, Chain, ChainContract } from 'viem'; +import { Client, Transport, Chain, ChainContract, Address } from 'viem'; import { rollupCreatorAddress } from '../contracts/RollupCreator'; import { validateParentChain } from '../types/ParentChain'; export function getRollupCreatorAddress( client: Client, -) { - const customParentChainRollupCreator = client.chain?.contracts?.rollupCreator as - | ChainContract - | undefined; +): Address { + const { chainId: parentChainId, isCustom: parentChainIsCustom } = validateParentChain(client); - // check if it's a custom parent chain with the factory address provided - if (customParentChainRollupCreator?.address) { - return customParentChainRollupCreator.address; - } + if (parentChainIsCustom) { + const customParentChainRollupCreator = client.chain?.contracts?.rollupCreator as + | ChainContract + | undefined; + + // check if it's a custom parent chain with the factory address provided - const { chainId } = validateParentChain(client); + if (!customParentChainRollupCreator?.address) { + throw new Error('invalid rollup creator address provided'); + } - if (!rollupCreatorAddress[chainId]) { - throw new Error(`Parent chain not supported: ${chainId}`); + return customParentChainRollupCreator?.address; } - return rollupCreatorAddress[chainId]; + return rollupCreatorAddress[parentChainId]; } diff --git a/src/utils/getTokenBridgeCreatorAddress.ts b/src/utils/getTokenBridgeCreatorAddress.ts index 61cbc378..33e5409a 100644 --- a/src/utils/getTokenBridgeCreatorAddress.ts +++ b/src/utils/getTokenBridgeCreatorAddress.ts @@ -6,20 +6,21 @@ import { validateParentChain } from '../types/ParentChain'; export function getTokenBridgeCreatorAddress( client: Client, ) { - const customParentChainTokenBridgeCreator = client.chain?.contracts?.tokenBridgeCreator as - | ChainContract - | undefined; + const { chainId: parentChainId, isCustom: parentChainIsCustom } = validateParentChain(client); - // check if it's a custom parent chain with the factory address provided - if (customParentChainTokenBridgeCreator?.address) { - return customParentChainTokenBridgeCreator?.address; - } + if (parentChainIsCustom) { + const customParentChainTokenBridgeCreator = client.chain?.contracts?.tokenBridgeCreator as + | ChainContract + | undefined; - const { chainId } = validateParentChain(client); + // check if it's a custom parent chain with the factory address provided - if (!tokenBridgeCreatorAddress[chainId]) { - throw new Error(`Parent chain not supported: ${chainId}`); + if (!customParentChainTokenBridgeCreator?.address) { + throw new Error('invalid token bridge creator address provided'); + } + + return customParentChainTokenBridgeCreator?.address; } - return tokenBridgeCreatorAddress[chainId]; + return tokenBridgeCreatorAddress[parentChainId]; } From 6e17a34cb9d0a634a577f56bf0f9bdf26be30ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 14:13:30 +0200 Subject: [PATCH 23/41] fix --- src/createRollupPrepareDeploymentParamsConfig.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/createRollupPrepareDeploymentParamsConfig.ts b/src/createRollupPrepareDeploymentParamsConfig.ts index 4219968e..3407f59c 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.ts @@ -100,8 +100,9 @@ export function createRollupPrepareDeploymentParamsConfig Date: Tue, 8 Oct 2024 14:16:22 +0200 Subject: [PATCH 24/41] nice --- src/getDefaultConfirmPeriodBlocks.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/getDefaultConfirmPeriodBlocks.ts b/src/getDefaultConfirmPeriodBlocks.ts index dbe1d64e..6a10b104 100644 --- a/src/getDefaultConfirmPeriodBlocks.ts +++ b/src/getDefaultConfirmPeriodBlocks.ts @@ -7,7 +7,14 @@ import { base, baseSepolia } from './chains'; export function getDefaultConfirmPeriodBlocks( parentChainIdOrClient: ParentChainId | Client, ): bigint { - const { chainId: parentChainId } = validateParentChain(parentChainIdOrClient, { custom: false }); + const { chainId: parentChainId, isCustom: parentChainIsCustom } = + validateParentChain(parentChainIdOrClient); + + if (parentChainIsCustom) { + throw new Error( + `[getDefaultConfirmPeriodBlocks] can't provide defaults for custom parent chain with id ${parentChainId}`, + ); + } const isMainnet = parentChainIsMainnet(parentChainId); const confirmPeriodBlocks = isMainnet ? 45_818n : 150n; From 9ff31f86ea96292b225a4fad07b50a029dbd85df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Tue, 8 Oct 2024 14:19:52 +0200 Subject: [PATCH 25/41] simplify --- src/types/ParentChain.ts | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index 969174b2..8bcbdf05 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -11,40 +11,24 @@ function isCustom(chainId: number) { return customChains.map((chain) => chain.id).includes(chainId); } -function isValidParentChainId( - parentChainId: number | undefined, - options?: { custom?: TCustom }, -): parentChainId is TCustom extends true ? number : ParentChainId { - const defaultIds = chains +function isValidParentChainId(parentChainId: number | undefined): parentChainId is number { + const ids = [...chains, ...customChains] // exclude nitro-testnode L3 from the list of parent chains .filter((chain) => chain.id !== nitroTestnodeL3.id) .map((chain) => chain.id) as Number[]; - - // default to allowing custom parent chains - const custom = options?.custom ?? true; - const customIds = customChains.map((chain) => chain.id); - - if (!custom) { - return defaultIds.includes(Number(parentChainId)); - } - - return [...defaultIds, ...customIds].includes(Number(parentChainId)); + return ids.includes(Number(parentChainId)); } -export function validateParentChain< - TChain extends Chain | undefined, - TCustom extends boolean = true, ->( +export function validateParentChain( chainIdOrClient: number | Client, - options?: { custom?: TCustom }, -): TCustom extends true - ? { chainId: number; isCustom: true } | { chainId: ParentChainId; isCustom: false } - : { chainId: ParentChainId; isCustom: false } { +): { chainId: number; isCustom: true } | { chainId: ParentChainId; isCustom: false } { const chainId = typeof chainIdOrClient === 'number' ? chainIdOrClient : chainIdOrClient.chain?.id; - if (!isValidParentChainId(chainId, options)) { + if (!isValidParentChainId(chainId)) { throw new Error(`Parent chain not supported: ${chainId}`); } - return { chainId, isCustom: isCustom(chainId) } as any; + return { chainId, isCustom: isCustom(chainId) } as + | { chainId: number; isCustom: true } + | { chainId: ParentChainId; isCustom: false }; } From 34fc9fb479b923dfcde5806acc7dab464383ddff Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 16:02:41 +0200 Subject: [PATCH 26/41] refactor --- ...eateRollupPrepareDeploymentParamsConfig.ts | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/createRollupPrepareDeploymentParamsConfig.ts b/src/createRollupPrepareDeploymentParamsConfig.ts index 3407f59c..cee50dbf 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.ts @@ -89,21 +89,26 @@ export function createRollupPrepareDeploymentParamsConfig Date: Wed, 9 Oct 2024 17:23:18 +0200 Subject: [PATCH 27/41] fix --- ...eateRollupPrepareDeploymentParamsConfig.ts | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/createRollupPrepareDeploymentParamsConfig.ts b/src/createRollupPrepareDeploymentParamsConfig.ts index cee50dbf..79af5162 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.ts @@ -77,28 +77,27 @@ export function createRollupPrepareDeploymentParamsConfig Date: Wed, 9 Oct 2024 17:24:25 +0200 Subject: [PATCH 28/41] fix --- src/types/ParentChain.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index 8bcbdf05..2fda9882 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -28,7 +28,9 @@ export function validateParentChain( throw new Error(`Parent chain not supported: ${chainId}`); } - return { chainId, isCustom: isCustom(chainId) } as - | { chainId: number; isCustom: true } - | { chainId: ParentChainId; isCustom: false }; + if (isCustom(chainId)) { + return { chainId, isCustom: true }; + } + + return { chainId: chainId as ParentChainId, isCustom: false }; } From d49fc2628d647abec960ea684b667a08c6426810 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 18:23:03 +0200 Subject: [PATCH 29/41] refactor --- src/utils/getRollupCreatorAddress.ts | 15 +++++++-------- src/utils/getTokenBridgeCreatorAddress.ts | 15 +++++++-------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/utils/getRollupCreatorAddress.ts b/src/utils/getRollupCreatorAddress.ts index 950ee64f..97edac91 100644 --- a/src/utils/getRollupCreatorAddress.ts +++ b/src/utils/getRollupCreatorAddress.ts @@ -9,17 +9,16 @@ export function getRollupCreatorAddress( const { chainId: parentChainId, isCustom: parentChainIsCustom } = validateParentChain(client); if (parentChainIsCustom) { - const customParentChainRollupCreator = client.chain?.contracts?.rollupCreator as - | ChainContract - | undefined; + const contract = client.chain?.contracts?.rollupCreator as ChainContract | undefined; + const address = contract?.address; - // check if it's a custom parent chain with the factory address provided - - if (!customParentChainRollupCreator?.address) { - throw new Error('invalid rollup creator address provided'); + if (typeof address === 'undefined') { + throw new Error( + `Address for RollupCreator is missing on custom parent chain with id ${parentChainId}`, + ); } - return customParentChainRollupCreator?.address; + return address; } return rollupCreatorAddress[parentChainId]; diff --git a/src/utils/getTokenBridgeCreatorAddress.ts b/src/utils/getTokenBridgeCreatorAddress.ts index 33e5409a..aa7c9485 100644 --- a/src/utils/getTokenBridgeCreatorAddress.ts +++ b/src/utils/getTokenBridgeCreatorAddress.ts @@ -9,17 +9,16 @@ export function getTokenBridgeCreatorAddress( const { chainId: parentChainId, isCustom: parentChainIsCustom } = validateParentChain(client); if (parentChainIsCustom) { - const customParentChainTokenBridgeCreator = client.chain?.contracts?.tokenBridgeCreator as - | ChainContract - | undefined; + const contract = client.chain?.contracts?.tokenBridgeCreator as ChainContract | undefined; + const address = contract?.address; - // check if it's a custom parent chain with the factory address provided - - if (!customParentChainTokenBridgeCreator?.address) { - throw new Error('invalid token bridge creator address provided'); + if (typeof address === 'undefined') { + throw new Error( + `Address for TokenBridgeCreator is missing on custom parent chain with id ${parentChainId}`, + ); } - return customParentChainTokenBridgeCreator?.address; + return address; } return tokenBridgeCreatorAddress[parentChainId]; From f403266ceadb8cdf529c6dc6ca0ebfcec12a5c61 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 18:32:05 +0200 Subject: [PATCH 30/41] fix --- src/utils/getParentChainFromId.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/getParentChainFromId.ts b/src/utils/getParentChainFromId.ts index c521ab9f..ebcd9602 100644 --- a/src/utils/getParentChainFromId.ts +++ b/src/utils/getParentChainFromId.ts @@ -1,14 +1,14 @@ -import { extractChain } from 'viem'; +import { Chain, extractChain } from 'viem'; -import { ParentChain, validateParentChain } from '../types/ParentChain'; +import { validateParentChain } from '../types/ParentChain'; import { chains } from '../chains'; import { customChains } from '../customChains'; -export function getParentChainFromId(chainId: number): ParentChain { +export function getParentChainFromId(chainId: number): Chain { const { chainId: parentChainId } = validateParentChain(chainId); return extractChain({ chains: [...chains, ...customChains], id: parentChainId, - }) as ParentChain; + }); } From 3ab67404843c0c9fd9ec6fa410b25fbabbe30ee7 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 18:52:33 +0200 Subject: [PATCH 31/41] move stuff --- src/chains.ts | 19 ++++++++++++++++++- ...PrepareDeploymentParamsConfig.unit.test.ts | 10 ++++++++-- ...llupPrepareTransactionRequest.unit.test.ts | 2 +- src/customChains.ts | 15 --------------- src/customChains.unit.test.ts | 2 +- src/index.ts | 2 +- src/types/ParentChain.ts | 12 ++++++------ src/utils/getParentChainFromId.ts | 5 ++--- .../getRollupCreatorAddress.unit.test.ts | 2 +- .../getTokenBridgeCreatorAddress.unit.test.ts | 2 +- 10 files changed, 39 insertions(+), 32 deletions(-) delete mode 100644 src/customChains.ts diff --git a/src/chains.ts b/src/chains.ts index b2525fe4..26584764 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -1,4 +1,4 @@ -import { defineChain } from 'viem'; +import { defineChain, Chain, ChainContract } from 'viem'; import { mainnet, arbitrum as arbitrumOne, @@ -59,6 +59,23 @@ const nitroTestnodeL3 = defineChain({ testnet: true, }); +const customParentChains: Record = {}; + +export function getCustomParentChains(): Chain[] { + return Object.values(customParentChains); +} + +export type CustomParentChain = Chain & { + contracts: { + rollupCreator: ChainContract; + tokenBridgeCreator: ChainContract; + }; +}; + +export function registerCustomParentChain(chain: CustomParentChain) { + customParentChains[chain.id] = chain; +} + export const chains = [ // mainnet L1 mainnet, diff --git a/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts b/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts index 3652b84d..4b9d925a 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts @@ -1,10 +1,16 @@ import { it, expect } from 'vitest'; import { Address, createPublicClient, http } from 'viem'; -import { arbitrumOne, arbitrumSepolia, base, baseSepolia } from './chains'; +import { + arbitrumOne, + arbitrumSepolia, + base, + baseSepolia, + CustomParentChain, + registerCustomParentChain, +} from './chains'; import { prepareChainConfig } from './prepareChainConfig'; import { createRollupPrepareDeploymentParamsConfig } from './createRollupPrepareDeploymentParamsConfig'; -import { CustomParentChain, registerCustomParentChain } from './customChains'; import { createCustomChain } from './customChainsTestHelpers'; const chainId = 69_420n; diff --git a/src/createRollupPrepareTransactionRequest.unit.test.ts b/src/createRollupPrepareTransactionRequest.unit.test.ts index 00fdeeff..5915fadd 100644 --- a/src/createRollupPrepareTransactionRequest.unit.test.ts +++ b/src/createRollupPrepareTransactionRequest.unit.test.ts @@ -10,7 +10,7 @@ import { createRollupPrepareTransactionRequest } from './createRollupPrepareTran import { rollupCreatorAddress } from './contracts/RollupCreator'; import { getNitroTestnodePrivateKeyAccounts } from './testHelpers'; -import { CustomParentChain, registerCustomParentChain } from './customChains'; +import { CustomParentChain, registerCustomParentChain } from './chains'; import { createCustomChain } from './customChainsTestHelpers'; import { getConsensusReleaseByVersion } from './wasmModuleRoot'; diff --git a/src/customChains.ts b/src/customChains.ts deleted file mode 100644 index 2969de21..00000000 --- a/src/customChains.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Chain, ChainContract, Client } from 'viem'; - -export type CustomParentChain = Chain & { - contracts: { - rollupCreator: ChainContract; - tokenBridgeCreator: ChainContract; - }; -}; - -export const customChains: Chain[] = []; - -export function registerCustomParentChain(chain: CustomParentChain) { - // todo: don't duplicate - customChains.push(chain); -} diff --git a/src/customChains.unit.test.ts b/src/customChains.unit.test.ts index 520c1764..ab034697 100644 --- a/src/customChains.unit.test.ts +++ b/src/customChains.unit.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from 'vitest'; import { validateParentChain } from './types/ParentChain'; -import { CustomParentChain, registerCustomParentChain } from './customChains'; +import { CustomParentChain, registerCustomParentChain } from './chains'; import { createCustomChain } from './customChainsTestHelpers'; describe(`validateParentChain`, () => { diff --git a/src/index.ts b/src/index.ts index b48a154a..8975f0f2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -144,7 +144,7 @@ import { getConsensusReleaseByWasmModuleRoot, GetConsensusReleaseByWasmModuleRoot, } from './wasmModuleRoot'; -import { CustomParentChain, registerCustomParentChain } from './customChains'; +import { CustomParentChain, registerCustomParentChain } from './chains'; export * from './actions'; export { diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index 2fda9882..bc50a1c8 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -1,18 +1,18 @@ import { Client, Transport, Chain } from 'viem'; -import { chains, nitroTestnodeL3 } from '../chains'; -import { customChains } from '../customChains'; +import { chains, getCustomParentChains, nitroTestnodeL3 } from '../chains'; // exclude nitro-testnode L3 from the list of parent chains export type ParentChain = Exclude<(typeof chains)[number], { id: typeof nitroTestnodeL3.id }>; export type ParentChainId = ParentChain['id']; -function isCustom(chainId: number) { - return customChains.map((chain) => chain.id).includes(chainId); +function isCustomParentChain(chainId: number): boolean { + const ids = getCustomParentChains().map((chain) => chain.id); + return ids.includes(chainId); } function isValidParentChainId(parentChainId: number | undefined): parentChainId is number { - const ids = [...chains, ...customChains] + const ids = [...chains, ...getCustomParentChains()] // exclude nitro-testnode L3 from the list of parent chains .filter((chain) => chain.id !== nitroTestnodeL3.id) .map((chain) => chain.id) as Number[]; @@ -28,7 +28,7 @@ export function validateParentChain( throw new Error(`Parent chain not supported: ${chainId}`); } - if (isCustom(chainId)) { + if (isCustomParentChain(chainId)) { return { chainId, isCustom: true }; } diff --git a/src/utils/getParentChainFromId.ts b/src/utils/getParentChainFromId.ts index ebcd9602..f575f65f 100644 --- a/src/utils/getParentChainFromId.ts +++ b/src/utils/getParentChainFromId.ts @@ -1,14 +1,13 @@ import { Chain, extractChain } from 'viem'; import { validateParentChain } from '../types/ParentChain'; -import { chains } from '../chains'; -import { customChains } from '../customChains'; +import { chains, getCustomParentChains } from '../chains'; export function getParentChainFromId(chainId: number): Chain { const { chainId: parentChainId } = validateParentChain(chainId); return extractChain({ - chains: [...chains, ...customChains], + chains: [...chains, ...getCustomParentChains()], id: parentChainId, }); } diff --git a/src/utils/getRollupCreatorAddress.unit.test.ts b/src/utils/getRollupCreatorAddress.unit.test.ts index 998bd18b..dcfe1607 100644 --- a/src/utils/getRollupCreatorAddress.unit.test.ts +++ b/src/utils/getRollupCreatorAddress.unit.test.ts @@ -3,7 +3,7 @@ import { createPublicClient, http } from 'viem'; import { sepolia } from 'viem/chains'; import { getRollupCreatorAddress } from './getRollupCreatorAddress'; -import { CustomParentChain, registerCustomParentChain } from '../customChains'; +import { CustomParentChain, registerCustomParentChain } from '../chains'; import { createCustomChain } from '../customChainsTestHelpers'; it(`successfully returns address for Sepolia`, () => { diff --git a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts index d67bbe12..fbe0ad73 100644 --- a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts +++ b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts @@ -3,7 +3,7 @@ import { createPublicClient, http } from 'viem'; import { sepolia } from 'viem/chains'; import { getTokenBridgeCreatorAddress } from './getTokenBridgeCreatorAddress'; -import { CustomParentChain, registerCustomParentChain } from '../customChains'; +import { CustomParentChain, registerCustomParentChain } from '../chains'; import { createCustomChain } from '../customChainsTestHelpers'; it(`successfully returns address for Sepolia`, () => { From a3111707461f56f4a1fcf72564d0dffe2b70a4f1 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 18:58:31 +0200 Subject: [PATCH 32/41] fix error --- src/prepareNodeConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prepareNodeConfig.ts b/src/prepareNodeConfig.ts index 9f37a3ed..d43ae50e 100644 --- a/src/prepareNodeConfig.ts +++ b/src/prepareNodeConfig.ts @@ -67,7 +67,7 @@ export function prepareNodeConfig({ if (parentChainIsCustom && typeof parentChainIsArbitrumParam === 'undefined') { throw new Error( - `"params.parentChainIsArbitrumParam" must be provided when using a custom parent chain.`, + `"params.parentChainIsArbitrum" must be provided when using a custom parent chain.`, ); } From cba60f693e51bf37a71224d7172c003f5a88b9dd Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 19:04:06 +0200 Subject: [PATCH 33/41] refactor --- src/createRollupPrepareTransactionRequest.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/createRollupPrepareTransactionRequest.ts b/src/createRollupPrepareTransactionRequest.ts index a5d8ffb0..e86846d1 100644 --- a/src/createRollupPrepareTransactionRequest.ts +++ b/src/createRollupPrepareTransactionRequest.ts @@ -76,8 +76,16 @@ export async function createRollupPrepareTransactionRequest Date: Wed, 9 Oct 2024 19:22:07 +0200 Subject: [PATCH 34/41] clean up --- src/chains.ts | 9 +---- ...PrepareDeploymentParamsConfig.unit.test.ts | 33 ++++++------------- ...llupPrepareTransactionRequest.unit.test.ts | 24 +++++--------- src/customChains.unit.test.ts | 14 +++----- src/customChainsTestHelpers.ts | 16 ++++++--- src/index.ts | 3 +- .../getRollupCreatorAddress.unit.test.ts | 21 ++++-------- .../getTokenBridgeCreatorAddress.unit.test.ts | 21 ++++-------- 8 files changed, 51 insertions(+), 90 deletions(-) diff --git a/src/chains.ts b/src/chains.ts index 26584764..52006562 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -65,14 +65,7 @@ export function getCustomParentChains(): Chain[] { return Object.values(customParentChains); } -export type CustomParentChain = Chain & { - contracts: { - rollupCreator: ChainContract; - tokenBridgeCreator: ChainContract; - }; -}; - -export function registerCustomParentChain(chain: CustomParentChain) { +export function registerCustomParentChain(chain: Chain) { customParentChains[chain.id] = chain; } diff --git a/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts b/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts index 4b9d925a..14a73617 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts @@ -6,12 +6,11 @@ import { arbitrumSepolia, base, baseSepolia, - CustomParentChain, registerCustomParentChain, } from './chains'; import { prepareChainConfig } from './prepareChainConfig'; import { createRollupPrepareDeploymentParamsConfig } from './createRollupPrepareDeploymentParamsConfig'; -import { createCustomChain } from './customChainsTestHelpers'; +import { createExampleCustomParentChain } from './customChainsTestHelpers'; const chainId = 69_420n; const vitalik: `0x${string}` = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'; @@ -127,13 +126,9 @@ it('creates config for a chain on top of base sepolia with defaults', () => { }); it('fails to create a config for a chain on top of a custom parent chain if "confirmPeriodBlocks" is not provided', () => { - const chain: CustomParentChain = { - ...createCustomChain({ id: 123 }), - contracts: { - rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, - tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, - }, - }; + const chain = createExampleCustomParentChain({ + id: 123, + }); const publicClient = createPublicClient({ chain, @@ -151,13 +146,9 @@ it('fails to create a config for a chain on top of a custom parent chain if "con }); it('fails to create a config for a chain on top of a custom parent chain if "sequencerInboxMaxTimeVariation" is not provided', () => { - const chain: CustomParentChain = { - ...createCustomChain({ id: 123 }), - contracts: { - rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, - tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, - }, - }; + const chain = createExampleCustomParentChain({ + id: 123, + }); const publicClient = createPublicClient({ chain, @@ -178,13 +169,9 @@ it('fails to create a config for a chain on top of a custom parent chain if "seq }); it('creates a config for a chain on top of a custom parent chain', () => { - const chain: CustomParentChain = { - ...createCustomChain({ id: 123 }), - contracts: { - rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, - tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, - }, - }; + const chain = createExampleCustomParentChain({ + id: 123, + }); const publicClient = createPublicClient({ chain, diff --git a/src/createRollupPrepareTransactionRequest.unit.test.ts b/src/createRollupPrepareTransactionRequest.unit.test.ts index 5915fadd..391870b0 100644 --- a/src/createRollupPrepareTransactionRequest.unit.test.ts +++ b/src/createRollupPrepareTransactionRequest.unit.test.ts @@ -10,8 +10,8 @@ import { createRollupPrepareTransactionRequest } from './createRollupPrepareTran import { rollupCreatorAddress } from './contracts/RollupCreator'; import { getNitroTestnodePrivateKeyAccounts } from './testHelpers'; -import { CustomParentChain, registerCustomParentChain } from './chains'; -import { createCustomChain } from './customChainsTestHelpers'; +import { registerCustomParentChain } from './chains'; +import { createExampleCustomParentChain } from './customChainsTestHelpers'; import { getConsensusReleaseByVersion } from './wasmModuleRoot'; const testnodeAccounts = getNitroTestnodePrivateKeyAccounts(); @@ -302,13 +302,9 @@ it(`fails to prepare transaction request if "params.maxDataSize" is not provided arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, }); - const chain: CustomParentChain = { - ...createCustomChain({ id: 123 }), - contracts: { - rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, - tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, - }, - }; + const chain = createExampleCustomParentChain({ + id: chainId, + }); const publicClient = createPublicClient({ chain, @@ -419,13 +415,9 @@ it(`successfully prepares a transaction request with a custom parent chain`, asy arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, }); - const chain: CustomParentChain = { - ...createCustomChain({ id: 123 }), - contracts: { - rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, - tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, - }, - }; + const chain = createExampleCustomParentChain({ + id: chainId, + }); const publicClient = createPublicClient({ chain, diff --git a/src/customChains.unit.test.ts b/src/customChains.unit.test.ts index ab034697..44dbe064 100644 --- a/src/customChains.unit.test.ts +++ b/src/customChains.unit.test.ts @@ -1,8 +1,8 @@ import { describe, it, expect } from 'vitest'; import { validateParentChain } from './types/ParentChain'; -import { CustomParentChain, registerCustomParentChain } from './chains'; -import { createCustomChain } from './customChainsTestHelpers'; +import { registerCustomParentChain } from './chains'; +import { createExampleCustomParentChain } from './customChainsTestHelpers'; describe(`validateParentChain`, () => { it(`throws for an unregistered custom parent chain`, () => { @@ -14,13 +14,9 @@ describe(`validateParentChain`, () => { it(`works for a registered custom parent chain`, () => { const id = 123_456; - const chain: CustomParentChain = { - ...createCustomChain({ id }), - contracts: { - rollupCreator: { address: '0x1000000000000000000000000000000000000000' }, - tokenBridgeCreator: { address: '0x2000000000000000000000000000000000000000' }, - }, - }; + const chain = createExampleCustomParentChain({ + id, + }); registerCustomParentChain(chain); diff --git a/src/customChainsTestHelpers.ts b/src/customChainsTestHelpers.ts index ba4c02f4..ab8a8880 100644 --- a/src/customChainsTestHelpers.ts +++ b/src/customChainsTestHelpers.ts @@ -1,10 +1,10 @@ import { Chain } from 'viem'; -export function createCustomChain({ id }: { id: number }): Chain { +export function createExampleCustomParentChain({ id }: { id: number }) { return { id, - name: `Custom Chain (${id})`, - network: `custom-chain-${id}`, + name: `Custom Parent Chain (${id})`, + network: `custom-parent-chain-${id}`, nativeCurrency: { name: 'Ether', symbol: 'ETH', @@ -18,5 +18,13 @@ export function createCustomChain({ id }: { id: number }): Chain { http: ['http://localhost:3000'], }, }, - }; + contracts: { + rollupCreator: { + address: '0x1000000000000000000000000000000000000000', + }, + tokenBridgeCreator: { + address: '0x2000000000000000000000000000000000000000', + }, + }, + } satisfies Chain; } diff --git a/src/index.ts b/src/index.ts index 8975f0f2..ae67d37b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -144,7 +144,7 @@ import { getConsensusReleaseByWasmModuleRoot, GetConsensusReleaseByWasmModuleRoot, } from './wasmModuleRoot'; -import { CustomParentChain, registerCustomParentChain } from './chains'; +import { registerCustomParentChain } from './chains'; export * from './actions'; export { @@ -266,6 +266,5 @@ export { getConsensusReleaseByWasmModuleRoot, GetConsensusReleaseByWasmModuleRoot, // - CustomParentChain, registerCustomParentChain, }; diff --git a/src/utils/getRollupCreatorAddress.unit.test.ts b/src/utils/getRollupCreatorAddress.unit.test.ts index dcfe1607..d7ed1424 100644 --- a/src/utils/getRollupCreatorAddress.unit.test.ts +++ b/src/utils/getRollupCreatorAddress.unit.test.ts @@ -3,8 +3,8 @@ import { createPublicClient, http } from 'viem'; import { sepolia } from 'viem/chains'; import { getRollupCreatorAddress } from './getRollupCreatorAddress'; -import { CustomParentChain, registerCustomParentChain } from '../chains'; -import { createCustomChain } from '../customChainsTestHelpers'; +import { registerCustomParentChain } from '../chains'; +import { createExampleCustomParentChain } from '../customChainsTestHelpers'; it(`successfully returns address for Sepolia`, () => { const client = createPublicClient({ @@ -17,7 +17,7 @@ it(`successfully returns address for Sepolia`, () => { it(`fails to return address for an unrecognized parent chain`, () => { const client = createPublicClient({ - chain: createCustomChain({ id: 123 }), + chain: createExampleCustomParentChain({ id: 123 }), transport: http(), }); @@ -25,16 +25,9 @@ it(`fails to return address for an unrecognized parent chain`, () => { }); it(`successfully returns address for a registered custom parent chain`, () => { - const rollupCreator = '0x1000000000000000000000000000000000000000'; - const tokenBridgeCreator = '0x2000000000000000000000000000000000000000'; - - const chain: CustomParentChain = { - ...createCustomChain({ id: 123_456 }), - contracts: { - rollupCreator: { address: rollupCreator }, - tokenBridgeCreator: { address: tokenBridgeCreator }, - }, - }; + const chain = createExampleCustomParentChain({ + id: 123_456, + }); registerCustomParentChain(chain); @@ -43,5 +36,5 @@ it(`successfully returns address for a registered custom parent chain`, () => { transport: http(), }); - expect(getRollupCreatorAddress(client)).toEqual(rollupCreator); + expect(getRollupCreatorAddress(client)).toEqual(chain.contracts.rollupCreator.address); }); diff --git a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts index fbe0ad73..687bf15b 100644 --- a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts +++ b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts @@ -3,8 +3,8 @@ import { createPublicClient, http } from 'viem'; import { sepolia } from 'viem/chains'; import { getTokenBridgeCreatorAddress } from './getTokenBridgeCreatorAddress'; -import { CustomParentChain, registerCustomParentChain } from '../chains'; -import { createCustomChain } from '../customChainsTestHelpers'; +import { registerCustomParentChain } from '../chains'; +import { createExampleCustomParentChain } from '../customChainsTestHelpers'; it(`successfully returns address for Sepolia`, () => { const client = createPublicClient({ @@ -19,7 +19,7 @@ it(`successfully returns address for Sepolia`, () => { it(`fails to return address for an unrecognized parent chain`, () => { const client = createPublicClient({ - chain: createCustomChain({ id: 123 }), + chain: createExampleCustomParentChain({ id: 123 }), transport: http(), }); @@ -29,16 +29,9 @@ it(`fails to return address for an unrecognized parent chain`, () => { }); it(`successfully returns address for a registered custom parent chain`, () => { - const rollupCreator = '0x1000000000000000000000000000000000000000'; - const tokenBridgeCreator = '0x2000000000000000000000000000000000000000'; - - const chain: CustomParentChain = { - ...createCustomChain({ id: 123_456 }), - contracts: { - rollupCreator: { address: rollupCreator }, - tokenBridgeCreator: { address: tokenBridgeCreator }, - }, - }; + const chain = createExampleCustomParentChain({ + id: 123_456, + }); registerCustomParentChain(chain); @@ -47,5 +40,5 @@ it(`successfully returns address for a registered custom parent chain`, () => { transport: http(), }); - expect(getTokenBridgeCreatorAddress(client)).toEqual(tokenBridgeCreator); + expect(getTokenBridgeCreatorAddress(client)).toEqual(chain.contracts.tokenBridgeCreator.address); }); From be8c257e7ade4a09f32ac0750bf65f0dbeff0cff Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 19:35:59 +0200 Subject: [PATCH 35/41] clean up --- ...PrepareDeploymentParamsConfig.unit.test.ts | 20 ++++++------- ...llupPrepareTransactionRequest.unit.test.ts | 12 ++++---- src/customChains.unit.test.ts | 16 +++++----- src/customChainsTestHelpers.ts | 29 +++++++++++-------- .../getRollupCreatorAddress.unit.test.ts | 15 ++++++---- .../getTokenBridgeCreatorAddress.unit.test.ts | 13 +++++---- 6 files changed, 55 insertions(+), 50 deletions(-) diff --git a/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts b/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts index 14a73617..112977ea 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts @@ -10,7 +10,8 @@ import { } from './chains'; import { prepareChainConfig } from './prepareChainConfig'; import { createRollupPrepareDeploymentParamsConfig } from './createRollupPrepareDeploymentParamsConfig'; -import { createExampleCustomParentChain } from './customChainsTestHelpers'; + +import { testHelper_createCustomParentChain } from './customChainsTestHelpers'; const chainId = 69_420n; const vitalik: `0x${string}` = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'; @@ -126,13 +127,11 @@ it('creates config for a chain on top of base sepolia with defaults', () => { }); it('fails to create a config for a chain on top of a custom parent chain if "confirmPeriodBlocks" is not provided', () => { - const chain = createExampleCustomParentChain({ - id: 123, - }); + const chain = testHelper_createCustomParentChain(); const publicClient = createPublicClient({ chain, - transport: http('https://sepolia-rollup.arbitrum.io/rpc'), + transport: http(), }); registerCustomParentChain(chain); @@ -146,13 +145,11 @@ it('fails to create a config for a chain on top of a custom parent chain if "con }); it('fails to create a config for a chain on top of a custom parent chain if "sequencerInboxMaxTimeVariation" is not provided', () => { - const chain = createExampleCustomParentChain({ - id: 123, - }); + const chain = testHelper_createCustomParentChain(); const publicClient = createPublicClient({ chain, - transport: http('https://sepolia-rollup.arbitrum.io/rpc'), + transport: http(), }); registerCustomParentChain(chain); @@ -169,13 +166,14 @@ it('fails to create a config for a chain on top of a custom parent chain if "seq }); it('creates a config for a chain on top of a custom parent chain', () => { - const chain = createExampleCustomParentChain({ + const chain = testHelper_createCustomParentChain({ + // using a specific chain id here as it's a snapshot test id: 123, }); const publicClient = createPublicClient({ chain, - transport: http('https://sepolia-rollup.arbitrum.io/rpc'), + transport: http(), }); registerCustomParentChain(chain); diff --git a/src/createRollupPrepareTransactionRequest.unit.test.ts b/src/createRollupPrepareTransactionRequest.unit.test.ts index 391870b0..172533d6 100644 --- a/src/createRollupPrepareTransactionRequest.unit.test.ts +++ b/src/createRollupPrepareTransactionRequest.unit.test.ts @@ -11,7 +11,7 @@ import { rollupCreatorAddress } from './contracts/RollupCreator'; import { getNitroTestnodePrivateKeyAccounts } from './testHelpers'; import { registerCustomParentChain } from './chains'; -import { createExampleCustomParentChain } from './customChainsTestHelpers'; +import { testHelper_createCustomParentChain } from './customChainsTestHelpers'; import { getConsensusReleaseByVersion } from './wasmModuleRoot'; const testnodeAccounts = getNitroTestnodePrivateKeyAccounts(); @@ -302,7 +302,7 @@ it(`fails to prepare transaction request if "params.maxDataSize" is not provided arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, }); - const chain = createExampleCustomParentChain({ + const chain = testHelper_createCustomParentChain({ id: chainId, }); @@ -415,13 +415,13 @@ it(`successfully prepares a transaction request with a custom parent chain`, asy arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, }); - const chain = createExampleCustomParentChain({ + const chain = testHelper_createCustomParentChain({ id: chainId, }); const publicClient = createPublicClient({ chain, - transport: http('https://sepolia-rollup.arbitrum.io/rpc'), + transport: http(), }); registerCustomParentChain(chain); @@ -451,7 +451,7 @@ it(`successfully prepares a transaction request with a custom parent chain`, asy expect(txRequest.account).toEqual(deployer.address); expect(txRequest.from).toEqual(deployer.address); - expect(txRequest.to).toEqual('0x1000000000000000000000000000000000000000'); - expect(txRequest.chainId).toEqual(123); + expect(txRequest.to).toEqual(chain.contracts.rollupCreator.address); + expect(txRequest.chainId).toEqual(chainId); expect(txRequest.gas).toEqual(1_000n); }); diff --git a/src/customChains.unit.test.ts b/src/customChains.unit.test.ts index 44dbe064..bd187195 100644 --- a/src/customChains.unit.test.ts +++ b/src/customChains.unit.test.ts @@ -2,27 +2,25 @@ import { describe, it, expect } from 'vitest'; import { validateParentChain } from './types/ParentChain'; import { registerCustomParentChain } from './chains'; -import { createExampleCustomParentChain } from './customChainsTestHelpers'; +import { generateChainId } from './utils'; + +import { testHelper_createCustomParentChain } from './customChainsTestHelpers'; describe(`validateParentChain`, () => { it(`throws for an unregistered custom parent chain`, () => { - const id = 456_789; + const id = generateChainId(); expect(() => validateParentChain(id)).toThrowError(`Parent chain not supported: ${id}`); }); it(`works for a registered custom parent chain`, () => { - const id = 123_456; - - const chain = createExampleCustomParentChain({ - id, - }); + const chain = testHelper_createCustomParentChain(); registerCustomParentChain(chain); - const result = validateParentChain(id); + const result = validateParentChain(chain.id); - expect(result.chainId).toEqual(id); + expect(result.chainId).toEqual(chain.id); expect(result.isCustom).toEqual(true); }); }); diff --git a/src/customChainsTestHelpers.ts b/src/customChainsTestHelpers.ts index ab8a8880..20c543c5 100644 --- a/src/customChainsTestHelpers.ts +++ b/src/customChainsTestHelpers.ts @@ -1,10 +1,17 @@ import { Chain } from 'viem'; +import { generatePrivateKey, privateKeyToAddress } from 'viem/accounts'; + +import { generateChainId } from './utils'; + +export function testHelper_createCustomParentChain(params?: { id?: number }) { + const chainId = params?.id ?? generateChainId(); + const rollupCreator = privateKeyToAddress(generatePrivateKey()); + const tokenBridgeCreator = privateKeyToAddress(generatePrivateKey()); -export function createExampleCustomParentChain({ id }: { id: number }) { return { - id, - name: `Custom Parent Chain (${id})`, - network: `custom-parent-chain-${id}`, + id: chainId, + name: `Custom Parent Chain (${chainId})`, + network: `custom-parent-chain-${chainId}`, nativeCurrency: { name: 'Ether', symbol: 'ETH', @@ -12,19 +19,17 @@ export function createExampleCustomParentChain({ id }: { id: number }) { }, rpcUrls: { public: { - http: ['http://localhost:3000'], + // have to put a valid rpc here so using arbitrum sepolia + http: ['https://sepolia-rollup.arbitrum.io/rpc'], }, default: { - http: ['http://localhost:3000'], + // have to put a valid rpc here so using arbitrum sepolia + http: ['https://sepolia-rollup.arbitrum.io/rpc'], }, }, contracts: { - rollupCreator: { - address: '0x1000000000000000000000000000000000000000', - }, - tokenBridgeCreator: { - address: '0x2000000000000000000000000000000000000000', - }, + rollupCreator: { address: rollupCreator }, + tokenBridgeCreator: { address: tokenBridgeCreator }, }, } satisfies Chain; } diff --git a/src/utils/getRollupCreatorAddress.unit.test.ts b/src/utils/getRollupCreatorAddress.unit.test.ts index d7ed1424..2e23ad21 100644 --- a/src/utils/getRollupCreatorAddress.unit.test.ts +++ b/src/utils/getRollupCreatorAddress.unit.test.ts @@ -4,7 +4,8 @@ import { sepolia } from 'viem/chains'; import { getRollupCreatorAddress } from './getRollupCreatorAddress'; import { registerCustomParentChain } from '../chains'; -import { createExampleCustomParentChain } from '../customChainsTestHelpers'; + +import { testHelper_createCustomParentChain } from '../customChainsTestHelpers'; it(`successfully returns address for Sepolia`, () => { const client = createPublicClient({ @@ -16,18 +17,20 @@ it(`successfully returns address for Sepolia`, () => { }); it(`fails to return address for an unrecognized parent chain`, () => { + const chain = testHelper_createCustomParentChain(); + const client = createPublicClient({ - chain: createExampleCustomParentChain({ id: 123 }), + chain, transport: http(), }); - expect(() => getRollupCreatorAddress(client)).toThrowError('Parent chain not supported: 123'); + expect(() => getRollupCreatorAddress(client)).toThrowError( + `Parent chain not supported: ${chain.id}`, + ); }); it(`successfully returns address for a registered custom parent chain`, () => { - const chain = createExampleCustomParentChain({ - id: 123_456, - }); + const chain = testHelper_createCustomParentChain(); registerCustomParentChain(chain); diff --git a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts index 687bf15b..d6a423bf 100644 --- a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts +++ b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts @@ -4,7 +4,8 @@ import { sepolia } from 'viem/chains'; import { getTokenBridgeCreatorAddress } from './getTokenBridgeCreatorAddress'; import { registerCustomParentChain } from '../chains'; -import { createExampleCustomParentChain } from '../customChainsTestHelpers'; + +import { testHelper_createCustomParentChain } from '../customChainsTestHelpers'; it(`successfully returns address for Sepolia`, () => { const client = createPublicClient({ @@ -18,20 +19,20 @@ it(`successfully returns address for Sepolia`, () => { }); it(`fails to return address for an unrecognized parent chain`, () => { + const chain = testHelper_createCustomParentChain(); + const client = createPublicClient({ - chain: createExampleCustomParentChain({ id: 123 }), + chain, transport: http(), }); expect(() => getTokenBridgeCreatorAddress(client)).toThrowError( - 'Parent chain not supported: 123', + `Parent chain not supported: ${chain.id}`, ); }); it(`successfully returns address for a registered custom parent chain`, () => { - const chain = createExampleCustomParentChain({ - id: 123_456, - }); + const chain = testHelper_createCustomParentChain(); registerCustomParentChain(chain); From 68c7899af228c9ba79a8ea6d121df795f1e329a7 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 19:41:21 +0200 Subject: [PATCH 36/41] rename file plus add test case --- src/customChains.unit.test.ts | 26 ----------------------- src/validateParentChain.unit.test.ts | 31 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 26 deletions(-) delete mode 100644 src/customChains.unit.test.ts create mode 100644 src/validateParentChain.unit.test.ts diff --git a/src/customChains.unit.test.ts b/src/customChains.unit.test.ts deleted file mode 100644 index bd187195..00000000 --- a/src/customChains.unit.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { describe, it, expect } from 'vitest'; - -import { validateParentChain } from './types/ParentChain'; -import { registerCustomParentChain } from './chains'; -import { generateChainId } from './utils'; - -import { testHelper_createCustomParentChain } from './customChainsTestHelpers'; - -describe(`validateParentChain`, () => { - it(`throws for an unregistered custom parent chain`, () => { - const id = generateChainId(); - - expect(() => validateParentChain(id)).toThrowError(`Parent chain not supported: ${id}`); - }); - - it(`works for a registered custom parent chain`, () => { - const chain = testHelper_createCustomParentChain(); - - registerCustomParentChain(chain); - - const result = validateParentChain(chain.id); - - expect(result.chainId).toEqual(chain.id); - expect(result.isCustom).toEqual(true); - }); -}); diff --git a/src/validateParentChain.unit.test.ts b/src/validateParentChain.unit.test.ts new file mode 100644 index 00000000..52892f39 --- /dev/null +++ b/src/validateParentChain.unit.test.ts @@ -0,0 +1,31 @@ +import { it, expect } from 'vitest'; + +import { validateParentChain } from './types/ParentChain'; +import { arbitrumOne, registerCustomParentChain } from './chains'; +import { generateChainId } from './utils'; + +import { testHelper_createCustomParentChain } from './customChainsTestHelpers'; + +it(`sucessfully validates arbitrum one`, () => { + const result = validateParentChain(arbitrumOne.id); + + expect(result.chainId).toEqual(arbitrumOne.id); + expect(result.isCustom).toEqual(false); +}); + +it(`throws for an unregistered custom parent chain`, () => { + const id = generateChainId(); + + expect(() => validateParentChain(id)).toThrowError(`Parent chain not supported: ${id}`); +}); + +it(`sucessfully validates a registered custom parent chain`, () => { + const chain = testHelper_createCustomParentChain(); + + registerCustomParentChain(chain); + + const result = validateParentChain(chain.id); + + expect(result.chainId).toEqual(chain.id); + expect(result.isCustom).toEqual(true); +}); From 8c0d9608ffd608ed3bafdd7a74861984c271a86e Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 19:44:41 +0200 Subject: [PATCH 37/41] move stuff --- ...PrepareDeploymentParamsConfig.unit.test.ts | 2 +- ...llupPrepareTransactionRequest.unit.test.ts | 6 ++-- src/customChainsTestHelpers.ts | 35 ------------------- src/testHelpers.ts | 35 +++++++++++++++++-- .../getRollupCreatorAddress.unit.test.ts | 2 +- .../getTokenBridgeCreatorAddress.unit.test.ts | 2 +- src/validateParentChain.unit.test.ts | 2 +- 7 files changed, 41 insertions(+), 43 deletions(-) delete mode 100644 src/customChainsTestHelpers.ts diff --git a/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts b/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts index 112977ea..10ccca06 100644 --- a/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts +++ b/src/createRollupPrepareDeploymentParamsConfig.unit.test.ts @@ -11,7 +11,7 @@ import { import { prepareChainConfig } from './prepareChainConfig'; import { createRollupPrepareDeploymentParamsConfig } from './createRollupPrepareDeploymentParamsConfig'; -import { testHelper_createCustomParentChain } from './customChainsTestHelpers'; +import { testHelper_createCustomParentChain } from './testHelpers'; const chainId = 69_420n; const vitalik: `0x${string}` = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'; diff --git a/src/createRollupPrepareTransactionRequest.unit.test.ts b/src/createRollupPrepareTransactionRequest.unit.test.ts index 172533d6..e026f580 100644 --- a/src/createRollupPrepareTransactionRequest.unit.test.ts +++ b/src/createRollupPrepareTransactionRequest.unit.test.ts @@ -9,9 +9,11 @@ import { createRollupPrepareDeploymentParamsConfig } from './createRollupPrepare import { createRollupPrepareTransactionRequest } from './createRollupPrepareTransactionRequest'; import { rollupCreatorAddress } from './contracts/RollupCreator'; -import { getNitroTestnodePrivateKeyAccounts } from './testHelpers'; +import { + getNitroTestnodePrivateKeyAccounts, + testHelper_createCustomParentChain, +} from './testHelpers'; import { registerCustomParentChain } from './chains'; -import { testHelper_createCustomParentChain } from './customChainsTestHelpers'; import { getConsensusReleaseByVersion } from './wasmModuleRoot'; const testnodeAccounts = getNitroTestnodePrivateKeyAccounts(); diff --git a/src/customChainsTestHelpers.ts b/src/customChainsTestHelpers.ts deleted file mode 100644 index 20c543c5..00000000 --- a/src/customChainsTestHelpers.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Chain } from 'viem'; -import { generatePrivateKey, privateKeyToAddress } from 'viem/accounts'; - -import { generateChainId } from './utils'; - -export function testHelper_createCustomParentChain(params?: { id?: number }) { - const chainId = params?.id ?? generateChainId(); - const rollupCreator = privateKeyToAddress(generatePrivateKey()); - const tokenBridgeCreator = privateKeyToAddress(generatePrivateKey()); - - return { - id: chainId, - name: `Custom Parent Chain (${chainId})`, - network: `custom-parent-chain-${chainId}`, - nativeCurrency: { - name: 'Ether', - symbol: 'ETH', - decimals: 18, - }, - rpcUrls: { - public: { - // have to put a valid rpc here so using arbitrum sepolia - http: ['https://sepolia-rollup.arbitrum.io/rpc'], - }, - default: { - // have to put a valid rpc here so using arbitrum sepolia - http: ['https://sepolia-rollup.arbitrum.io/rpc'], - }, - }, - contracts: { - rollupCreator: { address: rollupCreator }, - tokenBridgeCreator: { address: tokenBridgeCreator }, - }, - } satisfies Chain; -} diff --git a/src/testHelpers.ts b/src/testHelpers.ts index eb8c3893..597bd5c9 100644 --- a/src/testHelpers.ts +++ b/src/testHelpers.ts @@ -1,5 +1,5 @@ -import { Address, Client, PublicClient, zeroAddress } from 'viem'; -import { privateKeyToAccount, PrivateKeyAccount } from 'viem/accounts'; +import { Address, Chain, PublicClient, zeroAddress } from 'viem'; +import { PrivateKeyAccount, privateKeyToAccount, generatePrivateKey } from 'viem/accounts'; import { config } from 'dotenv'; import { execSync } from 'node:child_process'; @@ -179,3 +179,34 @@ export async function createRollupHelper({ createRollupInformation, }; } + +export function testHelper_createCustomParentChain(params?: { id?: number }) { + const chainId = params?.id ?? generateChainId(); + const rollupCreator = privateKeyToAccount(generatePrivateKey()).address; + const tokenBridgeCreator = privateKeyToAccount(generatePrivateKey()).address; + + return { + id: chainId, + name: `Custom Parent Chain (${chainId})`, + network: `custom-parent-chain-${chainId}`, + nativeCurrency: { + name: 'Ether', + symbol: 'ETH', + decimals: 18, + }, + rpcUrls: { + public: { + // have to put a valid rpc here so using arbitrum sepolia + http: ['https://sepolia-rollup.arbitrum.io/rpc'], + }, + default: { + // have to put a valid rpc here so using arbitrum sepolia + http: ['https://sepolia-rollup.arbitrum.io/rpc'], + }, + }, + contracts: { + rollupCreator: { address: rollupCreator }, + tokenBridgeCreator: { address: tokenBridgeCreator }, + }, + } satisfies Chain; +} diff --git a/src/utils/getRollupCreatorAddress.unit.test.ts b/src/utils/getRollupCreatorAddress.unit.test.ts index 2e23ad21..1874c8b1 100644 --- a/src/utils/getRollupCreatorAddress.unit.test.ts +++ b/src/utils/getRollupCreatorAddress.unit.test.ts @@ -5,7 +5,7 @@ import { sepolia } from 'viem/chains'; import { getRollupCreatorAddress } from './getRollupCreatorAddress'; import { registerCustomParentChain } from '../chains'; -import { testHelper_createCustomParentChain } from '../customChainsTestHelpers'; +import { testHelper_createCustomParentChain } from '../testHelpers'; it(`successfully returns address for Sepolia`, () => { const client = createPublicClient({ diff --git a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts index d6a423bf..82eb11ce 100644 --- a/src/utils/getTokenBridgeCreatorAddress.unit.test.ts +++ b/src/utils/getTokenBridgeCreatorAddress.unit.test.ts @@ -5,7 +5,7 @@ import { sepolia } from 'viem/chains'; import { getTokenBridgeCreatorAddress } from './getTokenBridgeCreatorAddress'; import { registerCustomParentChain } from '../chains'; -import { testHelper_createCustomParentChain } from '../customChainsTestHelpers'; +import { testHelper_createCustomParentChain } from '../testHelpers'; it(`successfully returns address for Sepolia`, () => { const client = createPublicClient({ diff --git a/src/validateParentChain.unit.test.ts b/src/validateParentChain.unit.test.ts index 52892f39..a579e936 100644 --- a/src/validateParentChain.unit.test.ts +++ b/src/validateParentChain.unit.test.ts @@ -4,7 +4,7 @@ import { validateParentChain } from './types/ParentChain'; import { arbitrumOne, registerCustomParentChain } from './chains'; import { generateChainId } from './utils'; -import { testHelper_createCustomParentChain } from './customChainsTestHelpers'; +import { testHelper_createCustomParentChain } from './testHelpers'; it(`sucessfully validates arbitrum one`, () => { const result = validateParentChain(arbitrumOne.id); From 761052f3a339e3f8ac9e37dc245ad201ecfb69a0 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 19:55:47 +0200 Subject: [PATCH 38/41] use default value --- src/createRollupPrepareTransactionRequest.unit.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/createRollupPrepareTransactionRequest.unit.test.ts b/src/createRollupPrepareTransactionRequest.unit.test.ts index e026f580..8db6405e 100644 --- a/src/createRollupPrepareTransactionRequest.unit.test.ts +++ b/src/createRollupPrepareTransactionRequest.unit.test.ts @@ -447,6 +447,7 @@ it(`successfully prepares a transaction request with a custom parent chain`, asy maxDataSize: 123_456n, }, account: deployer.address, + value: createRollupDefaultRetryablesFees, publicClient, gasOverrides: { gasLimit: { base: 1_000n } }, }); From a542da318505bddf90004829bae4a5ca08abcb6b Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 20:10:16 +0200 Subject: [PATCH 39/41] add validation and tests --- src/chains.ts | 20 +++++++++++++++++++- src/chains.unit.test.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/chains.unit.test.ts diff --git a/src/chains.ts b/src/chains.ts index 52006562..6ff78053 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -1,4 +1,4 @@ -import { defineChain, Chain, ChainContract } from 'viem'; +import { defineChain, Chain, ChainContract, isAddress } from 'viem'; import { mainnet, arbitrum as arbitrumOne, @@ -66,6 +66,24 @@ export function getCustomParentChains(): Chain[] { } export function registerCustomParentChain(chain: Chain) { + const rollupCreator = chain.contracts?.rollupCreator as ChainContract | undefined; + const rollupCreatorAddress = rollupCreator?.address; + + const tokenBridgeCreator = chain.contracts?.tokenBridgeCreator as ChainContract | undefined; + const tokenBridgeCreatorAddress = tokenBridgeCreator?.address; + + if (typeof rollupCreatorAddress === 'undefined' || !isAddress(rollupCreatorAddress)) { + throw new Error( + `"contracts.rollupCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, + ); + } + + if (typeof tokenBridgeCreatorAddress === 'undefined' || !isAddress(tokenBridgeCreatorAddress)) { + throw new Error( + `"contracts.tokenBridgeCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, + ); + } + customParentChains[chain.id] = chain; } diff --git a/src/chains.unit.test.ts b/src/chains.unit.test.ts new file mode 100644 index 00000000..310394f1 --- /dev/null +++ b/src/chains.unit.test.ts @@ -0,0 +1,30 @@ +import { describe, expect, it } from 'vitest'; + +import { registerCustomParentChain } from './chains'; +import { testHelper_createCustomParentChain } from './testHelpers'; + +describe('registerCustomParentChain', () => { + it(`throws if the RollupCreator address wasn't provided`, () => { + // omit contracts from the chain + const { contracts, ...chain } = testHelper_createCustomParentChain(); + + expect(() => registerCustomParentChain(chain)).toThrowError( + `"contracts.rollupCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, + ); + }); + + it(`throws if the TokenBridgeCreator address wasn't provided`, () => { + // omit contracts from the chain + const { contracts, ...chain } = testHelper_createCustomParentChain(); + + expect(() => + registerCustomParentChain({ + ...chain, + // add in only RollupCreator + contracts: { rollupCreator: contracts.rollupCreator }, + }), + ).toThrowError( + `"contracts.tokenBridgeCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, + ); + }); +}); From 54cf124b04d98a5a7cb00030e78c5849f69e1063 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 20:13:01 +0200 Subject: [PATCH 40/41] add another test --- src/chains.unit.test.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/chains.unit.test.ts b/src/chains.unit.test.ts index 310394f1..5258f6c2 100644 --- a/src/chains.unit.test.ts +++ b/src/chains.unit.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { registerCustomParentChain } from './chains'; +import { getCustomParentChains, registerCustomParentChain } from './chains'; import { testHelper_createCustomParentChain } from './testHelpers'; describe('registerCustomParentChain', () => { @@ -27,4 +27,17 @@ describe('registerCustomParentChain', () => { `"contracts.tokenBridgeCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, ); }); + + it('successfully registers a custom parent chain', () => { + const chain = testHelper_createCustomParentChain(); + + // assert before + expect(getCustomParentChains().map((c) => c.id)).not.includes(chain.id); + + // register + registerCustomParentChain(chain); + + // assert after + expect(getCustomParentChains().map((c) => c.id)).includes(chain.id); + }); }); From 2fb05c6f80381c5a56ef7c5effd6dc7aa52abdba Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 9 Oct 2024 20:34:14 +0200 Subject: [PATCH 41/41] wrap up --- src/chains.ts | 60 +++++++++++++++++++++++++++++++++-------- src/chains.unit.test.ts | 33 ++++++++++++++++++----- 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/src/chains.ts b/src/chains.ts index 6ff78053..04dc167c 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -1,4 +1,4 @@ -import { defineChain, Chain, ChainContract, isAddress } from 'viem'; +import { defineChain, Chain, ChainContract, isAddress, zeroAddress } from 'viem'; import { mainnet, arbitrum as arbitrumOne, @@ -65,22 +65,60 @@ export function getCustomParentChains(): Chain[] { return Object.values(customParentChains); } -export function registerCustomParentChain(chain: Chain) { - const rollupCreator = chain.contracts?.rollupCreator as ChainContract | undefined; - const rollupCreatorAddress = rollupCreator?.address; - - const tokenBridgeCreator = chain.contracts?.tokenBridgeCreator as ChainContract | undefined; - const tokenBridgeCreatorAddress = tokenBridgeCreator?.address; +/** + * Registers a custom parent chain. + * + * @param {Chain} chain Regular `Chain` object with mandatory `contracts.rollupCreator` and `contracts.tokenBridgeCreator` fields. + * + * @example + * registerCustomParentChain({ + * id: 123_456, + * name: `My Chain`, + * network: `my-chain`, + * nativeCurrency: { + * name: 'Ether', + * symbol: 'ETH', + * decimals: 18, + * }, + * rpcUrls: { + * public: { + * http: ['http://localhost:8080'], + * }, + * default: { + * http: ['http://localhost:8080'], + * }, + * }, + * // these are mandatory + * contracts: { + * rollupCreator: { + * address: '0x0000000000000000000000000000000000000001', + * }, + * tokenBridgeCreator: { + * address: '0x0000000000000000000000000000000000000002', + * }, + * }, + * }); + */ +export function registerCustomParentChain( + chain: Chain & { + contracts: { + rollupCreator: ChainContract; + tokenBridgeCreator: ChainContract; + }; + }, +) { + const rollupCreator = chain.contracts.rollupCreator.address; + const tokenBridgeCreator = chain.contracts.tokenBridgeCreator.address; - if (typeof rollupCreatorAddress === 'undefined' || !isAddress(rollupCreatorAddress)) { + if (!isAddress(rollupCreator) || rollupCreator === zeroAddress) { throw new Error( - `"contracts.rollupCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, + `"contracts.rollupCreator.address" is invalid for custom parent chain with id ${chain.id}`, ); } - if (typeof tokenBridgeCreatorAddress === 'undefined' || !isAddress(tokenBridgeCreatorAddress)) { + if (!isAddress(tokenBridgeCreator) || tokenBridgeCreator === zeroAddress) { throw new Error( - `"contracts.tokenBridgeCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, + `"contracts.tokenBridgeCreator.address" is invalid for custom parent chain with id ${chain.id}`, ); } diff --git a/src/chains.unit.test.ts b/src/chains.unit.test.ts index 5258f6c2..ec5d7443 100644 --- a/src/chains.unit.test.ts +++ b/src/chains.unit.test.ts @@ -4,27 +4,46 @@ import { getCustomParentChains, registerCustomParentChain } from './chains'; import { testHelper_createCustomParentChain } from './testHelpers'; describe('registerCustomParentChain', () => { - it(`throws if the RollupCreator address wasn't provided`, () => { + it(`throws if "contracts.rollupCreator.address" is invalid`, () => { // omit contracts from the chain const { contracts, ...chain } = testHelper_createCustomParentChain(); - expect(() => registerCustomParentChain(chain)).toThrowError( - `"contracts.rollupCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, + expect(() => + registerCustomParentChain({ + ...chain, + contracts: { + rollupCreator: { + address: '0x123', + }, + tokenBridgeCreator: { + address: '0x123', + }, + }, + }), + ).toThrowError( + `"contracts.rollupCreator.address" is invalid for custom parent chain with id ${chain.id}`, ); }); - it(`throws if the TokenBridgeCreator address wasn't provided`, () => { + it(`throws if "contracts.tokenBridgeCreator.address" is invalid`, () => { // omit contracts from the chain const { contracts, ...chain } = testHelper_createCustomParentChain(); expect(() => registerCustomParentChain({ ...chain, - // add in only RollupCreator - contracts: { rollupCreator: contracts.rollupCreator }, + contracts: { + rollupCreator: { + // use a correct address for the RollupCreator + address: contracts.rollupCreator.address, + }, + tokenBridgeCreator: { + address: '0x0', + }, + }, }), ).toThrowError( - `"contracts.tokenBridgeCreator.address" is missing or invalid for custom parent chain with id ${chain.id}`, + `"contracts.tokenBridgeCreator.address" is invalid for custom parent chain with id ${chain.id}`, ); });