From 9199d0da3a4b0e91391c25baf60a0db13a9d967d Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 20 Dec 2023 18:29:21 +0100 Subject: [PATCH 1/2] feat: add support for nitro-testnode (#21) --- src/chains.ts | 43 +++++++++++++++++++++++++++++-- src/createRollupGetMaxDataSize.ts | 4 +-- src/package.json | 7 +++++ src/prepareNodeConfig.ts | 9 ++++++- wagmi.config.ts | 24 ++++++++++++++++- 5 files changed, 81 insertions(+), 6 deletions(-) diff --git a/src/chains.ts b/src/chains.ts index 91b5bd23..ae120967 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -1,4 +1,43 @@ +import { defineChain } from 'viem'; import { sepolia, arbitrumSepolia } from 'viem/chains'; -export const chains = [sepolia, arbitrumSepolia]; -export { sepolia, arbitrumSepolia }; +const nitroTestnodeL1 = defineChain({ + id: 1_337, + network: 'Nitro Testnode L1', + name: 'nitro-testnode-l1', + nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, + rpcUrls: { + default: { + http: ['http://127.0.0.1:8545'], + }, + public: { + http: ['http://127.0.0.1:8545'], + }, + }, + testnet: true, +}); + +const nitroTestnodeL2 = defineChain({ + id: 412_346, + network: 'Nitro Testnode L2', + name: 'nitro-testnode-l2', + nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, + rpcUrls: { + default: { + http: ['http://127.0.0.1:8547'], + }, + public: { + http: ['http://127.0.0.1:8547'], + }, + }, + testnet: true, +}); + +export const chains = [ + sepolia, + arbitrumSepolia, + nitroTestnodeL1, + nitroTestnodeL2, +] as const; + +export { sepolia, arbitrumSepolia, nitroTestnodeL1, nitroTestnodeL2 }; diff --git a/src/createRollupGetMaxDataSize.ts b/src/createRollupGetMaxDataSize.ts index b590adad..db7368e0 100644 --- a/src/createRollupGetMaxDataSize.ts +++ b/src/createRollupGetMaxDataSize.ts @@ -1,9 +1,9 @@ -import { sepolia } from './chains'; +import { sepolia, nitroTestnodeL1 } from './chains'; import { ParentChainId } from './types/ParentChain'; export function createRollupGetMaxDataSize(parentChainId: ParentChainId) { // L2 - if (parentChainId === sepolia.id) { + if (parentChainId === sepolia.id || parentChainId === nitroTestnodeL1.id) { return BigInt(117_964); } diff --git a/src/package.json b/src/package.json index 637d3c72..5d7a5838 100644 --- a/src/package.json +++ b/src/package.json @@ -11,6 +11,10 @@ "types": "./dist/index.d.ts", "default": "./dist/index.js" }, + "./chains": { + "types": "./dist/chains.d.ts", + "default": "./dist/chains.js" + }, "./contracts": { "types": "./dist/contracts.d.ts", "default": "./dist/contracts.js" @@ -22,6 +26,9 @@ }, "typesVersions": { "*": { + "chains": [ + "./dist/chains.d.ts" + ], "contracts": [ "./dist/contracts.d.ts" ], diff --git a/src/prepareNodeConfig.ts b/src/prepareNodeConfig.ts index ace51245..9089e375 100644 --- a/src/prepareNodeConfig.ts +++ b/src/prepareNodeConfig.ts @@ -6,7 +6,12 @@ import { import { ChainConfig } from './types/ChainConfig'; import { CoreContracts } from './types/CoreContracts'; import { ParentChainId, validParentChainId } from './types/ParentChain'; -import { sepolia, arbitrumSepolia } from './chains'; +import { + sepolia, + arbitrumSepolia, + nitroTestnodeL1, + nitroTestnodeL2, +} from './chains'; function sanitizePrivateKey(privateKey: string) { return privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey; @@ -26,9 +31,11 @@ function parentChainIsArbitrum(parentChainId: ParentChainId): boolean { // doing switch here to make sure it's exhaustive when checking against `ParentChainId` switch (parentChainId) { case sepolia.id: + case nitroTestnodeL1.id: return false; case arbitrumSepolia.id: + case nitroTestnodeL2.id: return true; } } diff --git a/wagmi.config.ts b/wagmi.config.ts index da2bd556..c92ed9e0 100644 --- a/wagmi.config.ts +++ b/wagmi.config.ts @@ -2,7 +2,12 @@ import { erc, etherscan } from '@wagmi/cli/plugins'; import dotenv from 'dotenv'; import { ParentChainId } from './src'; -import { sepolia, arbitrumSepolia } from './src/chains'; +import { + sepolia, + arbitrumSepolia, + nitroTestnodeL1, + nitroTestnodeL2, +} from './src/chains'; dotenv.config(); @@ -17,8 +22,12 @@ function sleep(ms: number = 3_000) { } const blockExplorerApiUrls: Record = { + // testnet [sepolia.id]: 'https://api-sepolia.etherscan.io/api', [arbitrumSepolia.id]: 'https://api-sepolia.arbiscan.io/api', + // local nitro-testnode / fine to omit these as we skip abi fetch + [nitroTestnodeL1.id]: '', + [nitroTestnodeL2.id]: '', }; export async function fetchAbi(chainId: ParentChainId, address: `0x${string}`) { @@ -40,16 +49,24 @@ const contracts: ContractConfig[] = [ name: 'RollupCreator', version: '1.1.0', address: { + // testnet [sepolia.id]: '0xfbd0b034e6305788007f6e0123cc5eae701a5751', [arbitrumSepolia.id]: '0x06E341073b2749e0Bb9912461351f716DeCDa9b0', + // local nitro-testnode (on "use-tokenbridge-creator" branch) + [nitroTestnodeL1.id]: '0x596eabe0291d4cdafac7ef53d16c92bf6922b5e0', + [nitroTestnodeL2.id]: '0x3BaF9f08bAD68869eEdEa90F2Cc546Bd80F1A651', }, }, { name: 'TokenBridgeCreator', version: '1.1.2', address: { + // testnet [sepolia.id]: '0x7612718D3143C791B2Ff5c01a9a7D02CEf00AE9c', [arbitrumSepolia.id]: '0xb462C69f8f638d2954c9618B03765FC1770190cF', + // local nitro-testnode (on "use-tokenbridge-creator" branch) + [nitroTestnodeL1.id]: '0x4a2ba922052ba54e29c5417bc979daaf7d5fe4f4', + [nitroTestnodeL2.id]: '0x38f35af53bf913c439eab06a367e09d6eb253492', }, }, { @@ -75,6 +92,11 @@ export async function assertContractAbisMatch(contract: ContractConfig) { const abis = await Promise.all( Object.entries(contract.address) + // don't fetch abis for testnode + .filter(([chainIdString]) => { + const chainId = Number(chainIdString); + return chainId !== nitroTestnodeL1.id && chainId !== nitroTestnodeL2.id; + }) // fetch abis for all chains .map(([chainId, address]) => fetchAbi(Number(chainId) as ParentChainId, address) From 8dec14c18b72a5b8f342538a8e60dcbe98343d5e Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 20 Dec 2023 18:33:46 +0100 Subject: [PATCH 2/2] feat: deploy factories by default (#23) --- .../index.ts | 0 .../package.json | 2 +- .../tsconfig.json | 0 examples/{eth => create-rollup-eth}/index.ts | 0 .../package.json | 2 +- .../tsconfig.json | 0 .../package.json | 13 --- examples/custom-fee-token/index.ts | 90 ------------------- .../eth-with-deterministic-factories/index.ts | 90 ------------------- .../package.json | 13 --- .../tsconfig.json | 4 - examples/eth/tsconfig.json | 4 - src/createRollupDefaults.ts | 2 +- 13 files changed, 3 insertions(+), 217 deletions(-) rename examples/{custom-fee-token-with-deterministic-factories => create-rollup-custom-fee-token}/index.ts (100%) rename examples/{eth => create-rollup-custom-fee-token}/package.json (83%) rename examples/{custom-fee-token-with-deterministic-factories => create-rollup-custom-fee-token}/tsconfig.json (100%) rename examples/{eth => create-rollup-eth}/index.ts (100%) rename examples/{custom-fee-token => create-rollup-eth}/package.json (87%) rename examples/{custom-fee-token => create-rollup-eth}/tsconfig.json (100%) delete mode 100644 examples/custom-fee-token-with-deterministic-factories/package.json delete mode 100644 examples/custom-fee-token/index.ts delete mode 100644 examples/eth-with-deterministic-factories/index.ts delete mode 100644 examples/eth-with-deterministic-factories/package.json delete mode 100644 examples/eth-with-deterministic-factories/tsconfig.json delete mode 100644 examples/eth/tsconfig.json diff --git a/examples/custom-fee-token-with-deterministic-factories/index.ts b/examples/create-rollup-custom-fee-token/index.ts similarity index 100% rename from examples/custom-fee-token-with-deterministic-factories/index.ts rename to examples/create-rollup-custom-fee-token/index.ts diff --git a/examples/eth/package.json b/examples/create-rollup-custom-fee-token/package.json similarity index 83% rename from examples/eth/package.json rename to examples/create-rollup-custom-fee-token/package.json index 5b6c1c73..398ad20f 100644 --- a/examples/eth/package.json +++ b/examples/create-rollup-custom-fee-token/package.json @@ -1,5 +1,5 @@ { - "name": "eth", + "name": "create-rollup-custom-fee-token", "private": true, "version": "0.0.0", "type": "module", diff --git a/examples/custom-fee-token-with-deterministic-factories/tsconfig.json b/examples/create-rollup-custom-fee-token/tsconfig.json similarity index 100% rename from examples/custom-fee-token-with-deterministic-factories/tsconfig.json rename to examples/create-rollup-custom-fee-token/tsconfig.json diff --git a/examples/eth/index.ts b/examples/create-rollup-eth/index.ts similarity index 100% rename from examples/eth/index.ts rename to examples/create-rollup-eth/index.ts diff --git a/examples/custom-fee-token/package.json b/examples/create-rollup-eth/package.json similarity index 87% rename from examples/custom-fee-token/package.json rename to examples/create-rollup-eth/package.json index bfa67292..1f274307 100644 --- a/examples/custom-fee-token/package.json +++ b/examples/create-rollup-eth/package.json @@ -1,5 +1,5 @@ { - "name": "custom-fee-token", + "name": "create-rollup-eth", "private": true, "version": "0.0.0", "type": "module", diff --git a/examples/custom-fee-token/tsconfig.json b/examples/create-rollup-eth/tsconfig.json similarity index 100% rename from examples/custom-fee-token/tsconfig.json rename to examples/create-rollup-eth/tsconfig.json diff --git a/examples/custom-fee-token-with-deterministic-factories/package.json b/examples/custom-fee-token-with-deterministic-factories/package.json deleted file mode 100644 index 8a48a96e..00000000 --- a/examples/custom-fee-token-with-deterministic-factories/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "custom-fee-token-with-deterministic-factories", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "tsc --outDir dist && node ./dist/index.js" - }, - "devDependencies": { - "@types/node": "^20.9.0", - "typescript": "^5.2.2" - } -} diff --git a/examples/custom-fee-token/index.ts b/examples/custom-fee-token/index.ts deleted file mode 100644 index 69d6a6a2..00000000 --- a/examples/custom-fee-token/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Chain, createPublicClient, http } from 'viem'; -import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; -import { arbitrumSepolia } from 'viem/chains'; -import { - createRollupPrepareConfig, - prepareChainConfig, - createRollupPrepareTransactionRequest, - createRollupPrepareTransactionReceipt, -} from '@arbitrum/orbit-sdk'; -import { generateChainId } from '@arbitrum/orbit-sdk/utils'; - -function sanitizePrivateKey(privateKey: string): `0x${string}` { - if (!privateKey.startsWith('0x')) { - return `0x${privateKey}`; - } - - return privateKey as `0x${string}`; -} - -function withFallbackPrivateKey(privateKey: string | undefined): `0x${string}` { - if (typeof privateKey === 'undefined') { - return generatePrivateKey(); - } - - return sanitizePrivateKey(privateKey); -} - -function getBlockExplorerUrl(chain: Chain) { - return chain.blockExplorers?.default.url; -} - -if (typeof process.env.DEPLOYER_PRIVATE_KEY === 'undefined') { - throw new Error(`Please provide the "DEPLOYER_PRIVATE_KEY" environment variable`); -} - -// load or generate a random batch poster account -const batchPosterPrivateKey = withFallbackPrivateKey(process.env.BATCH_POSTER_PRIVATE_KEY); -const batchPoster = privateKeyToAccount(batchPosterPrivateKey).address; - -// load or generate a random validator account -const validatorPrivateKey = withFallbackPrivateKey(process.env.VALIDATOR_PRIVATE_KEY); -const validator = privateKeyToAccount(validatorPrivateKey).address; - -// set the parent chain and create a public client for it -const parentChain = arbitrumSepolia; -const parentChainPublicClient = createPublicClient({ chain: parentChain, transport: http() }); - -// load the deployer account -const deployer = privateKeyToAccount(sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY)); - -async function main() { - // generate a random chain id - const chainId = generateChainId(); - - // create the chain config - const chainConfig = prepareChainConfig({ - chainId, - arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, - }); - - // prepare the transaction for deploying the core contracts - const request = await createRollupPrepareTransactionRequest({ - params: { - config: createRollupPrepareConfig({ - chainId: BigInt(chainId), - owner: deployer.address, - chainConfig, - }), - batchPoster, - validators: [validator], - nativeToken: '0xf861378b543525ae0c47d33c90c954dc774ac1f9', // $ARB - }, - account: deployer.address, - publicClient: parentChainPublicClient, - }); - - // sign and send the transaction - const txHash = await parentChainPublicClient.sendRawTransaction({ - serializedTransaction: await deployer.signTransaction(request), - }); - - // get the transaction receipt after waiting for the transaction to complete - const txReceipt = createRollupPrepareTransactionReceipt( - await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }) - ); - - console.log(`Deployed in ${getBlockExplorerUrl(parentChain)}/tx/${txReceipt.transactionHash}`); -} - -main(); diff --git a/examples/eth-with-deterministic-factories/index.ts b/examples/eth-with-deterministic-factories/index.ts deleted file mode 100644 index 39e3a35b..00000000 --- a/examples/eth-with-deterministic-factories/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Chain, createPublicClient, http } from 'viem'; -import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; -import { arbitrumSepolia } from 'viem/chains'; -import { - createRollupPrepareConfig, - prepareChainConfig, - createRollupPrepareTransactionRequest, - createRollupPrepareTransactionReceipt, -} from '@arbitrum/orbit-sdk'; -import { generateChainId } from '@arbitrum/orbit-sdk/utils'; - -function sanitizePrivateKey(privateKey: string): `0x${string}` { - if (!privateKey.startsWith('0x')) { - return `0x${privateKey}`; - } - - return privateKey as `0x${string}`; -} - -function withFallbackPrivateKey(privateKey: string | undefined): `0x${string}` { - if (typeof privateKey === 'undefined') { - return generatePrivateKey(); - } - - return sanitizePrivateKey(privateKey); -} - -function getBlockExplorerUrl(chain: Chain) { - return chain.blockExplorers?.default.url; -} - -if (typeof process.env.DEPLOYER_PRIVATE_KEY === 'undefined') { - throw new Error(`Please provide the "DEPLOYER_PRIVATE_KEY" environment variable`); -} - -// load or generate a random batch poster account -const batchPosterPrivateKey = withFallbackPrivateKey(process.env.BATCH_POSTER_PRIVATE_KEY); -const batchPoster = privateKeyToAccount(batchPosterPrivateKey).address; - -// load or generate a random validator account -const validatorPrivateKey = withFallbackPrivateKey(process.env.VALIDATOR_PRIVATE_KEY); -const validator = privateKeyToAccount(validatorPrivateKey).address; - -// set the parent chain and create a public client for it -const parentChain = arbitrumSepolia; -const parentChainPublicClient = createPublicClient({ chain: parentChain, transport: http() }); - -// load the deployer account -const deployer = privateKeyToAccount(sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY)); - -async function main() { - // generate a random chain id - const chainId = generateChainId(); - - // create the chain config - const chainConfig = prepareChainConfig({ - chainId, - arbitrum: { InitialChainOwner: deployer.address, DataAvailabilityCommittee: true }, - }); - - // prepare the transaction for deploying the core contracts - const request = await createRollupPrepareTransactionRequest({ - params: { - config: createRollupPrepareConfig({ - chainId: BigInt(chainId), - owner: deployer.address, - chainConfig, - }), - batchPoster, - validators: [validator], - deployFactoriesToL2: true, - }, - account: deployer.address, - publicClient: parentChainPublicClient, - }); - - // sign and send the transaction - const txHash = await parentChainPublicClient.sendRawTransaction({ - serializedTransaction: await deployer.signTransaction(request), - }); - - // get the transaction receipt after waiting for the transaction to complete - const txReceipt = createRollupPrepareTransactionReceipt( - await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }) - ); - - console.log(`Deployed in ${getBlockExplorerUrl(parentChain)}/tx/${txReceipt.transactionHash}`); -} - -main(); diff --git a/examples/eth-with-deterministic-factories/package.json b/examples/eth-with-deterministic-factories/package.json deleted file mode 100644 index 03c6f99c..00000000 --- a/examples/eth-with-deterministic-factories/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "eth-with-deterministic-factories", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "tsc --outDir dist && node ./dist/index.js" - }, - "devDependencies": { - "@types/node": "^20.9.0", - "typescript": "^5.2.2" - } -} diff --git a/examples/eth-with-deterministic-factories/tsconfig.json b/examples/eth-with-deterministic-factories/tsconfig.json deleted file mode 100644 index abf0a90d..00000000 --- a/examples/eth-with-deterministic-factories/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../tsconfig.base.json", - "include": ["./**/*"] -} diff --git a/examples/eth/tsconfig.json b/examples/eth/tsconfig.json deleted file mode 100644 index abf0a90d..00000000 --- a/examples/eth/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../tsconfig.base.json", - "include": ["./**/*"] -} diff --git a/src/createRollupDefaults.ts b/src/createRollupDefaults.ts index fb96e174..380bc888 100644 --- a/src/createRollupDefaults.ts +++ b/src/createRollupDefaults.ts @@ -2,6 +2,6 @@ import { zeroAddress, parseGwei } from 'viem'; export const defaults = { nativeToken: zeroAddress, - deployFactoriesToL2: false, + deployFactoriesToL2: true, maxFeePerGasForRetryables: parseGwei(String('0.1')), };