From 542fa73e3f381e73612ba87f9d1a567a5d64c7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20FP?= <105675159+TucksonDev@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:46:55 +0100 Subject: [PATCH 01/54] feat: fast-withdrawal setup script (#143) --- examples/setup-fast-withdrawal/.env.example | 14 + examples/setup-fast-withdrawal/README.md | 54 +++ examples/setup-fast-withdrawal/index.ts | 317 ++++++++++++++++++ examples/setup-fast-withdrawal/package.json | 13 + examples/setup-fast-withdrawal/tsconfig.json | 4 + src/createSafePrepareTransactionReceipt.ts | 54 +++ src/createSafePrepareTransactionRequest.ts | 164 +++++++++ src/index.ts | 19 ++ src/package.json | 1 + ...tFastConfirmerPrepareTransactionRequest.ts | 74 ++++ src/types/ParentChain.ts | 4 +- src/utils/getParentChainFromId.ts | 15 + src/utils/index.ts | 2 + yarn.lock | 74 +++- 14 files changed, 806 insertions(+), 3 deletions(-) create mode 100644 examples/setup-fast-withdrawal/.env.example create mode 100644 examples/setup-fast-withdrawal/README.md create mode 100644 examples/setup-fast-withdrawal/index.ts create mode 100644 examples/setup-fast-withdrawal/package.json create mode 100644 examples/setup-fast-withdrawal/tsconfig.json create mode 100644 src/createSafePrepareTransactionReceipt.ts create mode 100644 src/createSafePrepareTransactionRequest.ts create mode 100644 src/setAnyTrustFastConfirmerPrepareTransactionRequest.ts create mode 100644 src/utils/getParentChainFromId.ts diff --git a/examples/setup-fast-withdrawal/.env.example b/examples/setup-fast-withdrawal/.env.example new file mode 100644 index 00000000..24b996ba --- /dev/null +++ b/examples/setup-fast-withdrawal/.env.example @@ -0,0 +1,14 @@ +# Private key of an account with executor privileges in the UpgradeExecutor admin contract for the chain. +CHAIN_OWNER_PRIVATE_KEY= + +# Parent chain id +PARENT_CHAIN_ID=421614 + +# Address of the Rollup contract +ROLLUP_ADDRESS= + +# Fast-confirmation validators (comma-separated array) +FC_VALIDATORS=["0x1234567890123456789012345678901234567890", "0x1234567890123456789012345678901234567891"] + +# Minimum number of blocks that have to pass in between assertions (measured in L1 blocks) +MINIMUM_ASSERTION_PERIOD=75 diff --git a/examples/setup-fast-withdrawal/README.md b/examples/setup-fast-withdrawal/README.md new file mode 100644 index 00000000..d7e8663c --- /dev/null +++ b/examples/setup-fast-withdrawal/README.md @@ -0,0 +1,54 @@ +# Setup a fast-withdrawal committee for your AnyTrust Orbit chain + +This example script shows how to setup a fast-withdrawal committee for your AnyTrust Orbit chain. + +## Rationale + +Optimistic rollups must sustain a multi-day challenge period to allow time for fraud proofs. This delays finality for users and apps, resulting in multi-day withdrawal times and cross-chain communication delays. + +Fast Withdrawals is a new configuration allowing Orbit chains to achieve fast finality. Orbit chains with Fast Withdrawals will have their transactions processed by a committee of validators. Transactions with a unanimous vote across the committee will have their state transition immediately confirmed. + +This will allow: + +- Orbit chains can configure a fast confirmation frequency (any time up to 15 minutes) +- User withdrawals to are confirmed on the parent chain at frequencies up to ~15 minutes +- Enhanced cross-chain communication by allowing cross-chain apps to read finalized state up to the fast confirmation frequency + +## How it works + +This script performs the following operations: + +1. Create a new n/n Safe wallet with the specified validators as signers +2. Add the specified validators to the Rollup validators whitelist +3. Set the new Safe wallet as the anytrustFastConfirmer in the Rollup contract +4. Set the new minimumAssertionPeriod if needed +5. Show how to configure the batch poster and validator nodes + +## Variables needed + +You need to set the following environment variables in an .env file: + +- CHAIN_OWNER_PRIVATE_KEY: private key of the account with executor privileges in the UpgradeExecutor admin contract for the chain. It will be the deployer of the multisig Safe wallet. +- PARENT_CHAIN_ID: chainId of the parent chain. +- ROLLUP_ADDRESS: address of the Rollup contract. +- FC_VALIDATORS: array of fast-withdrawal validators. They will be added as signers to the multisig Safe wallet, and will be added to the Rollup's validator whitelist. +- MINIMUM_ASSERTION_PERIOD: optional parameter. Minimum number of blocks that have to pass in between assertions (measured in L1 blocks). + +## Setup + +1. Install dependencies + + ```bash + yarn install + ``` + +2. Create .env file and add the env vars + + ```bash + cp .env.example .env + ``` + +3. Run the example + ```bash + yarn dev + ``` diff --git a/examples/setup-fast-withdrawal/index.ts b/examples/setup-fast-withdrawal/index.ts new file mode 100644 index 00000000..6ad4f0d6 --- /dev/null +++ b/examples/setup-fast-withdrawal/index.ts @@ -0,0 +1,317 @@ +import { Chain, createPublicClient, http, isAddress, Address, parseAbi } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { + createRollupFetchTransactionHash, + createRollupPrepareTransactionReceipt, + createSafePrepareTransactionReceipt, + createSafePrepareTransactionRequest, + rollupAdminLogicPublicActions, + setAnyTrustFastConfirmerPrepareTransactionRequest, +} from '@arbitrum/orbit-sdk'; +import { sanitizePrivateKey, getParentChainFromId } from '@arbitrum/orbit-sdk/utils'; +import { base, baseSepolia } from '@arbitrum/orbit-sdk/chains'; +import { config } from 'dotenv'; +config(); + +// helper functions +function getBlockExplorerUrl(chain: Chain) { + return chain.blockExplorers?.default.url; +} + +function getTimeDelayFromNumberOfBlocks(chainId: number, blocks: bigint): string { + // For Arbitrum L2s built on top of Ethereum, or Arbitrum L3s built on top of an Arbitrum L2, `block.number` always returns the L1 block number. + // L1 blocks are produced every 12 seconds. + // + // For Arbitrum L3s built on top of an OP Stack L2, `block.number` will return the L2 block number. + // L2 blocks in OP Stack chains are produced every 2 seconds. + const seconds = Number( + chainId === base.id || chainId === baseSepolia.id ? blocks * 2n : blocks * 12n, + ); + + const h = Math.floor(seconds / 3600); + const m = Math.floor((seconds % 3600) / 60); + const s = seconds % 60; + return `${h}h${m}m${s}s`; +} + +// check environment variables +if (typeof process.env.CHAIN_OWNER_PRIVATE_KEY === 'undefined') { + throw new Error(`Please provide the "CHAIN_OWNER_PRIVATE_KEY" environment variable`); +} + +if (typeof process.env.PARENT_CHAIN_ID === 'undefined') { + throw new Error(`Please provide the "PARENT_CHAIN_ID" environment variable`); +} + +if (typeof process.env.ROLLUP_ADDRESS === 'undefined') { + throw new Error(`Please provide the "ROLLUP_ADDRESS" environment variable`); +} + +if (typeof process.env.FC_VALIDATORS === 'undefined') { + throw new Error(`Please provide the "FC_VALIDATORS" environment variable`); +} + +// rollup address +const rollupAddress = process.env.ROLLUP_ADDRESS as Address; + +// set the parent chain and create a public client for it +const parentChain = getParentChainFromId(Number(process.env.PARENT_CHAIN_ID)); +const parentChainPublicClient = createPublicClient({ + chain: parentChain, + transport: http(), +}).extend( + rollupAdminLogicPublicActions({ + rollup: rollupAddress, + }), +); + +// load the deployer account +const safeOwner = privateKeyToAccount(sanitizePrivateKey(process.env.CHAIN_OWNER_PRIVATE_KEY)); + +// sanitize validator addresses +const fcValidators = JSON.parse(process.env.FC_VALIDATORS); +const safeWalletThreshold = fcValidators.length; +if (!fcValidators) { + throw new Error(`The "FC_VALIDATORS" environment variable must be a valid array`); +} + +const sanitizedFcValidators = [ + ...new Set( + fcValidators.filter((validator: `0x${string}`) => + isAddress(validator) ? validator : undefined, + ), + ), +]; +if (sanitizedFcValidators.length !== safeWalletThreshold) { + throw new Error( + `Some of the addresses in the "FC_VALIDATORS" environment variable appear to not be valid or duplicated.`, + ); +} + +// minimum assertion period +// (not required, by setting a default) +const minimumAssertionPeriod = BigInt(process.env.MINIMUM_ASSERTION_PERIOD || 75); + +async function main() { + // + // Step 0. Gather necessary data (UpgradeExecutor address) + // + const transactionHash = await createRollupFetchTransactionHash({ + rollup: rollupAddress, + publicClient: parentChainPublicClient, + }); + const transactionReceipt = createRollupPrepareTransactionReceipt( + await parentChainPublicClient.getTransactionReceipt({ hash: transactionHash }), + ); + const coreContracts = transactionReceipt.getCoreContracts(); + const upgradeExecutorAddress = coreContracts.upgradeExecutor; + + // + // Step 1. Create Safe multisig + // + console.log( + `Step 1: Create a new ${safeWalletThreshold}/${safeWalletThreshold} Safe wallet with the following addresses as signers:`, + fcValidators, + ); + console.log('---'); + + const txRequest = await createSafePrepareTransactionRequest({ + publicClient: parentChainPublicClient, + account: safeOwner, + owners: fcValidators, + threshold: safeWalletThreshold, + saltNonce: BigInt(Date.now()), + }); + + // sign and send the transaction + const txHash = await parentChainPublicClient.sendRawTransaction({ + serializedTransaction: await safeOwner.signTransaction(txRequest), + }); + + // get the transaction receipt after waiting for the transaction to complete + const txReceipt = createSafePrepareTransactionReceipt( + await parentChainPublicClient.waitForTransactionReceipt({ hash: txHash }), + ); + + // get the safe address + const safeAddress = txReceipt.getSafeContract(); + + console.log( + `Safe wallet (${safeAddress}) deployed in transaction ${getBlockExplorerUrl(parentChain)}/tx/${ + txReceipt.transactionHash + }`, + ); + console.log(''); + + // + // Step 2. Add validators to the Orbit chain rollup validator whitelist + // + console.log( + `Step 2: Adding the following validators to the Rollup validator whitelist:`, + fcValidators, + ); + console.log('---'); + + // prepare set validator transaction request + const fcValidatorsStatus = Array(fcValidators.length).fill(true); + const setValidatorTransactionRequest = + await parentChainPublicClient.rollupAdminLogicPrepareTransactionRequest({ + functionName: 'setValidator', + args: [ + fcValidators, // validator address list + fcValidatorsStatus, // validator status list + ], + upgradeExecutor: upgradeExecutorAddress, + account: safeOwner.address, + }); + + // sign and send the transaction + const setValidatorTransactionHash = await parentChainPublicClient.sendRawTransaction({ + serializedTransaction: await safeOwner.signTransaction(setValidatorTransactionRequest), + }); + + // wait for transaction receipt + const setValidatorTransactionReceipt = await parentChainPublicClient.waitForTransactionReceipt({ + hash: setValidatorTransactionHash, + }); + + console.log( + `New validators added in ${getBlockExplorerUrl(parentChain)}/tx/${ + setValidatorTransactionReceipt.transactionHash + }`, + ); + console.log(''); + + // + // Step 3. Configure the multisig address as the `anyTrustFastConfirmer` on the rollup contract using `setAnyTrustFastConfirmer` + // + console.log( + `Step 3: Configure the multisig address as the anyTrustFastConfirmer : ${safeAddress}`, + ); + console.log('---'); + + // get current anyTrustFastConfirmer + const currentAnyTrustFastConfirmer = await parentChainPublicClient.readContract({ + address: rollupAddress, + abi: parseAbi(['function anyTrustFastConfirmer() view returns (address)']), + functionName: 'anyTrustFastConfirmer', + }); + + if (currentAnyTrustFastConfirmer.toLowerCase() !== safeAddress.toLowerCase()) { + // prepare transaction + const setAnyTrustFastConfirmerTransactionRequest = + await setAnyTrustFastConfirmerPrepareTransactionRequest({ + publicClient: parentChainPublicClient, + account: safeOwner, + rollup: rollupAddress, + upgradeExecutor: upgradeExecutorAddress, + fastConfirmer: safeAddress, + }); + + // sign and send the transaction + const setAnyTrustFastConfirmerTransactionHash = + await parentChainPublicClient.sendRawTransaction({ + serializedTransaction: await safeOwner.signTransaction( + setAnyTrustFastConfirmerTransactionRequest, + ), + }); + + // wait for transaction receipt + const setAnyTrustFastConfirmerTransactionReceipt = + await parentChainPublicClient.waitForTransactionReceipt({ + hash: setAnyTrustFastConfirmerTransactionHash, + }); + + console.log( + `New AnyTrust fast confirmer set in ${getBlockExplorerUrl(parentChain)}/tx/${ + setAnyTrustFastConfirmerTransactionReceipt.transactionHash + }`, + ); + } else { + console.log( + `AnyTrust fast confirmer is already configured to ${currentAnyTrustFastConfirmer}. Skipping.`, + ); + } + console.log(''); + + // + // Step 4. Configure `minimumAssertionPeriod` on the rollup contract using `setMinimumAssertionPeriod` + // + console.log( + `Step 4: Configure the minimumAssertionPeriod in the Rollup contract to: ${Number( + minimumAssertionPeriod, + )}`, + ); + console.log('---'); + + // get current minimumAssertionPeriod + const currentMinimumAssertionPeriod = await parentChainPublicClient.rollupAdminLogicReadContract({ + functionName: 'minimumAssertionPeriod', + }); + + if (currentMinimumAssertionPeriod !== minimumAssertionPeriod) { + // prepare setMinimumAssertionPeriod transaction request + const setMinimumAssertionPeriodTransactionRequest = + await parentChainPublicClient.rollupAdminLogicPrepareTransactionRequest({ + functionName: 'setMinimumAssertionPeriod', + args: [minimumAssertionPeriod], + upgradeExecutor: upgradeExecutorAddress, + account: safeOwner.address, + }); + + // sign and send the transaction + const setMinimumAssertionPeriodTransactionHash = + await parentChainPublicClient.sendRawTransaction({ + serializedTransaction: await safeOwner.signTransaction( + setMinimumAssertionPeriodTransactionRequest, + ), + }); + + // wait for transaction receipt + const setMinimumAssertionPeriodTransactionReceipt = + await parentChainPublicClient.waitForTransactionReceipt({ + hash: setMinimumAssertionPeriodTransactionHash, + }); + + console.log( + `Minimum assertion period set in ${getBlockExplorerUrl(parentChain)}/tx/${ + setMinimumAssertionPeriodTransactionReceipt.transactionHash + }`, + ); + } else { + console.log( + `Minimum assertion period is already configured to ${currentMinimumAssertionPeriod}. Skipping.`, + ); + } + console.log(''); + + // + // Step 5. Show a confirmation message with the next steps + // + console.log(`Step 5: Configure your batch poster and your validator nodes`); + console.log(`---`); + console.log( + 'Your chain is now configured with a fast-withdrawal committee. The following instructions show how to configure your batch poster and your validators to start using this feature.', + ); + console.log(''); + + // Batch poster configuration + const timeDelay = getTimeDelayFromNumberOfBlocks(parentChain.id, minimumAssertionPeriod); + console.log('Your batch poster has to run at least nitro v3.x'); + console.log('Add the following parameter:'); + console.log(`--node.batch-poster.max-delay=${timeDelay}`); + console.log(''); + + // Validator configuration + console.log('Your validators have to run at least nitro v3.x'); + console.log('Add the following parameters:'); + console.log(`--node.staker.enable-fast-confirmation=true`); + console.log(`--node.staker.fast-confirm-safe-address=${safeAddress}`); + console.log(`--node.staker.make-assertion-interval=${timeDelay}`); + console.log(''); + + // Final recommendation + console.log('Finally, restart your batch poster and validator nodes.'); +} + +main(); diff --git a/examples/setup-fast-withdrawal/package.json b/examples/setup-fast-withdrawal/package.json new file mode 100644 index 00000000..3d1e0148 --- /dev/null +++ b/examples/setup-fast-withdrawal/package.json @@ -0,0 +1,13 @@ +{ + "name": "setup-fast-withdrawal", + "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/setup-fast-withdrawal/tsconfig.json b/examples/setup-fast-withdrawal/tsconfig.json new file mode 100644 index 00000000..abf0a90d --- /dev/null +++ b/examples/setup-fast-withdrawal/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.base.json", + "include": ["./**/*"] +} diff --git a/src/createSafePrepareTransactionReceipt.ts b/src/createSafePrepareTransactionReceipt.ts new file mode 100644 index 00000000..ed8b7cae --- /dev/null +++ b/src/createSafePrepareTransactionReceipt.ts @@ -0,0 +1,54 @@ +import { + TransactionReceipt, + getAbiItem, + getEventSelector, + Log, + decodeEventLog, + Address, +} from 'viem'; +import { SafeProxyFactoryAbi } from './createSafePrepareTransactionRequest'; + +function findProxyCreationEventLog(txReceipt: TransactionReceipt) { + const abiItem = getAbiItem({ abi: SafeProxyFactoryAbi, name: 'ProxyCreation' }); + const eventSelector = getEventSelector(abiItem); + const log = txReceipt.logs.find((log) => log.topics[0] === eventSelector); + + if (typeof log === 'undefined') { + throw new Error( + `No "ProxyCreation" logs found in logs for transaction: ${txReceipt.transactionHash}`, + ); + } + + return log; +} + +function decodeProxyCreationEventLog(log: Log) { + const decodedEventLog = decodeEventLog({ ...log, abi: SafeProxyFactoryAbi }); + + if (decodedEventLog.eventName !== 'ProxyCreation') { + throw new Error(`Expected "ProxyCreation" event but found: ${decodedEventLog.eventName}`); + } + + return decodedEventLog; +} + +export type CreateSafeTransactionReceipt = TransactionReceipt & { + getSafeContract(): Address; +}; + +/** + * Adds a getSafeContract() function to a regular {@link TransactionReceipt} for transactions that create a new Safe using the default SafeFactory + */ +export function createSafePrepareTransactionReceipt( + txReceipt: TransactionReceipt, +): CreateSafeTransactionReceipt { + return { + ...txReceipt, + getSafeContract: function () { + const eventLog = findProxyCreationEventLog(txReceipt); + const decodedEventLog = decodeProxyCreationEventLog(eventLog); + const { proxy } = decodedEventLog.args; + return proxy; + }, + }; +} diff --git a/src/createSafePrepareTransactionRequest.ts b/src/createSafePrepareTransactionRequest.ts new file mode 100644 index 00000000..f8b3d406 --- /dev/null +++ b/src/createSafePrepareTransactionRequest.ts @@ -0,0 +1,164 @@ +import { + Address, + Chain, + PrivateKeyAccount, + PublicClient, + Transport, + encodeFunctionData, + TransactionRequest, + PrepareTransactionRequestParameters, +} from 'viem'; +import { + DEFAULT_SAFE_VERSION, + SafeAccountConfig, + SafeFactory, + encodeSetupCallData, + getSafeContract, +} from '@safe-global/protocol-kit'; +import { + getChainSpecificDefaultSaltNonce, + validateSafeAccountConfig, +} from '@safe-global/protocol-kit/dist/src/contracts/utils'; +import { validateChain } from './utils/validateChain'; + +export const SafeProxyFactoryAbi = [ + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'contract GnosisSafeProxy', + name: 'proxy', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'singleton', + type: 'address', + }, + ], + name: 'ProxyCreation', + type: 'event', + }, + { + inputs: [ + { + internalType: 'address', + name: '_singleton', + type: 'address', + }, + { + internalType: 'bytes', + name: 'initializer', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'saltNonce', + type: 'uint256', + }, + ], + name: 'createProxyWithNonce', + outputs: [ + { + internalType: 'contract GnosisSafeProxy', + name: 'proxy', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; + +/** + * This type is for the parameters of the createSafePrepareTransactionRequest function + */ +export type CreateSafePrepareTransactionRequestParams = { + publicClient: PublicClient; + account: PrivateKeyAccount; + owners: Address[]; + threshold: number; + saltNonce?: bigint; +}; + +/** + * Prepares the transaction to create a new Safe using the default SafeFactory + * + * It leverages the [Protocol Kit](https://docs.safe.global/sdk/protocol-kit) from the Safe{Core} SDK. + * + * Returns the transaction to sign and send to the blockchain. + * + * @param {CreateSafePrepareTransactionRequestParams} createSafePrepareTransactionRequestParams {@link CreateSafePrepareTransactionRequestParams} + * @param {PublicClient} createSafePrepareTransactionRequestParams.publicClient - A Viem Public Client + * @param {PrivateKeyAccount} createSafePrepareTransactionRequestParams.account - The private key of the deployer of the new Safe + * @param {Address[]} createSafePrepareTransactionRequestParams.owners - Array of addresses of the signers of the Safe + * @param {number} createSafePrepareTransactionRequestParams.threshold - Number of signatures needed to validate a transaction in the Safe + * @param {bigint} createSafePrepareTransactionRequestParams.saltNonce - Optional salt nonce for the call to Create2 + * + * @returns Promise<{@link TransactionRequest}> - the transaction to sign and send to the blockchain. + */ +export async function createSafePrepareTransactionRequest({ + publicClient, + account, + owners, + threshold, + saltNonce, +}: CreateSafePrepareTransactionRequestParams) { + const chainId = validateChain(publicClient); + + // set and validate Safe configuration + const safeAccountConfig: SafeAccountConfig = { + owners, + threshold, + }; + validateSafeAccountConfig(safeAccountConfig); + + // instantiate Safe Factory + const safeFactory = await SafeFactory.init({ + provider: publicClient.chain!.rpcUrls.default.http[0], + }); + + // instantiate Safe Contract + const safeContract = await getSafeContract({ + safeProvider: safeFactory.getSafeProvider(), + safeVersion: DEFAULT_SAFE_VERSION, + }); + + // get Safe Proxy Factory address + const safeProxyFactoryAddress = (await safeFactory.getAddress()) as Address; + + // get Safe Contract address + const safeContractAddress = (await safeContract.getAddress()) as Address; + + // initializer calldata + const initializer = (await encodeSetupCallData({ + safeProvider: safeFactory.getSafeProvider(), + safeAccountConfig, + safeContract, + })) as `0x${string}`; + + // salt nonce + if (!saltNonce) { + saltNonce = BigInt(getChainSpecificDefaultSaltNonce(BigInt(chainId))); + } + + // prepare the transaction request + const request = await publicClient.prepareTransactionRequest({ + chain: publicClient.chain, + to: safeProxyFactoryAddress, + data: encodeFunctionData({ + abi: SafeProxyFactoryAbi, + functionName: 'createProxyWithNonce', + args: [ + safeContractAddress, // _singleton + initializer, // initializer + saltNonce, // saltNonce + ], + }), + account, + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId }; +} diff --git a/src/index.ts b/src/index.ts index 26d85b2e..fd43d9f1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -108,6 +108,18 @@ import { } from './getBatchPosters'; import { getKeysets, GetKeysetsParams, GetKeysetsReturnType } from './getKeysets'; import { isAnyTrust } from './isAnyTrust'; +import { + createSafePrepareTransactionRequest, + CreateSafePrepareTransactionRequestParams, +} from './createSafePrepareTransactionRequest'; +import { + createSafePrepareTransactionReceipt, + CreateSafeTransactionReceipt, +} from './createSafePrepareTransactionReceipt'; +import { + setAnyTrustFastConfirmerPrepareTransactionRequest, + SetAnyTrustFastConfirmerPrepareTransactionRequestParams, +} from './setAnyTrustFastConfirmerPrepareTransactionRequest'; export { arbOwnerPublicActions, @@ -203,4 +215,11 @@ export { GetKeysetsReturnType, // isAnyTrust, + // + createSafePrepareTransactionRequest, + CreateSafePrepareTransactionRequestParams, + createSafePrepareTransactionReceipt, + CreateSafeTransactionReceipt, + setAnyTrustFastConfirmerPrepareTransactionRequest, + SetAnyTrustFastConfirmerPrepareTransactionRequestParams, }; diff --git a/src/package.json b/src/package.json index 2d533ecd..df620330 100644 --- a/src/package.json +++ b/src/package.json @@ -53,6 +53,7 @@ "dependencies": { "@arbitrum/sdk": "^4.0.0-alpha.4", "@arbitrum/token-bridge-contracts": "^1.2.1", + "@safe-global/protocol-kit": "^4.0.2", "ethers": "^5.7.2" } } diff --git a/src/setAnyTrustFastConfirmerPrepareTransactionRequest.ts b/src/setAnyTrustFastConfirmerPrepareTransactionRequest.ts new file mode 100644 index 00000000..b3975b02 --- /dev/null +++ b/src/setAnyTrustFastConfirmerPrepareTransactionRequest.ts @@ -0,0 +1,74 @@ +import { + Address, + Chain, + PrivateKeyAccount, + PublicClient, + Transport, + encodeFunctionData, + parseAbi, +} from 'viem'; +import { validateChain } from './utils/validateChain'; +import { upgradeExecutorEncodeFunctionData } from './upgradeExecutorEncodeFunctionData'; + +/** + * This type is for the parameters of the setAnyTrustFastConfirmerPrepareTransactionRequest function + */ +export type SetAnyTrustFastConfirmerPrepareTransactionRequestParams< + TChain extends Chain | undefined, +> = { + publicClient: PublicClient; + account: PrivateKeyAccount; + rollup: Address; + upgradeExecutor: Address; + fastConfirmer: Address; +}; + +/** + * Prepares the transaction to set the AnyTrust fast confirmer address in the rollup contract + * + * Returns the transaction to sign and send to the blockchain. + * + * @param {SetAnyTrustFastConfirmerPrepareTransactionRequestParams} setAnyTrustFastConfirmerPrepareTransactionRequestParams {@link SetAnyTrustFastConfirmerPrepareTransactionRequestParams} + * @param {PublicClient} setAnyTrustFastConfirmerPrepareTransactionRequestParams.publicClient - A Viem Public Client + * @param {PrivateKeyAccount} setAnyTrustFastConfirmerPrepareTransactionRequestParams.account - The private key of the chain owner or an account with the executor role in the UpgradeExecutor + * @param {Address} setAnyTrustFastConfirmerPrepareTransactionRequestParams.rollup - Address of the Rollup contract + * @param {Address} setAnyTrustFastConfirmerPrepareTransactionRequestParams.upgradeExecutor - Address of the UpgradeExecutor contract + * @param {Address} setAnyTrustFastConfirmerPrepareTransactionRequestParams.fastConfirmer - Address of the fast confirmer validator (usually a Safe multisig) + * + * @returns Promise<{@link TransactionRequest}> - the transaction to sign and send to the blockchain. + */ +export async function setAnyTrustFastConfirmerPrepareTransactionRequest< + TChain extends Chain | undefined, +>({ + publicClient, + account, + rollup, + upgradeExecutor, + fastConfirmer, +}: SetAnyTrustFastConfirmerPrepareTransactionRequestParams) { + const chainId = validateChain(publicClient); + + // prepare the rollup transaction calldata + const setAnyTrustFastConfirmerCalldata = encodeFunctionData({ + abi: parseAbi(['function setAnyTrustFastConfirmer(address _anyTrustFastConfirmer)']), + functionName: 'setAnyTrustFastConfirmer', + args: [fastConfirmer], + }); + + // prepare the transaction request + // @ts-ignore (todo: fix viem type issue) + const request = await publicClient.prepareTransactionRequest({ + chain: publicClient.chain, + to: upgradeExecutor, + data: upgradeExecutorEncodeFunctionData({ + functionName: 'executeCall', + args: [ + rollup, // target + setAnyTrustFastConfirmerCalldata, // targetCallData + ], + }), + account, + }); + + return { ...request, chainId }; +} diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index ff298558..261a24cb 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -11,7 +11,9 @@ export type ParentChainPublicClient = Prettify PublicClient & { chain: { id: ParentChainId } } >; -function isValidParentChainId(parentChainId: number | undefined): parentChainId is ParentChainId { +export function isValidParentChainId( + parentChainId: number | undefined, +): parentChainId is ParentChainId { const ids = chains // exclude nitro-testnode L3 from the list of parent chains .filter((chain) => chain.id !== nitroTestnodeL3.id) diff --git a/src/utils/getParentChainFromId.ts b/src/utils/getParentChainFromId.ts new file mode 100644 index 00000000..1ca8631f --- /dev/null +++ b/src/utils/getParentChainFromId.ts @@ -0,0 +1,15 @@ +import { extractChain } from 'viem'; +import { ParentChain, isValidParentChainId } from '../types/ParentChain'; +import { chains } from '../chains'; + +export function getParentChainFromId(chainId: number): ParentChain { + // Just throws if the chainId is not valid + if (!isValidParentChainId(chainId)) { + throw new Error(`Parent chain not supported: ${chainId}`); + } + + return extractChain({ + chains, + id: chainId, + }) as ParentChain; +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 7fe69947..f9af6393 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,5 @@ import { generateChainId } from './generateChainId'; +import { getParentChainFromId } from './getParentChainFromId'; import { getParentChainLayer } from './getParentChainLayer'; import { sanitizePrivateKey } from './sanitizePrivateKey'; import { getArbOSVersion } from './getArbOSVersion'; @@ -7,6 +8,7 @@ import { getRollupCreatorAddress, getTokenBridgeCreatorAddress } from './getters export { generateChainId, + getParentChainFromId, getParentChainLayer, sanitizePrivateKey, getArbOSVersion, diff --git a/yarn.lock b/yarn.lock index 5c0eec09..fbd7dc01 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + "@arbitrum/nitro-contracts@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@arbitrum/nitro-contracts/-/nitro-contracts-1.1.1.tgz#2d8a2f9ab757bb7654562aebe435bff833c4b98d" @@ -631,6 +636,11 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== +"@noble/hashes@^1.3.3": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -789,6 +799,33 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4" integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g== +"@safe-global/protocol-kit@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@safe-global/protocol-kit/-/protocol-kit-4.0.2.tgz#5555e65359eeb5d210608aaa1ab889df15c14150" + integrity sha512-csmBR22XY0Sgx2Q6WSdRiAPj5UlR3FxrMeoAqUbV7kCzT7SVXBwrsRqLjiW2+B59Dgcxs6fR8aLjl7maweBPXw== + dependencies: + "@noble/hashes" "^1.3.3" + "@safe-global/safe-core-sdk-types" "^5.0.2" + "@safe-global/safe-deployments" "^1.37.0" + abitype "^1.0.2" + ethereumjs-util "^7.1.5" + ethers "^6.13.1" + semver "^7.6.2" + +"@safe-global/safe-core-sdk-types@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-types/-/safe-core-sdk-types-5.0.2.tgz#9552f5793581333c81676986b3eb19697e1c6627" + integrity sha512-UK2WL9nXN/8ez4Upx1D0KhtNXwkEjuV5O2XDem4Jchw5IBCLJnLowUBgEq8Tw4xdB7x2rw72VFAJXYZ/iY4qYw== + dependencies: + abitype "^1.0.2" + +"@safe-global/safe-deployments@^1.37.0": + version "1.37.1" + resolved "https://registry.yarnpkg.com/@safe-global/safe-deployments/-/safe-deployments-1.37.1.tgz#d8293c421b1b7445899aec720061be26bb3c4976" + integrity sha512-duCCQghqw9B/MmHPMXlkPpZwyq3T92unWVnwwhiA8alhush2FZ22+x6uF8bQtk/RYJzkpYzV1tPL/VBLt9U9XQ== + dependencies: + semver "^7.6.2" + "@scure/base@~1.1.0", "@scure/base@~1.1.2": version "1.1.3" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" @@ -845,6 +882,11 @@ dependencies: undici-types "~5.26.4" +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== + "@types/pbkdf2@^3.0.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" @@ -946,6 +988,11 @@ abitype@0.9.8: resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.9.8.tgz#1f120b6b717459deafd213dfbf3a3dd1bf10ae8c" integrity sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ== +abitype@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.5.tgz#29d0daa3eea867ca90f7e4123144c1d1270774b6" + integrity sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -975,6 +1022,11 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -1706,7 +1758,7 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereumjs-util@^7.0.3: +ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -1753,6 +1805,19 @@ ethers@^5.1.0, ethers@^5.7.2: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +ethers@^6.13.1: + version "6.13.1" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.1.tgz#2b9f9c7455cde9d38b30fe6589972eb083652961" + integrity sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.17.1" + event-stream@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-4.0.1.tgz#4092808ec995d0dd75ea4580c1df6a74db2cde65" @@ -3079,7 +3144,7 @@ semver@^5.5.0, semver@^5.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^7.0.0: +semver@^7.0.0, semver@^7.6.2: version "7.6.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== @@ -3372,6 +3437,11 @@ ts-morph@^21.0.1: "@ts-morph/common" "~0.22.0" code-block-writer "^12.0.0" +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslib@^2.0.0: version "2.6.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" From a2e7af02997aa9bf588157ea6f192bfbae1f8d9f Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 17 Jul 2024 15:52:43 +0200 Subject: [PATCH 02/54] refactor: bump @arbitrum/sdk from 4.0.0-alpha.4 to 4.0.0 (#151) --- ...PrepareSetWethGatewayTransactionReceipt.ts | 2 +- ...ateTokenBridgePrepareTransactionReceipt.ts | 2 +- src/package.json | 2 +- yarn.lock | 23 +++++++++++-------- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/createTokenBridgePrepareSetWethGatewayTransactionReceipt.ts b/src/createTokenBridgePrepareSetWethGatewayTransactionReceipt.ts index c0176b68..2b930f00 100644 --- a/src/createTokenBridgePrepareSetWethGatewayTransactionReceipt.ts +++ b/src/createTokenBridgePrepareSetWethGatewayTransactionReceipt.ts @@ -54,7 +54,7 @@ export function createTokenBridgePrepareSetWethGatewayTransactionReceipt< (messagesResults as unknown as [RedeemedRetryableTicket]) // .map((result) => - ethersTransactionReceiptToViemTransactionReceipt(result.txReceipt), + ethersTransactionReceiptToViemTransactionReceipt(result.childTxReceipt), ) as WaitForRetryablesResult ); }, diff --git a/src/createTokenBridgePrepareTransactionReceipt.ts b/src/createTokenBridgePrepareTransactionReceipt.ts index dcd5f06a..8de69fe2 100644 --- a/src/createTokenBridgePrepareTransactionReceipt.ts +++ b/src/createTokenBridgePrepareTransactionReceipt.ts @@ -104,7 +104,7 @@ export function createTokenBridgePrepareTransactionReceipt< (messagesResults as unknown as [RedeemedRetryableTicket, RedeemedRetryableTicket]) // .map((result) => - ethersTransactionReceiptToViemTransactionReceipt(result.txReceipt), + ethersTransactionReceiptToViemTransactionReceipt(result.childTxReceipt), ) as WaitForRetryablesResult ); }, diff --git a/src/package.json b/src/package.json index df620330..f2b506e4 100644 --- a/src/package.json +++ b/src/package.json @@ -51,7 +51,7 @@ "viem": "^1.20.0" }, "dependencies": { - "@arbitrum/sdk": "^4.0.0-alpha.4", + "@arbitrum/sdk": "^4.0.0", "@arbitrum/token-bridge-contracts": "^1.2.1", "@safe-global/protocol-kit": "^4.0.2", "ethers": "^5.7.2" diff --git a/yarn.lock b/yarn.lock index fbd7dc01..75b5dea6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,10 +22,10 @@ "@openzeppelin/contracts-upgradeable" "4.5.2" patch-package "^6.4.7" -"@arbitrum/sdk@^4.0.0-alpha.4": - version "4.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-4.0.0-alpha.4.tgz#d0e64c55d5033c22c0076ba028482eb7d6ed3621" - integrity sha512-hhZkTmFHIrnmrJQ7kKAmMP+YPWwC0j8JGo2UjFQqGfLilhMm1ihNlS29yvShkOjujEIgJYnHBVUt57ffXknlEw== +"@arbitrum/sdk@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-4.0.0.tgz#8eb2deed1a438250acb4084a4bb8fc7eae7659b6" + integrity sha512-wNZFRs4yYxd6Pyc6xEjksp3C59PikmmVPIw49ceMoLY5D0e6xJt2nuA7jjsemDgRe7q6EvLFvHAY2At6XUWrkg== dependencies: "@ethersproject/address" "^5.0.8" "@ethersproject/bignumber" "^5.1.1" @@ -3682,12 +3682,17 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@7.4.6, ws@7.5.10: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== -ws@8.13.0, ws@8.17.1: +ws@8.17.1: version "8.17.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== From e34d98995f9b367bf0a6ba1b8e91291bffda2dfe Mon Sep 17 00:00:00 2001 From: spsjvc Date: Fri, 19 Jul 2024 13:26:13 +0200 Subject: [PATCH 03/54] chore: update yarn.lock --- yarn.lock | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index 75b5dea6..82d2292e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3682,17 +3682,12 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@7.4.6, ws@7.5.10: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -ws@8.13.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - -ws@8.17.1: +ws@8.13.0, ws@8.17.1: version "8.17.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== From 1e5a32be215968c4e184675c4d8fbc142cdbf33b Mon Sep 17 00:00:00 2001 From: spsjvc Date: Fri, 19 Jul 2024 13:33:07 +0200 Subject: [PATCH 04/54] chore: bump version --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index f2b506e4..e38f750b 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.17.0", + "version": "0.17.1", "main": "./dist/index.js", "files": [ "./dist" From 86486d7c60be59f5fbc55af134e110a6858eef68 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Mon, 5 Aug 2024 12:36:33 +0200 Subject: [PATCH 05/54] ci: update node modules install action (#154) --- .github/workflows/build-test.yml | 45 ++++++-------------------------- 1 file changed, 8 insertions(+), 37 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index e8ab29f6..050ac983 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -13,31 +13,15 @@ env: ARBISCAN_API_KEY: ${{ secrets.ARBISCAN_API_KEY }} jobs: - install: - name: 'Install' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - - - name: Install node_modules - uses: OffchainLabs/actions/node-modules/install@main - audit: name: 'Audit' runs-on: ubuntu-latest - needs: install steps: - name: Checkout uses: actions/checkout@v4 - - name: Restore node_modules - uses: OffchainLabs/actions/node-modules/restore@main + - name: Install node_modules + uses: OffchainLabs/actions/node-modules/install@main - name: Run audit run: yarn audit:ci @@ -45,13 +29,12 @@ jobs: check-formatting: name: 'Check Formatting' runs-on: ubuntu-latest - needs: install steps: - name: Checkout uses: actions/checkout@v4 - - name: Restore node_modules - uses: OffchainLabs/actions/node-modules/restore@main + - name: Install node_modules + uses: OffchainLabs/actions/node-modules/install@main - name: Check formatting with Prettier run: yarn prettier:check @@ -59,18 +42,12 @@ jobs: test-unit: name: Test (Unit) runs-on: ubuntu-latest - needs: install steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - - - name: Restore node_modules - uses: OffchainLabs/actions/node-modules/restore@main + - name: Install node_modules + uses: OffchainLabs/actions/node-modules/install@main - name: Copy .env run: cp ./.env.example ./.env @@ -84,18 +61,12 @@ jobs: test-integration: name: Test (Integration) runs-on: ubuntu-latest - needs: install steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - - - name: Restore node_modules - uses: OffchainLabs/actions/node-modules/restore@main + - name: Install node_modules + uses: OffchainLabs/actions/node-modules/install@main - name: Set up the local node uses: OffchainLabs/actions/run-nitro-test-node@main From 264c39720e2bc038813025165babca8b1b2e24c8 Mon Sep 17 00:00:00 2001 From: Fionna Chan <13184582+fionnachan@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:07:58 +0100 Subject: [PATCH 06/54] ci: ignore elliptic advisories (#156) --- audit-ci.jsonc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/audit-ci.jsonc b/audit-ci.jsonc index bf718810..c7e6fbd7 100644 --- a/audit-ci.jsonc +++ b/audit-ci.jsonc @@ -70,6 +70,15 @@ // Uncontrolled resource consumption in braces // eslint and hardhat dependency, only used in dev // from: hardhat>braces & eslint>braces - "GHSA-grv7-fg5c-xmjg" + "GHSA-grv7-fg5c-xmjg", + // elliptic + // waiting for it to release a fix but low severity so we can ignore it + // from: @ethersproject/signing-key>elliptic + // https://github.com/advisories/GHSA-49q7-c7j4-3p7m + "GHSA-49q7-c7j4-3p7m", + // https://github.com/advisories/GHSA-977x-g7h5-7qgw + "GHSA-977x-g7h5-7qgw", + // https://github.com/advisories/GHSA-f7q4-pwc6-w24p + "GHSA-f7q4-pwc6-w24p" ] } From 2808ec1bc477170375afe42c548150ee8689e8a2 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 7 Aug 2024 19:04:52 +0200 Subject: [PATCH 07/54] fix: convert big number to hex string first (#158) --- src/createTokenBridge-ethers.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/createTokenBridge-ethers.ts b/src/createTokenBridge-ethers.ts index 785c3138..21019f20 100644 --- a/src/createTokenBridge-ethers.ts +++ b/src/createTokenBridge-ethers.ts @@ -63,7 +63,8 @@ export async function createTokenBridgeGetInputs< l2Provider, ); const maxSubmissionCostForFactoryEstimation = deployFactoryGasParams.maxSubmissionCost.mul(2); - const maxGasForFactoryEstimation = await l1TokenBridgeCreator.gasLimitForL2FactoryDeployment(); + const maxGasForFactoryEstimation = + (await l1TokenBridgeCreator.gasLimitForL2FactoryDeployment()) as BigNumber; //// run retryable estimate for deploying L2 contracts //// we do this estimate using L2 factory template on L1 because on L2 factory does not yet exist @@ -105,7 +106,7 @@ export async function createTokenBridgeGetInputs< applyPercentIncrease({ base: retryableGasOverrides.maxSubmissionCostForFactory.base ?? - BigInt(maxSubmissionCostForFactoryEstimation.toNumber()), + BigInt(maxSubmissionCostForFactoryEstimation.toHexString()), percentIncrease: retryableGasOverrides.maxSubmissionCostForFactory.percentIncrease, }), ) @@ -117,7 +118,7 @@ export async function createTokenBridgeGetInputs< applyPercentIncrease({ base: retryableGasOverrides.maxGasForFactory.base ?? - BigInt(maxGasForFactoryEstimation.toNumber()), + BigInt(maxGasForFactoryEstimation.toHexString()), percentIncrease: retryableGasOverrides.maxGasForFactory.percentIncrease, }), ) @@ -129,7 +130,7 @@ export async function createTokenBridgeGetInputs< applyPercentIncrease({ base: retryableGasOverrides.maxSubmissionCostForContracts.base ?? - BigInt(maxSubmissionCostForContractsEstimation.toNumber()), + BigInt(maxSubmissionCostForContractsEstimation.toHexString()), percentIncrease: retryableGasOverrides.maxSubmissionCostForContracts.percentIncrease, }), ) @@ -141,7 +142,7 @@ export async function createTokenBridgeGetInputs< applyPercentIncrease({ base: retryableGasOverrides.maxGasForContracts.base ?? - BigInt(gasEstimateToDeployContracts.toNumber()), + BigInt(gasEstimateToDeployContracts.toHexString()), percentIncrease: retryableGasOverrides.maxGasForContracts.percentIncrease, }), ) From 886e0b2ed82d6e76f6c73f999c63443873ea7718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Wed, 7 Aug 2024 19:05:21 +0200 Subject: [PATCH 08/54] docs: update readme --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 24cb7425..45d750fd 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,10 @@ # Arbitrum Orbit SDK -> [!WARNING] -> Disclaimer: This project is an Alpha release and should not be used in a production environment. We are working on getting it ready for mainnet deployments, meanwhile please use it at your own discretion. - TypeScript SDK for building [Arbitrum Orbit](https://arbitrum.io/orbit) chains. ## Installation -Make sure you are using Node v18 or greater. +Make sure you are using Node.js v18 or greater. ```bash yarn add @arbitrum/orbit-sdk viem@^1.20.0 From 6d8f9e0368b5761066b0ee0fb528c87785c32ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Wed, 7 Aug 2024 19:05:47 +0200 Subject: [PATCH 09/54] chore: bump version --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index e38f750b..890db794 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.17.1", + "version": "0.17.2", "main": "./dist/index.js", "files": [ "./dist" From 4e12681e2477d6a32318e03ebd49cee8dc4b3532 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Thu, 8 Aug 2024 16:40:11 +0200 Subject: [PATCH 10/54] feat: handle generating abi from proxy (#159) --- patches/@wagmi+cli+1.5.2.patch | 32 +- src/contracts.ts | 158 +--------- src/generated.ts | 386 ++++++++++++++++++++++- src/utils/getImplementation.ts | 22 ++ src/utils/getImplementation.unit.test.ts | 26 ++ wagmi.config.ts | 38 ++- 6 files changed, 487 insertions(+), 175 deletions(-) create mode 100644 src/utils/getImplementation.ts create mode 100644 src/utils/getImplementation.unit.test.ts diff --git a/patches/@wagmi+cli+1.5.2.patch b/patches/@wagmi+cli+1.5.2.patch index 4af5be65..85f7d99b 100644 --- a/patches/@wagmi+cli+1.5.2.patch +++ b/patches/@wagmi+cli+1.5.2.patch @@ -19,9 +19,24 @@ index 04a78d1..1574961 100644 97: string; 128: string; diff --git a/node_modules/@wagmi/cli/dist/plugins/index.js b/node_modules/@wagmi/cli/dist/plugins/index.js -index 8e23da2..4cc878a 100644 +index 8e23da2..7fa021f 100644 --- a/node_modules/@wagmi/cli/dist/plugins/index.js +++ b/node_modules/@wagmi/cli/dist/plugins/index.js +@@ -386,12 +386,12 @@ function blockExplorer({ + throw new Error(parsed.data.result); + return parsed.data.result; + }, +- request({ address }) { ++ request({ address, implementation }) { + if (!address) + throw new Error("address is required"); + return { + url: `${baseUrl}?module=contract&action=getabi&address=${getAddress({ +- address ++ address, implementation + })}${apiKey ? `&apikey=${apiKey}` : ""}` + }; + } @@ -1381,12 +1381,15 @@ var apiUrls = { [1]: "https://api.etherscan.io/api", [5]: "https://api-goerli.etherscan.io/api", @@ -38,3 +53,18 @@ index 8e23da2..4cc878a 100644 [56]: "https://api.bscscan.com/api", [97]: "https://api-testnet.bscscan.com/api", [128]: "https://api.hecoinfo.com/api", +@@ -1413,12 +1416,12 @@ function etherscan({ + baseUrl: apiUrls[chainId], + cacheDuration, + contracts, +- getAddress({ address }) { ++ getAddress({ address, implementation = {} }) { + if (!address) + throw new Error("address is required"); + if (typeof address === "string") + return address; +- const contractAddress = address[chainId]; ++ const contractAddress = implementation[chainId] ?? address[chainId]; + if (!contractAddress) + throw new Error( + `No address found for chainId "${chainId}". Make sure chainId "${chainId}" is set as an address.` diff --git a/src/contracts.ts b/src/contracts.ts index 79f9217a..a2e695dd 100644 --- a/src/contracts.ts +++ b/src/contracts.ts @@ -36,6 +36,7 @@ export const arbAggregator = { } as const; export const rollupCreator = rollupCreatorConfig; +export const tokenBridgeCreator = tokenBridgeCreatorConfig; export const upgradeExecutor = { abi: parseAbi([ @@ -47,163 +48,6 @@ export const upgradeExecutor = { ]), }; -const tokenBridgeCreatorABI = [ - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'inbox', type: 'address' }, - { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'router', type: 'address' }, - { internalType: 'address', name: 'standardGateway', type: 'address' }, - { internalType: 'address', name: 'customGateway', type: 'address' }, - { internalType: 'address', name: 'wethGateway', type: 'address' }, - { internalType: 'address', name: 'weth', type: 'address' }, - ], - indexed: false, - internalType: 'struct L1DeploymentAddresses', - name: 'l1Deployment', - type: 'tuple', - }, - { - components: [ - { internalType: 'address', name: 'router', type: 'address' }, - { internalType: 'address', name: 'standardGateway', type: 'address' }, - { internalType: 'address', name: 'customGateway', type: 'address' }, - { internalType: 'address', name: 'wethGateway', type: 'address' }, - { internalType: 'address', name: 'weth', type: 'address' }, - { internalType: 'address', name: 'proxyAdmin', type: 'address' }, - { internalType: 'address', name: 'beaconProxyFactory', type: 'address' }, - { internalType: 'address', name: 'upgradeExecutor', type: 'address' }, - { internalType: 'address', name: 'multicall', type: 'address' }, - ], - indexed: false, - internalType: 'struct L2DeploymentAddresses', - name: 'l2Deployment', - type: 'tuple', - }, - { indexed: false, internalType: 'address', name: 'proxyAdmin', type: 'address' }, - { indexed: false, internalType: 'address', name: 'upgradeExecutor', type: 'address' }, - ], - name: 'OrbitTokenBridgeCreated', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'inbox', type: 'address' }, - { - components: [ - { internalType: 'address', name: 'router', type: 'address' }, - { internalType: 'address', name: 'standardGateway', type: 'address' }, - { internalType: 'address', name: 'customGateway', type: 'address' }, - { internalType: 'address', name: 'wethGateway', type: 'address' }, - { internalType: 'address', name: 'weth', type: 'address' }, - ], - indexed: false, - internalType: 'struct L1DeploymentAddresses', - name: 'l1', - type: 'tuple', - }, - { - components: [ - { internalType: 'address', name: 'router', type: 'address' }, - { internalType: 'address', name: 'standardGateway', type: 'address' }, - { internalType: 'address', name: 'customGateway', type: 'address' }, - { internalType: 'address', name: 'wethGateway', type: 'address' }, - { internalType: 'address', name: 'weth', type: 'address' }, - { internalType: 'address', name: 'proxyAdmin', type: 'address' }, - { internalType: 'address', name: 'beaconProxyFactory', type: 'address' }, - { internalType: 'address', name: 'upgradeExecutor', type: 'address' }, - { internalType: 'address', name: 'multicall', type: 'address' }, - ], - indexed: false, - internalType: 'struct L2DeploymentAddresses', - name: 'l2', - type: 'tuple', - }, - ], - name: 'OrbitTokenBridgeDeploymentSet', - type: 'event', - }, - { - inputs: [], - name: 'canonicalL2FactoryAddress', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { internalType: 'address', name: 'inbox', type: 'address' }, - { internalType: 'address', name: 'rollupOwner', type: 'address' }, - { internalType: 'uint256', name: 'maxGasForContracts', type: 'uint256' }, - { internalType: 'uint256', name: 'gasPriceBid', type: 'uint256' }, - ], - name: 'createTokenBridge', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [], - name: 'gasLimitForL2FactoryDeployment', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'address', name: '', type: 'address' }], - name: 'inboxToL1Deployment', - outputs: [ - { internalType: 'address', name: 'router', type: 'address' }, - { internalType: 'address', name: 'standardGateway', type: 'address' }, - { internalType: 'address', name: 'customGateway', type: 'address' }, - { internalType: 'address', name: 'wethGateway', type: 'address' }, - { internalType: 'address', name: 'weth', type: 'address' }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'address', name: '', type: 'address' }], - name: 'inboxToL2Deployment', - outputs: [ - { internalType: 'address', name: 'router', type: 'address' }, - { internalType: 'address', name: 'standardGateway', type: 'address' }, - { internalType: 'address', name: 'customGateway', type: 'address' }, - { internalType: 'address', name: 'wethGateway', type: 'address' }, - { internalType: 'address', name: 'weth', type: 'address' }, - { internalType: 'address', name: 'proxyAdmin', type: 'address' }, - { internalType: 'address', name: 'beaconProxyFactory', type: 'address' }, - { internalType: 'address', name: 'upgradeExecutor', type: 'address' }, - { internalType: 'address', name: 'multicall', type: 'address' }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'l1Multicall', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'l1Weth', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function', - }, -] as const; - -export const tokenBridgeCreator = { - ...tokenBridgeCreatorConfig, - abi: tokenBridgeCreatorABI, -} as const; - export const sequencerInbox = { abi: sequencerInboxABI, }; diff --git a/src/generated.ts b/src/generated.ts index 95e9c6cf..dea6f0b5 100644 --- a/src/generated.ts +++ b/src/generated.ts @@ -984,38 +984,392 @@ export const rollupCreatorConfig = { * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570) */ export const tokenBridgeCreatorABI = [ + { stateMutability: 'nonpayable', type: 'constructor', inputs: [] }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_L2FactoryCannotBeChanged' }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_OnlyRollupOwner' }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_ProxyAdminNotFound' }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_RollupOwnershipMisconfig' }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_TemplatesNotSet' }, { - stateMutability: 'payable', - type: 'constructor', - inputs: [ - { name: '_logic', internalType: 'address', type: 'address' }, - { name: 'admin_', internalType: 'address', type: 'address' }, - { name: '_data', internalType: 'bytes', type: 'bytes' }, - ], + type: 'event', + anonymous: false, + inputs: [{ name: 'version', internalType: 'uint8', type: 'uint8', indexed: false }], + name: 'Initialized', }, { type: 'event', anonymous: false, inputs: [ - { name: 'previousAdmin', internalType: 'address', type: 'address', indexed: false }, - { name: 'newAdmin', internalType: 'address', type: 'address', indexed: false }, + { name: 'inbox', internalType: 'address', type: 'address', indexed: true }, + { name: 'owner', internalType: 'address', type: 'address', indexed: true }, + { + name: 'l1Deployment', + internalType: 'struct L1DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + ], + indexed: false, + }, + { + name: 'l2Deployment', + internalType: 'struct L2DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + { name: 'proxyAdmin', internalType: 'address', type: 'address' }, + { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, + { name: 'multicall', internalType: 'address', type: 'address' }, + ], + indexed: false, + }, + { name: 'proxyAdmin', internalType: 'address', type: 'address', indexed: false }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address', indexed: false }, ], - name: 'AdminChanged', + name: 'OrbitTokenBridgeCreated', }, { type: 'event', anonymous: false, - inputs: [{ name: 'beacon', internalType: 'address', type: 'address', indexed: true }], - name: 'BeaconUpgraded', + inputs: [ + { name: 'inbox', internalType: 'address', type: 'address', indexed: true }, + { + name: 'l1', + internalType: 'struct L1DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + ], + indexed: false, + }, + { + name: 'l2', + internalType: 'struct L2DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + { name: 'proxyAdmin', internalType: 'address', type: 'address' }, + { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, + { name: 'multicall', internalType: 'address', type: 'address' }, + ], + indexed: false, + }, + ], + name: 'OrbitTokenBridgeDeploymentSet', }, + { type: 'event', anonymous: false, inputs: [], name: 'OrbitTokenBridgeTemplatesUpdated' }, { type: 'event', anonymous: false, - inputs: [{ name: 'implementation', internalType: 'address', type: 'address', indexed: true }], - name: 'Upgraded', + inputs: [ + { name: 'previousOwner', internalType: 'address', type: 'address', indexed: true }, + { name: 'newOwner', internalType: 'address', type: 'address', indexed: true }, + ], + name: 'OwnershipTransferred', + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'canonicalL2FactoryAddress', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'payable', + type: 'function', + inputs: [ + { name: 'inbox', internalType: 'address', type: 'address' }, + { name: 'rollupOwner', internalType: 'address', type: 'address' }, + { name: 'maxGasForContracts', internalType: 'uint256', type: 'uint256' }, + { name: 'gasPriceBid', internalType: 'uint256', type: 'uint256' }, + ], + name: 'createTokenBridge', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'gasLimitForL2FactoryDeployment', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'inbox', internalType: 'address', type: 'address' }], + name: 'getRouter', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: '', internalType: 'address', type: 'address' }], + name: 'inboxToL1Deployment', + outputs: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: '', internalType: 'address', type: 'address' }], + name: 'inboxToL2Deployment', + outputs: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + { name: 'proxyAdmin', internalType: 'address', type: 'address' }, + { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, + { name: 'multicall', internalType: 'address', type: 'address' }, + ], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { + name: '_retryableSender', + internalType: 'contract L1TokenBridgeRetryableSender', + type: 'address', + }, + ], + name: 'initialize', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l1Multicall', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l1Templates', + outputs: [ + { name: 'routerTemplate', internalType: 'contract L1GatewayRouter', type: 'address' }, + { name: 'standardGatewayTemplate', internalType: 'contract L1ERC20Gateway', type: 'address' }, + { name: 'customGatewayTemplate', internalType: 'contract L1CustomGateway', type: 'address' }, + { name: 'wethGatewayTemplate', internalType: 'contract L1WethGateway', type: 'address' }, + { + name: 'feeTokenBasedRouterTemplate', + internalType: 'contract L1OrbitGatewayRouter', + type: 'address', + }, + { + name: 'feeTokenBasedStandardGatewayTemplate', + internalType: 'contract L1OrbitERC20Gateway', + type: 'address', + }, + { + name: 'feeTokenBasedCustomGatewayTemplate', + internalType: 'contract L1OrbitCustomGateway', + type: 'address', + }, + { name: 'upgradeExecutor', internalType: 'contract IUpgradeExecutor', type: 'address' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l1Weth', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2CustomGatewayTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2MulticallTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2RouterTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2StandardGatewayTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2TokenBridgeFactoryTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2WethGatewayTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2WethTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'owner', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [], + name: 'renounceOwnership', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'retryableSender', + outputs: [{ name: '', internalType: 'contract L1TokenBridgeRetryableSender', type: 'address' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'inbox', internalType: 'address', type: 'address' }, + { + name: 'l1Deployment', + internalType: 'struct L1DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + ], + }, + { + name: 'l2Deployment', + internalType: 'struct L2DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + { name: 'proxyAdmin', internalType: 'address', type: 'address' }, + { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, + { name: 'multicall', internalType: 'address', type: 'address' }, + ], + }, + ], + name: 'setDeployment', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { + name: '_l1Templates', + internalType: 'struct L1AtomicTokenBridgeCreator.L1Templates', + type: 'tuple', + components: [ + { name: 'routerTemplate', internalType: 'contract L1GatewayRouter', type: 'address' }, + { + name: 'standardGatewayTemplate', + internalType: 'contract L1ERC20Gateway', + type: 'address', + }, + { + name: 'customGatewayTemplate', + internalType: 'contract L1CustomGateway', + type: 'address', + }, + { name: 'wethGatewayTemplate', internalType: 'contract L1WethGateway', type: 'address' }, + { + name: 'feeTokenBasedRouterTemplate', + internalType: 'contract L1OrbitGatewayRouter', + type: 'address', + }, + { + name: 'feeTokenBasedStandardGatewayTemplate', + internalType: 'contract L1OrbitERC20Gateway', + type: 'address', + }, + { + name: 'feeTokenBasedCustomGatewayTemplate', + internalType: 'contract L1OrbitCustomGateway', + type: 'address', + }, + { name: 'upgradeExecutor', internalType: 'contract IUpgradeExecutor', type: 'address' }, + ], + }, + { name: '_l2TokenBridgeFactoryTemplate', internalType: 'address', type: 'address' }, + { name: '_l2RouterTemplate', internalType: 'address', type: 'address' }, + { name: '_l2StandardGatewayTemplate', internalType: 'address', type: 'address' }, + { name: '_l2CustomGatewayTemplate', internalType: 'address', type: 'address' }, + { name: '_l2WethGatewayTemplate', internalType: 'address', type: 'address' }, + { name: '_l2WethTemplate', internalType: 'address', type: 'address' }, + { name: '_l2MulticallTemplate', internalType: 'address', type: 'address' }, + { name: '_l1Weth', internalType: 'address', type: 'address' }, + { name: '_l1Multicall', internalType: 'address', type: 'address' }, + { name: '_gasLimitForL2FactoryDeployment', internalType: 'uint256', type: 'uint256' }, + ], + name: 'setTemplates', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], + name: 'transferOwnership', + outputs: [], }, - { stateMutability: 'payable', type: 'fallback' }, - { stateMutability: 'payable', type: 'receive' }, ] as const; /** diff --git a/src/utils/getImplementation.ts b/src/utils/getImplementation.ts new file mode 100644 index 00000000..ed9b6460 --- /dev/null +++ b/src/utils/getImplementation.ts @@ -0,0 +1,22 @@ +import { Chain, Transport, PublicClient, Address, zeroAddress } from 'viem'; + +export async function getImplementation({ + client, + address, +}: { + client: PublicClient; + address: Address; +}): Promise
{ + const value = await client.getStorageAt({ + address, + // https://eips.ethereum.org/EIPS/eip-1967#logic-contract-address + slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc', + }); + + if (typeof value === 'undefined') { + return zeroAddress; + } + + // strip zeros + return `0x${value.slice(26)}`; +} diff --git a/src/utils/getImplementation.unit.test.ts b/src/utils/getImplementation.unit.test.ts new file mode 100644 index 00000000..437e43cc --- /dev/null +++ b/src/utils/getImplementation.unit.test.ts @@ -0,0 +1,26 @@ +import { it, expect } from 'vitest'; +import { createPublicClient, http, zeroAddress } from 'viem'; +import { arbitrumSepolia } from 'viem/chains'; + +import { getImplementation } from './getImplementation'; + +const arbitrumSepoliaPublicClient = createPublicClient({ + chain: arbitrumSepolia, + transport: http(), +}); + +it('fetches no implementation address for RollupCreator v1.1.0 on Arbitrum Sepolia', async () => { + const implementation = await getImplementation({ + client: arbitrumSepoliaPublicClient, + address: '0x06E341073b2749e0Bb9912461351f716DeCDa9b0', + }); + expect(implementation).toEqual(zeroAddress); +}); + +it('fetches implementation address for TokenBridgeCreator v1.2.0 on Arbitrum Sepolia', async () => { + const implementation = await getImplementation({ + client: arbitrumSepoliaPublicClient, + address: '0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E', + }); + expect(implementation).toEqual('0x4d80b4fd42abd6934df7d9ba536e5cfe2fb7e730'); +}); diff --git a/wagmi.config.ts b/wagmi.config.ts index cf910910..f0291f0e 100644 --- a/wagmi.config.ts +++ b/wagmi.config.ts @@ -1,5 +1,5 @@ import { erc, etherscan } from '@wagmi/cli/plugins'; -import { hashMessage } from 'viem'; +import { hashMessage, createPublicClient, http, zeroAddress } from 'viem'; import dotenv from 'dotenv'; import { ParentChainId } from './src'; @@ -15,7 +15,9 @@ import { nitroTestnodeL1, nitroTestnodeL2, nitroTestnodeL3, + chains, } from './src/chains'; +import { getImplementation } from './src/utils/getImplementation'; dotenv.config(); @@ -82,6 +84,18 @@ const blockExplorerApiUrls: Record chain.id === chainId), + transport: http(), + }); + + const implementation = await getImplementation({ client, address }); + + if (implementation !== zeroAddress) { + // replace proxy address with implementation address, so proper abis are compared + address = implementation; + } + const responseJson = await ( await fetch( `${url}?module=contract&action=getabi&format=raw&address=${address}&apikey=${apiKey}`, @@ -99,6 +113,7 @@ type ContractConfig = { name: string; version?: string; address: Record | `0x${string}`; + implementation?: Record; }; const contracts: ContractConfig[] = [ @@ -205,11 +220,32 @@ export async function assertContractAbisMatch(contract: ContractConfig) { console.log(`- ${contract.name} ✔\n`); } +async function updateContractWithImplementationIfProxy(contract: ContractConfig) { + // precompiles, do nothing + if (typeof contract.address === 'string') { + return; + } + + const implementation = await getImplementation({ + client: createPublicClient({ chain: arbitrumSepolia, transport: http() }), + address: contract.address[arbitrumSepolia.id], + }); + + // not a proxy, do nothing + if (implementation === zeroAddress) { + return; + } + + // only add arbitrum sepolia implementation as that's the one we're generating from + contract.implementation = { [arbitrumSepolia.id]: implementation }; +} + export default async function () { console.log(`Checking if contracts match by comparing hashed JSON ABIs.\n`); for (const contract of contracts) { await assertContractAbisMatch(contract); + await updateContractWithImplementationIfProxy(contract); await sleep(); // sleep to avoid rate limiting } From 19b5a52b95dfa152c883a46a600c97b04a84de1d Mon Sep 17 00:00:00 2001 From: spsjvc Date: Thu, 8 Aug 2024 19:33:56 +0200 Subject: [PATCH 11/54] feat: organize contracts by file and version (#160) --- src/abi/index.ts | 5 - src/arbAggregatorPrepareTransactionRequest.ts | 10 +- src/arbAggregatorReadContract.ts | 8 +- src/arbGasInfoReadContract.ts | 8 +- src/arbOwnerPrepareTransactionRequest.ts | 10 +- src/arbOwnerReadContract.ts | 8 +- src/contracts.ts | 57 - src/contracts/ArbAggregator.ts | 87 + src/contracts/ArbGasInfo.ts | 213 +++ src/contracts/ArbOwner.ts | 214 +++ src/contracts/ArbOwnerPublic.ts | 80 + src/contracts/ERC20.ts | 120 ++ .../GnosisSafeL2.ts} | 2 +- .../Rollup.ts} | 2 +- src/contracts/RollupCreator/index.ts | 2 + src/contracts/RollupCreator/v1.1.0.ts | 242 +++ .../SequencerInbox.ts} | 0 src/contracts/TokenBridgeCreator/index.ts | 2 + src/contracts/TokenBridgeCreator/v1.2.0.ts | 443 ++++++ src/contracts/UpgradeExecutor.ts | 9 + src/createRollupPrepareTransaction.ts | 4 +- src/createRollupPrepareTransactionReceipt.ts | 6 +- src/createRollupPrepareTransactionRequest.ts | 4 +- ...llupPrepareTransactionRequest.unit.test.ts | 4 +- src/createTokenBridge.integration.test.ts | 6 +- ...ateTokenBridgeFetchTokenBridgeContracts.ts | 8 +- ...ateTokenBridgePrepareTransactionReceipt.ts | 6 +- ...ateTokenBridgePrepareTransactionRequest.ts | 4 +- .../sequencerInboxActions.integration.test.ts | 2 +- src/generated.ts | 1413 ----------------- src/getBatchPosters.ts | 14 +- src/getBatchPosters.unit.test.ts | 7 +- src/getKeysets.ts | 3 +- src/getValidators.ts | 21 +- src/getValidators.unit.test.ts | 11 +- src/isAnyTrust.ts | 4 +- src/package.json | 7 - ...llupAdminLogicPrepareTransactionRequest.ts | 7 +- src/rollupAdminLogicReadContract.ts | 6 +- ...sequencerInboxPrepareTransactionRequest.ts | 6 +- src/sequencerInboxReadContract.ts | 4 +- src/setValidKeyset.ts | 4 +- src/types/createRollupTypes.ts | 4 +- src/upgradeExecutorEncodeFunctionData.ts | 7 +- ...torPrepareAddExecutorTransactionRequest.ts | 7 +- ...PrepareRemoveExecutorTransactionRequest.ts | 7 +- src/utils/erc20.ts | 10 +- src/utils/getters.ts | 11 +- wagmi.config.ts | 44 +- 49 files changed, 1558 insertions(+), 1605 deletions(-) delete mode 100644 src/abi/index.ts delete mode 100644 src/contracts.ts create mode 100644 src/contracts/ArbAggregator.ts create mode 100644 src/contracts/ArbGasInfo.ts create mode 100644 src/contracts/ArbOwner.ts create mode 100644 src/contracts/ArbOwnerPublic.ts create mode 100644 src/contracts/ERC20.ts rename src/{abi/safeL2ABI.ts => contracts/GnosisSafeL2.ts} (99%) rename src/{abi/rollupAdminLogicABI.ts => contracts/Rollup.ts} (99%) create mode 100644 src/contracts/RollupCreator/index.ts create mode 100644 src/contracts/RollupCreator/v1.1.0.ts rename src/{abi/sequencerInboxABI.ts => contracts/SequencerInbox.ts} (100%) create mode 100644 src/contracts/TokenBridgeCreator/index.ts create mode 100644 src/contracts/TokenBridgeCreator/v1.2.0.ts create mode 100644 src/contracts/UpgradeExecutor.ts delete mode 100644 src/generated.ts diff --git a/src/abi/index.ts b/src/abi/index.ts deleted file mode 100644 index 4c41e4ce..00000000 --- a/src/abi/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { rollupAdminLogicABI } from './rollupAdminLogicABI'; -import { sequencerInboxABI } from './sequencerInboxABI'; -import { safeL2ABI } from './safeL2ABI'; - -export { rollupAdminLogicABI, sequencerInboxABI, safeL2ABI }; diff --git a/src/arbAggregatorPrepareTransactionRequest.ts b/src/arbAggregatorPrepareTransactionRequest.ts index e7e42442..dfdc8c25 100644 --- a/src/arbAggregatorPrepareTransactionRequest.ts +++ b/src/arbAggregatorPrepareTransactionRequest.ts @@ -7,11 +7,11 @@ import { Transport, } from 'viem'; -import { arbAggregator } from './contracts'; +import { arbAggregatorABI, arbAggregatorAddress } from './contracts/ArbAggregator'; import { upgradeExecutorEncodeFunctionData } from './upgradeExecutorEncodeFunctionData'; import { GetFunctionName } from './types/utils'; -type ArbAggregatorAbi = typeof arbAggregator.abi; +type ArbAggregatorAbi = typeof arbAggregatorABI; export type ArbAggregatorPrepareTransactionRequestFunctionName = GetFunctionName; export type ArbAggregatorEncodeFunctionDataParameters< TFunctionName extends ArbAggregatorPrepareTransactionRequestFunctionName, @@ -40,7 +40,7 @@ function arbAggregatorPrepareFunctionData< if (!upgradeExecutor) { return { - to: arbAggregator.address, + to: arbAggregatorAddress, data: arbAggregatorEncodeFunctionData( params as ArbAggregatorEncodeFunctionDataParameters, ), @@ -53,7 +53,7 @@ function arbAggregatorPrepareFunctionData< data: upgradeExecutorEncodeFunctionData({ functionName: 'executeCall', args: [ - arbAggregator.address, // target + arbAggregatorAddress, // target arbAggregatorEncodeFunctionData( params as ArbAggregatorEncodeFunctionDataParameters, ), // targetCallData @@ -82,7 +82,7 @@ export async function arbAggregatorPrepareTransactionRequest< // params is extending ArbAggregatorPrepareFunctionDataParameters, it's safe to cast const { to, data, value } = arbAggregatorPrepareFunctionData({ ...params, - abi: arbAggregator.abi, + abi: arbAggregatorABI, } as unknown as ArbAggregatorPrepareFunctionDataParameters); // @ts-ignore (todo: fix viem type issue) diff --git a/src/arbAggregatorReadContract.ts b/src/arbAggregatorReadContract.ts index 9082cdbc..6bec0124 100644 --- a/src/arbAggregatorReadContract.ts +++ b/src/arbAggregatorReadContract.ts @@ -1,9 +1,9 @@ import { Chain, GetFunctionArgs, PublicClient, ReadContractReturnType, Transport } from 'viem'; -import { arbAggregator } from './contracts'; +import { arbAggregatorABI, arbAggregatorAddress } from './contracts/ArbAggregator'; import { GetFunctionName } from './types/utils'; -export type ArbAggregatorAbi = typeof arbAggregator.abi; +export type ArbAggregatorAbi = typeof arbAggregatorABI; export type ArbAggregatorFunctionName = GetFunctionName; export type ArbAggregatorReadContractParameters = { @@ -22,8 +22,8 @@ export function arbAggregatorReadContract< ): Promise> { // @ts-ignore (todo: fix viem type issue) return client.readContract({ - address: arbAggregator.address, - abi: arbAggregator.abi, + address: arbAggregatorAddress, + abi: arbAggregatorABI, functionName: params.functionName, args: params.args, }); diff --git a/src/arbGasInfoReadContract.ts b/src/arbGasInfoReadContract.ts index 13db05d1..eeb88f34 100644 --- a/src/arbGasInfoReadContract.ts +++ b/src/arbGasInfoReadContract.ts @@ -1,9 +1,9 @@ import { Chain, GetFunctionArgs, PublicClient, ReadContractReturnType, Transport } from 'viem'; -import { arbGasInfo } from './contracts'; +import { arbGasInfoABI, arbGasInfoAddress } from './contracts/ArbGasInfo'; import { GetFunctionName } from './types/utils'; -export type ArbGasInfoAbi = typeof arbGasInfo.abi; +export type ArbGasInfoAbi = typeof arbGasInfoABI; export type ArbGasInfoFunctionName = GetFunctionName; export type ArbGasInfoReadContractParameters = { @@ -22,8 +22,8 @@ export function arbGasInfoReadContract< ): Promise> { // @ts-ignore (todo: fix viem type issue) return client.readContract({ - address: arbGasInfo.address, - abi: arbGasInfo.abi, + address: arbGasInfoAddress, + abi: arbGasInfoABI, functionName: params.functionName, args: params.args, }); diff --git a/src/arbOwnerPrepareTransactionRequest.ts b/src/arbOwnerPrepareTransactionRequest.ts index 67e1bb97..11174665 100644 --- a/src/arbOwnerPrepareTransactionRequest.ts +++ b/src/arbOwnerPrepareTransactionRequest.ts @@ -7,11 +7,11 @@ import { Transport, } from 'viem'; -import { arbOwner } from './contracts'; +import { arbOwnerABI, arbOwnerAddress } from './contracts/ArbOwner'; import { upgradeExecutorEncodeFunctionData } from './upgradeExecutorEncodeFunctionData'; import { GetFunctionName } from './types/utils'; -type ArbOwnerAbi = typeof arbOwner.abi; +type ArbOwnerAbi = typeof arbOwnerABI; export type ArbOwnerPrepareTransactionRequestFunctionName = GetFunctionName; export type ArbOwnerEncodeFunctionDataParameters< TFunctionName extends ArbOwnerPrepareTransactionRequestFunctionName, @@ -40,7 +40,7 @@ function arbOwnerPrepareFunctionData< if (!upgradeExecutor) { return { - to: arbOwner.address, + to: arbOwnerAddress, data: arbOwnerEncodeFunctionData( params as ArbOwnerEncodeFunctionDataParameters, ), @@ -53,7 +53,7 @@ function arbOwnerPrepareFunctionData< data: upgradeExecutorEncodeFunctionData({ functionName: 'executeCall', args: [ - arbOwner.address, // target + arbOwnerAddress, // target arbOwnerEncodeFunctionData(params as ArbOwnerEncodeFunctionDataParameters), // targetCallData ], }), @@ -81,7 +81,7 @@ export async function arbOwnerPrepareTransactionRequest< // params is extending ArbOwnerPrepareFunctionDataParameters, it's safe to cast const { to, data, value } = arbOwnerPrepareFunctionData({ ...params, - abi: arbOwner.abi, + abi: arbOwnerABI, } as unknown as ArbOwnerPrepareFunctionDataParameters); // @ts-ignore (todo: fix viem type issue) diff --git a/src/arbOwnerReadContract.ts b/src/arbOwnerReadContract.ts index 62a5ff15..3d805649 100644 --- a/src/arbOwnerReadContract.ts +++ b/src/arbOwnerReadContract.ts @@ -1,9 +1,9 @@ import { Chain, GetFunctionArgs, PublicClient, ReadContractReturnType, Transport } from 'viem'; -import { arbOwnerPublic } from './contracts'; +import { arbOwnerPublicABI, arbOwnerPublicAddress } from './contracts/ArbOwnerPublic'; import { GetFunctionName } from './types/utils'; -export type ArbOwnerPublicAbi = typeof arbOwnerPublic.abi; +export type ArbOwnerPublicAbi = typeof arbOwnerPublicABI; export type ArbOwnerPublicFunctionName = GetFunctionName; export type ArbOwnerReadContractParameters = { @@ -22,8 +22,8 @@ export function arbOwnerReadContract< ): Promise> { // @ts-ignore (todo: fix viem type issue) return client.readContract({ - address: arbOwnerPublic.address, - abi: arbOwnerPublic.abi, + address: arbOwnerPublicAddress, + abi: arbOwnerPublicABI, functionName: params.functionName, args: params.args, }); diff --git a/src/contracts.ts b/src/contracts.ts deleted file mode 100644 index a2e695dd..00000000 --- a/src/contracts.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { parseAbi } from 'viem'; - -import { - erc20ABI, - arbOwnerConfig, - arbOwnerPublicConfig, - rollupCreatorConfig, - tokenBridgeCreatorConfig, - arbGasInfoConfig, - arbAggregatorConfig, -} from './generated'; -import { sequencerInboxABI, rollupAdminLogicABI } from './abi'; - -export const erc20 = { - abi: erc20ABI, -}; - -export const arbOwner = { - ...arbOwnerConfig, - address: Object.values(arbOwnerConfig.address)[0], -} as const; - -export const arbGasInfo = { - ...arbGasInfoConfig, - address: Object.values(arbGasInfoConfig.address)[0], -} as const; - -export const arbOwnerPublic = { - ...arbOwnerPublicConfig, - address: Object.values(arbOwnerPublicConfig.address)[0], -} as const; - -export const arbAggregator = { - ...arbAggregatorConfig, - address: Object.values(arbAggregatorConfig.address)[0], -} as const; - -export const rollupCreator = rollupCreatorConfig; -export const tokenBridgeCreator = tokenBridgeCreatorConfig; - -export const upgradeExecutor = { - abi: parseAbi([ - 'function execute(address upgrade, bytes upgradeCallData)', - 'function executeCall(address target, bytes targetCallData)', - 'function hasRole(bytes32 role, address account) public view returns (bool)', - 'function grantRole(bytes32 role, address account)', - 'function revokeRole(bytes32 role, address account)', - ]), -}; - -export const sequencerInbox = { - abi: sequencerInboxABI, -}; - -export const rollupAdminLogic = { - abi: rollupAdminLogicABI, -}; diff --git a/src/contracts/ArbAggregator.ts b/src/contracts/ArbAggregator.ts new file mode 100644 index 00000000..07c43b06 --- /dev/null +++ b/src/contracts/ArbAggregator.ts @@ -0,0 +1,87 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ArbAggregator +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006d) + */ +export const arbAggregatorABI = [ + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'newBatchPoster', internalType: 'address', type: 'address' }], + name: 'addBatchPoster', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getBatchPosters', + outputs: [{ name: '', internalType: 'address[]', type: 'address[]' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getDefaultAggregator', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'batchPoster', internalType: 'address', type: 'address' }], + name: 'getFeeCollector', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'addr', internalType: 'address', type: 'address' }], + name: 'getPreferredAggregator', + outputs: [ + { name: '', internalType: 'address', type: 'address' }, + { name: '', internalType: 'bool', type: 'bool' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'aggregator', internalType: 'address', type: 'address' }], + name: 'getTxBaseFee', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'batchPoster', internalType: 'address', type: 'address' }, + { name: 'newFeeCollector', internalType: 'address', type: 'address' }, + ], + name: 'setFeeCollector', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'aggregator', internalType: 'address', type: 'address' }, + { name: 'feeInL1Gas', internalType: 'uint256', type: 'uint256' }, + ], + name: 'setTxBaseFee', + outputs: [], + }, +] as const; + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006d) + */ +export const arbAggregatorAddress = '0x000000000000000000000000000000000000006D'; + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006d) + */ +export const arbAggregatorConfig = { + address: arbAggregatorAddress, + abi: arbAggregatorABI, +} as const; diff --git a/src/contracts/ArbGasInfo.ts b/src/contracts/ArbGasInfo.ts new file mode 100644 index 00000000..840d64a5 --- /dev/null +++ b/src/contracts/ArbGasInfo.ts @@ -0,0 +1,213 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ArbGasInfo +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006c) + */ +export const arbGasInfoABI = [ + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getAmortizedCostCapBips', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getCurrentTxL1GasFees', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getGasAccountingParams', + outputs: [ + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getGasBacklog', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getGasBacklogTolerance', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1BaseFeeEstimate', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1BaseFeeEstimateInertia', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1FeesAvailable', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1GasPriceEstimate', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1PricingEquilibrationUnits', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1PricingFundsDueForRewards', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1PricingSurplus', + outputs: [{ name: '', internalType: 'int256', type: 'int256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1PricingUnitsSinceUpdate', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1RewardRate', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getL1RewardRecipient', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getLastL1PricingSurplus', + outputs: [{ name: '', internalType: 'int256', type: 'int256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getLastL1PricingUpdateTime', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getMinimumGasPrice', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getPerBatchGasCharge', + outputs: [{ name: '', internalType: 'int64', type: 'int64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getPricesInArbGas', + outputs: [ + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'aggregator', internalType: 'address', type: 'address' }], + name: 'getPricesInArbGasWithAggregator', + outputs: [ + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getPricesInWei', + outputs: [ + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'aggregator', internalType: 'address', type: 'address' }], + name: 'getPricesInWeiWithAggregator', + outputs: [ + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + { name: '', internalType: 'uint256', type: 'uint256' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getPricingInertia', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, +] as const; + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006c) + */ +export const arbGasInfoAddress = '0x000000000000000000000000000000000000006C'; + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006c) + */ +export const arbGasInfoConfig = { address: arbGasInfoAddress, abi: arbGasInfoABI } as const; diff --git a/src/contracts/ArbOwner.ts b/src/contracts/ArbOwner.ts new file mode 100644 index 00000000..8b63a2c1 --- /dev/null +++ b/src/contracts/ArbOwner.ts @@ -0,0 +1,214 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ArbOwner +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x0000000000000000000000000000000000000070) + */ +export const arbOwnerABI = [ + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'method', internalType: 'bytes4', type: 'bytes4', indexed: true }, + { name: 'owner', internalType: 'address', type: 'address', indexed: true }, + { name: 'data', internalType: 'bytes', type: 'bytes', indexed: false }, + ], + name: 'OwnerActs', + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], + name: 'addChainOwner', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getAllChainOwners', + outputs: [{ name: '', internalType: 'address[]', type: 'address[]' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getInfraFeeAccount', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getNetworkFeeAccount', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'addr', internalType: 'address', type: 'address' }], + name: 'isChainOwner', + outputs: [{ name: '', internalType: 'bool', type: 'bool' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'maxWeiToRelease', internalType: 'uint256', type: 'uint256' }], + name: 'releaseL1PricerSurplusFunds', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'ownerToRemove', internalType: 'address', type: 'address' }], + name: 'removeChainOwner', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'newVersion', internalType: 'uint64', type: 'uint64' }, + { name: 'timestamp', internalType: 'uint64', type: 'uint64' }, + ], + name: 'scheduleArbOSUpgrade', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'cap', internalType: 'uint64', type: 'uint64' }], + name: 'setAmortizedCostCapBips', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'level', internalType: 'uint64', type: 'uint64' }], + name: 'setBrotliCompressionLevel', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'chainConfig', internalType: 'string', type: 'string' }], + name: 'setChainConfig', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'newInfraFeeAccount', internalType: 'address', type: 'address' }], + name: 'setInfraFeeAccount', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'inertia', internalType: 'uint64', type: 'uint64' }], + name: 'setL1BaseFeeEstimateInertia', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'pricePerUnit', internalType: 'uint256', type: 'uint256' }], + name: 'setL1PricePerUnit', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'equilibrationUnits', internalType: 'uint256', type: 'uint256' }], + name: 'setL1PricingEquilibrationUnits', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'inertia', internalType: 'uint64', type: 'uint64' }], + name: 'setL1PricingInertia', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'weiPerUnit', internalType: 'uint64', type: 'uint64' }], + name: 'setL1PricingRewardRate', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'recipient', internalType: 'address', type: 'address' }], + name: 'setL1PricingRewardRecipient', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'priceInWei', internalType: 'uint256', type: 'uint256' }], + name: 'setL2BaseFee', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'sec', internalType: 'uint64', type: 'uint64' }], + name: 'setL2GasBacklogTolerance', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'sec', internalType: 'uint64', type: 'uint64' }], + name: 'setL2GasPricingInertia', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'limit', internalType: 'uint64', type: 'uint64' }], + name: 'setMaxTxGasLimit', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'priceInWei', internalType: 'uint256', type: 'uint256' }], + name: 'setMinimumL2BaseFee', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'newNetworkFeeAccount', internalType: 'address', type: 'address' }], + name: 'setNetworkFeeAccount', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'cost', internalType: 'int64', type: 'int64' }], + name: 'setPerBatchGasCharge', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'limit', internalType: 'uint64', type: 'uint64' }], + name: 'setSpeedLimit', + outputs: [], + }, +] as const; + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x0000000000000000000000000000000000000070) + */ +export const arbOwnerAddress = '0x0000000000000000000000000000000000000070'; + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x0000000000000000000000000000000000000070) + */ +export const arbOwnerConfig = { address: arbOwnerAddress, abi: arbOwnerABI } as const; diff --git a/src/contracts/ArbOwnerPublic.ts b/src/contracts/ArbOwnerPublic.ts new file mode 100644 index 00000000..31cd2513 --- /dev/null +++ b/src/contracts/ArbOwnerPublic.ts @@ -0,0 +1,80 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ArbOwnerPublic +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006b) + */ +export const arbOwnerPublicABI = [ + { + type: 'event', + anonymous: false, + inputs: [{ name: 'rectifiedOwner', internalType: 'address', type: 'address', indexed: false }], + name: 'ChainOwnerRectified', + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getAllChainOwners', + outputs: [{ name: '', internalType: 'address[]', type: 'address[]' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getBrotliCompressionLevel', + outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getInfraFeeAccount', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getNetworkFeeAccount', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'getScheduledUpgrade', + outputs: [ + { name: 'arbosVersion', internalType: 'uint64', type: 'uint64' }, + { name: 'scheduledForTimestamp', internalType: 'uint64', type: 'uint64' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'addr', internalType: 'address', type: 'address' }], + name: 'isChainOwner', + outputs: [{ name: '', internalType: 'bool', type: 'bool' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'ownerToRectify', internalType: 'address', type: 'address' }], + name: 'rectifyChainOwner', + outputs: [], + }, +] as const; + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006b) + */ +export const arbOwnerPublicAddress = '0x000000000000000000000000000000000000006b'; + +/** + * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006b) + */ +export const arbOwnerPublicConfig = { + address: arbOwnerPublicAddress, + abi: arbOwnerPublicABI, +} as const; diff --git a/src/contracts/ERC20.ts b/src/contracts/ERC20.ts new file mode 100644 index 00000000..5d64f364 --- /dev/null +++ b/src/contracts/ERC20.ts @@ -0,0 +1,120 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ERC20 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const erc20ABI = [ + { + type: 'event', + inputs: [ + { name: 'owner', type: 'address', indexed: true }, + { name: 'spender', type: 'address', indexed: true }, + { name: 'value', type: 'uint256', indexed: false }, + ], + name: 'Approval', + }, + { + type: 'event', + inputs: [ + { name: 'from', type: 'address', indexed: true }, + { name: 'to', type: 'address', indexed: true }, + { name: 'value', type: 'uint256', indexed: false }, + ], + name: 'Transfer', + }, + { + stateMutability: 'view', + type: 'function', + inputs: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + ], + name: 'allowance', + outputs: [{ type: 'uint256' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'spender', type: 'address' }, + { name: 'amount', type: 'uint256' }, + ], + name: 'approve', + outputs: [{ type: 'bool' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'account', type: 'address' }], + name: 'balanceOf', + outputs: [{ type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'decimals', + outputs: [{ type: 'uint8' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'name', + outputs: [{ type: 'string' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'symbol', + outputs: [{ type: 'string' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'totalSupply', + outputs: [{ type: 'uint256' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'recipient', type: 'address' }, + { name: 'amount', type: 'uint256' }, + ], + name: 'transfer', + outputs: [{ type: 'bool' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'sender', type: 'address' }, + { name: 'recipient', type: 'address' }, + { name: 'amount', type: 'uint256' }, + ], + name: 'transferFrom', + outputs: [{ type: 'bool' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'spender', type: 'address' }, + { name: 'addedValue', type: 'uint256' }, + ], + name: 'increaseAllowance', + outputs: [{ type: 'bool' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'spender', type: 'address' }, + { name: 'subtractedValue', type: 'uint256' }, + ], + name: 'decreaseAllowance', + outputs: [{ type: 'bool' }], + }, +] as const; diff --git a/src/abi/safeL2ABI.ts b/src/contracts/GnosisSafeL2.ts similarity index 99% rename from src/abi/safeL2ABI.ts rename to src/contracts/GnosisSafeL2.ts index 496621cd..7632d2b4 100644 --- a/src/abi/safeL2ABI.ts +++ b/src/contracts/GnosisSafeL2.ts @@ -1,5 +1,5 @@ // https://sepolia.arbiscan.io/address/0x3e5c63644e683549055b9be8653de26e0b4cd36e#code -export const safeL2ABI = [ +export const gnosisSafeL2ABI = [ { anonymous: false, inputs: [ diff --git a/src/abi/rollupAdminLogicABI.ts b/src/contracts/Rollup.ts similarity index 99% rename from src/abi/rollupAdminLogicABI.ts rename to src/contracts/Rollup.ts index 393b2e7b..0fe25e92 100644 --- a/src/abi/rollupAdminLogicABI.ts +++ b/src/contracts/Rollup.ts @@ -1,6 +1,6 @@ // from @arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory // needs to be copied into this codebase because it is not cast to const in arbitrum sdk -export const rollupAdminLogicABI = [ +export const rollupABI = [ { anonymous: false, inputs: [ diff --git a/src/contracts/RollupCreator/index.ts b/src/contracts/RollupCreator/index.ts new file mode 100644 index 00000000..3c275a4f --- /dev/null +++ b/src/contracts/RollupCreator/index.ts @@ -0,0 +1,2 @@ +// export the latest version +export * from './v1.1.0'; diff --git a/src/contracts/RollupCreator/v1.1.0.ts b/src/contracts/RollupCreator/v1.1.0.ts new file mode 100644 index 00000000..51b71531 --- /dev/null +++ b/src/contracts/RollupCreator/v1.1.0.ts @@ -0,0 +1,242 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// RollupCreator +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x90d68b056c411015eae3ec0b98ad94e2c91419f1) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x850F050C65B34966895AdA26a4D06923901916DB) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x1E0921818df948c338380e722C8aE91Bb285763C) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x06E341073b2749e0Bb9912461351f716DeCDa9b0) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfbd0b034e6305788007f6e0123cc5eae701a5751) + */ +export const rollupCreatorABI = [ + { stateMutability: 'nonpayable', type: 'constructor', inputs: [] }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'previousOwner', internalType: 'address', type: 'address', indexed: true }, + { name: 'newOwner', internalType: 'address', type: 'address', indexed: true }, + ], + name: 'OwnershipTransferred', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'rollupAddress', internalType: 'address', type: 'address', indexed: true }, + { name: 'nativeToken', internalType: 'address', type: 'address', indexed: true }, + { name: 'inboxAddress', internalType: 'address', type: 'address', indexed: false }, + { name: 'outbox', internalType: 'address', type: 'address', indexed: false }, + { name: 'rollupEventInbox', internalType: 'address', type: 'address', indexed: false }, + { name: 'challengeManager', internalType: 'address', type: 'address', indexed: false }, + { name: 'adminProxy', internalType: 'address', type: 'address', indexed: false }, + { name: 'sequencerInbox', internalType: 'address', type: 'address', indexed: false }, + { name: 'bridge', internalType: 'address', type: 'address', indexed: false }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address', indexed: false }, + { name: 'validatorUtils', internalType: 'address', type: 'address', indexed: false }, + { name: 'validatorWalletCreator', internalType: 'address', type: 'address', indexed: false }, + ], + name: 'RollupCreated', + }, + { type: 'event', anonymous: false, inputs: [], name: 'TemplatesUpdated' }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'bridgeCreator', + outputs: [{ name: '', internalType: 'contract BridgeCreator', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'challengeManagerTemplate', + outputs: [{ name: '', internalType: 'contract IChallengeManager', type: 'address' }], + }, + { + stateMutability: 'payable', + type: 'function', + inputs: [ + { + name: 'deployParams', + internalType: 'struct RollupCreator.RollupDeploymentParams', + type: 'tuple', + components: [ + { + name: 'config', + internalType: 'struct Config', + type: 'tuple', + components: [ + { name: 'confirmPeriodBlocks', internalType: 'uint64', type: 'uint64' }, + { name: 'extraChallengeTimeBlocks', internalType: 'uint64', type: 'uint64' }, + { name: 'stakeToken', internalType: 'address', type: 'address' }, + { name: 'baseStake', internalType: 'uint256', type: 'uint256' }, + { name: 'wasmModuleRoot', internalType: 'bytes32', type: 'bytes32' }, + { name: 'owner', internalType: 'address', type: 'address' }, + { name: 'loserStakeEscrow', internalType: 'address', type: 'address' }, + { name: 'chainId', internalType: 'uint256', type: 'uint256' }, + { name: 'chainConfig', internalType: 'string', type: 'string' }, + { name: 'genesisBlockNum', internalType: 'uint64', type: 'uint64' }, + { + name: 'sequencerInboxMaxTimeVariation', + internalType: 'struct ISequencerInbox.MaxTimeVariation', + type: 'tuple', + components: [ + { name: 'delayBlocks', internalType: 'uint256', type: 'uint256' }, + { name: 'futureBlocks', internalType: 'uint256', type: 'uint256' }, + { name: 'delaySeconds', internalType: 'uint256', type: 'uint256' }, + { name: 'futureSeconds', internalType: 'uint256', type: 'uint256' }, + ], + }, + ], + }, + { name: 'batchPoster', internalType: 'address', type: 'address' }, + { name: 'validators', internalType: 'address[]', type: 'address[]' }, + { name: 'maxDataSize', internalType: 'uint256', type: 'uint256' }, + { name: 'nativeToken', internalType: 'address', type: 'address' }, + { name: 'deployFactoriesToL2', internalType: 'bool', type: 'bool' }, + { name: 'maxFeePerGasForRetryables', internalType: 'uint256', type: 'uint256' }, + ], + }, + ], + name: 'createRollup', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2FactoriesDeployer', + outputs: [{ name: '', internalType: 'contract DeployHelper', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'osp', + outputs: [{ name: '', internalType: 'contract IOneStepProofEntry', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'owner', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [], + name: 'renounceOwnership', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'rollupAdminLogic', + outputs: [{ name: '', internalType: 'contract IRollupAdmin', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'rollupUserLogic', + outputs: [{ name: '', internalType: 'contract IRollupUser', type: 'address' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: '_bridgeCreator', internalType: 'contract BridgeCreator', type: 'address' }, + { name: '_osp', internalType: 'contract IOneStepProofEntry', type: 'address' }, + { + name: '_challengeManagerLogic', + internalType: 'contract IChallengeManager', + type: 'address', + }, + { name: '_rollupAdminLogic', internalType: 'contract IRollupAdmin', type: 'address' }, + { name: '_rollupUserLogic', internalType: 'contract IRollupUser', type: 'address' }, + { name: '_upgradeExecutorLogic', internalType: 'contract IUpgradeExecutor', type: 'address' }, + { name: '_validatorUtils', internalType: 'address', type: 'address' }, + { name: '_validatorWalletCreator', internalType: 'address', type: 'address' }, + { name: '_l2FactoriesDeployer', internalType: 'contract DeployHelper', type: 'address' }, + ], + name: 'setTemplates', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], + name: 'transferOwnership', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'upgradeExecutorLogic', + outputs: [{ name: '', internalType: 'contract IUpgradeExecutor', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'validatorUtils', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'validatorWalletCreator', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { stateMutability: 'payable', type: 'receive' }, +] as const; + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x90d68b056c411015eae3ec0b98ad94e2c91419f1) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x850F050C65B34966895AdA26a4D06923901916DB) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x1E0921818df948c338380e722C8aE91Bb285763C) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x06E341073b2749e0Bb9912461351f716DeCDa9b0) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfbd0b034e6305788007f6e0123cc5eae701a5751) + */ +export const rollupCreatorAddress = { + 1: '0x90D68B056c411015eaE3EC0b98AD94E2C91419F1', + 1337: '0x596eAbE0291D4cdAfAC7ef53D16C92Bf6922b5e0', + 8453: '0x850F050C65B34966895AdA26a4D06923901916DB', + 17000: '0xB512078282F462Ba104231ad856464Ceb0a7747e', + 42161: '0x9CAd81628aB7D8e239F1A5B497313341578c5F71', + 42170: '0x9CAd81628aB7D8e239F1A5B497313341578c5F71', + 84532: '0x1E0921818df948c338380e722C8aE91Bb285763C', + 412346: '0x3BaF9f08bAD68869eEdEa90F2Cc546Bd80F1A651', + 421614: '0x06E341073b2749e0Bb9912461351f716DeCDa9b0', + 11155111: '0xfBD0B034e6305788007f6e0123cc5EaE701a5751', +} as const; + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x90d68b056c411015eae3ec0b98ad94e2c91419f1) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x850F050C65B34966895AdA26a4D06923901916DB) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x1E0921818df948c338380e722C8aE91Bb285763C) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x06E341073b2749e0Bb9912461351f716DeCDa9b0) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfbd0b034e6305788007f6e0123cc5eae701a5751) + */ +export const rollupCreatorConfig = { + address: rollupCreatorAddress, + abi: rollupCreatorABI, +} as const; diff --git a/src/abi/sequencerInboxABI.ts b/src/contracts/SequencerInbox.ts similarity index 100% rename from src/abi/sequencerInboxABI.ts rename to src/contracts/SequencerInbox.ts diff --git a/src/contracts/TokenBridgeCreator/index.ts b/src/contracts/TokenBridgeCreator/index.ts new file mode 100644 index 00000000..1e0e8d08 --- /dev/null +++ b/src/contracts/TokenBridgeCreator/index.ts @@ -0,0 +1,2 @@ +// export the latest version +export * from './v1.2.0'; diff --git a/src/contracts/TokenBridgeCreator/v1.2.0.ts b/src/contracts/TokenBridgeCreator/v1.2.0.ts new file mode 100644 index 00000000..dbc6d575 --- /dev/null +++ b/src/contracts/TokenBridgeCreator/v1.2.0.ts @@ -0,0 +1,443 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// TokenBridgeCreator +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x4C240987d6fE4fa8C7a0004986e3db563150CA55) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x8B9D9490a68B1F16ac8A21DdAE5Fd7aB9d708c14) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570) + */ +export const tokenBridgeCreatorABI = [ + { stateMutability: 'nonpayable', type: 'constructor', inputs: [] }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_L2FactoryCannotBeChanged' }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_OnlyRollupOwner' }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_ProxyAdminNotFound' }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_RollupOwnershipMisconfig' }, + { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_TemplatesNotSet' }, + { + type: 'event', + anonymous: false, + inputs: [{ name: 'version', internalType: 'uint8', type: 'uint8', indexed: false }], + name: 'Initialized', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'inbox', internalType: 'address', type: 'address', indexed: true }, + { name: 'owner', internalType: 'address', type: 'address', indexed: true }, + { + name: 'l1Deployment', + internalType: 'struct L1DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + ], + indexed: false, + }, + { + name: 'l2Deployment', + internalType: 'struct L2DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + { name: 'proxyAdmin', internalType: 'address', type: 'address' }, + { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, + { name: 'multicall', internalType: 'address', type: 'address' }, + ], + indexed: false, + }, + { name: 'proxyAdmin', internalType: 'address', type: 'address', indexed: false }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address', indexed: false }, + ], + name: 'OrbitTokenBridgeCreated', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'inbox', internalType: 'address', type: 'address', indexed: true }, + { + name: 'l1', + internalType: 'struct L1DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + ], + indexed: false, + }, + { + name: 'l2', + internalType: 'struct L2DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + { name: 'proxyAdmin', internalType: 'address', type: 'address' }, + { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, + { name: 'multicall', internalType: 'address', type: 'address' }, + ], + indexed: false, + }, + ], + name: 'OrbitTokenBridgeDeploymentSet', + }, + { type: 'event', anonymous: false, inputs: [], name: 'OrbitTokenBridgeTemplatesUpdated' }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'previousOwner', internalType: 'address', type: 'address', indexed: true }, + { name: 'newOwner', internalType: 'address', type: 'address', indexed: true }, + ], + name: 'OwnershipTransferred', + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'canonicalL2FactoryAddress', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'payable', + type: 'function', + inputs: [ + { name: 'inbox', internalType: 'address', type: 'address' }, + { name: 'rollupOwner', internalType: 'address', type: 'address' }, + { name: 'maxGasForContracts', internalType: 'uint256', type: 'uint256' }, + { name: 'gasPriceBid', internalType: 'uint256', type: 'uint256' }, + ], + name: 'createTokenBridge', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'gasLimitForL2FactoryDeployment', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: 'inbox', internalType: 'address', type: 'address' }], + name: 'getRouter', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: '', internalType: 'address', type: 'address' }], + name: 'inboxToL1Deployment', + outputs: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [{ name: '', internalType: 'address', type: 'address' }], + name: 'inboxToL2Deployment', + outputs: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + { name: 'proxyAdmin', internalType: 'address', type: 'address' }, + { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, + { name: 'multicall', internalType: 'address', type: 'address' }, + ], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { + name: '_retryableSender', + internalType: 'contract L1TokenBridgeRetryableSender', + type: 'address', + }, + ], + name: 'initialize', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l1Multicall', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l1Templates', + outputs: [ + { name: 'routerTemplate', internalType: 'contract L1GatewayRouter', type: 'address' }, + { name: 'standardGatewayTemplate', internalType: 'contract L1ERC20Gateway', type: 'address' }, + { name: 'customGatewayTemplate', internalType: 'contract L1CustomGateway', type: 'address' }, + { name: 'wethGatewayTemplate', internalType: 'contract L1WethGateway', type: 'address' }, + { + name: 'feeTokenBasedRouterTemplate', + internalType: 'contract L1OrbitGatewayRouter', + type: 'address', + }, + { + name: 'feeTokenBasedStandardGatewayTemplate', + internalType: 'contract L1OrbitERC20Gateway', + type: 'address', + }, + { + name: 'feeTokenBasedCustomGatewayTemplate', + internalType: 'contract L1OrbitCustomGateway', + type: 'address', + }, + { name: 'upgradeExecutor', internalType: 'contract IUpgradeExecutor', type: 'address' }, + ], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l1Weth', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2CustomGatewayTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2MulticallTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2RouterTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2StandardGatewayTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2TokenBridgeFactoryTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2WethGatewayTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2WethTemplate', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'owner', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [], + name: 'renounceOwnership', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'retryableSender', + outputs: [{ name: '', internalType: 'contract L1TokenBridgeRetryableSender', type: 'address' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'inbox', internalType: 'address', type: 'address' }, + { + name: 'l1Deployment', + internalType: 'struct L1DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + ], + }, + { + name: 'l2Deployment', + internalType: 'struct L2DeploymentAddresses', + type: 'tuple', + components: [ + { name: 'router', internalType: 'address', type: 'address' }, + { name: 'standardGateway', internalType: 'address', type: 'address' }, + { name: 'customGateway', internalType: 'address', type: 'address' }, + { name: 'wethGateway', internalType: 'address', type: 'address' }, + { name: 'weth', internalType: 'address', type: 'address' }, + { name: 'proxyAdmin', internalType: 'address', type: 'address' }, + { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, + { name: 'multicall', internalType: 'address', type: 'address' }, + ], + }, + ], + name: 'setDeployment', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { + name: '_l1Templates', + internalType: 'struct L1AtomicTokenBridgeCreator.L1Templates', + type: 'tuple', + components: [ + { name: 'routerTemplate', internalType: 'contract L1GatewayRouter', type: 'address' }, + { + name: 'standardGatewayTemplate', + internalType: 'contract L1ERC20Gateway', + type: 'address', + }, + { + name: 'customGatewayTemplate', + internalType: 'contract L1CustomGateway', + type: 'address', + }, + { name: 'wethGatewayTemplate', internalType: 'contract L1WethGateway', type: 'address' }, + { + name: 'feeTokenBasedRouterTemplate', + internalType: 'contract L1OrbitGatewayRouter', + type: 'address', + }, + { + name: 'feeTokenBasedStandardGatewayTemplate', + internalType: 'contract L1OrbitERC20Gateway', + type: 'address', + }, + { + name: 'feeTokenBasedCustomGatewayTemplate', + internalType: 'contract L1OrbitCustomGateway', + type: 'address', + }, + { name: 'upgradeExecutor', internalType: 'contract IUpgradeExecutor', type: 'address' }, + ], + }, + { name: '_l2TokenBridgeFactoryTemplate', internalType: 'address', type: 'address' }, + { name: '_l2RouterTemplate', internalType: 'address', type: 'address' }, + { name: '_l2StandardGatewayTemplate', internalType: 'address', type: 'address' }, + { name: '_l2CustomGatewayTemplate', internalType: 'address', type: 'address' }, + { name: '_l2WethGatewayTemplate', internalType: 'address', type: 'address' }, + { name: '_l2WethTemplate', internalType: 'address', type: 'address' }, + { name: '_l2MulticallTemplate', internalType: 'address', type: 'address' }, + { name: '_l1Weth', internalType: 'address', type: 'address' }, + { name: '_l1Multicall', internalType: 'address', type: 'address' }, + { name: '_gasLimitForL2FactoryDeployment', internalType: 'uint256', type: 'uint256' }, + ], + name: 'setTemplates', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], + name: 'transferOwnership', + outputs: [], + }, +] as const; + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x4C240987d6fE4fa8C7a0004986e3db563150CA55) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x8B9D9490a68B1F16ac8A21DdAE5Fd7aB9d708c14) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570) + */ +export const tokenBridgeCreatorAddress = { + 1: '0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660', + 1337: '0x54B4D4e578E10178a6cA602bdb6df0F213296Af4', + 8453: '0x4C240987d6fE4fa8C7a0004986e3db563150CA55', + 17000: '0xac890ED9bC2494C053cE701F138958df95966d94', + 42161: '0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e', + 42170: '0x8B9D9490a68B1F16ac8A21DdAE5Fd7aB9d708c14', + 84532: '0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3', + 412346: '0x38F35Af53bF913c439eaB06A367e09D6eb253492', + 421614: '0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E', + 11155111: '0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570', +} as const; + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x4C240987d6fE4fa8C7a0004986e3db563150CA55) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x8B9D9490a68B1F16ac8A21DdAE5Fd7aB9d708c14) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570) + */ +export const tokenBridgeCreatorConfig = { + address: tokenBridgeCreatorAddress, + abi: tokenBridgeCreatorABI, +} as const; diff --git a/src/contracts/UpgradeExecutor.ts b/src/contracts/UpgradeExecutor.ts new file mode 100644 index 00000000..b58201f2 --- /dev/null +++ b/src/contracts/UpgradeExecutor.ts @@ -0,0 +1,9 @@ +import { parseAbi } from 'viem'; + +export const upgradeExecutorABI = parseAbi([ + 'function execute(address upgrade, bytes upgradeCallData)', + 'function executeCall(address target, bytes targetCallData)', + 'function hasRole(bytes32 role, address account) public view returns (bool)', + 'function grantRole(bytes32 role, address account)', + 'function revokeRole(bytes32 role, address account)', +]); diff --git a/src/createRollupPrepareTransaction.ts b/src/createRollupPrepareTransaction.ts index 2b943bb1..4528107b 100644 --- a/src/createRollupPrepareTransaction.ts +++ b/src/createRollupPrepareTransaction.ts @@ -1,11 +1,11 @@ import { Transaction, decodeFunctionData } from 'viem'; -import { rollupCreator } from './contracts'; +import { rollupCreatorABI } from './contracts/RollupCreator'; import { CreateRollupFunctionInputs } from './types/createRollupTypes'; function createRollupDecodeFunctionData(data: `0x${string}`) { return decodeFunctionData({ - abi: rollupCreator.abi, + abi: rollupCreatorABI, data, }); } diff --git a/src/createRollupPrepareTransactionReceipt.ts b/src/createRollupPrepareTransactionReceipt.ts index 440838b4..5eb21cae 100644 --- a/src/createRollupPrepareTransactionReceipt.ts +++ b/src/createRollupPrepareTransactionReceipt.ts @@ -1,10 +1,10 @@ import { TransactionReceipt, getAbiItem, getEventSelector, Log, decodeEventLog } from 'viem'; -import { rollupCreator } from './contracts'; +import { rollupCreatorABI } from './contracts/RollupCreator'; import { CoreContracts } from './types/CoreContracts'; function findRollupCreatedEventLog(txReceipt: TransactionReceipt) { - const abiItem = getAbiItem({ abi: rollupCreator.abi, name: 'RollupCreated' }); + const abiItem = getAbiItem({ abi: rollupCreatorABI, name: 'RollupCreated' }); const eventSelector = getEventSelector(abiItem); const log = txReceipt.logs.find((log) => log.topics[0] === eventSelector); @@ -18,7 +18,7 @@ function findRollupCreatedEventLog(txReceipt: TransactionReceipt) { } function decodeRollupCreatedEventLog(log: Log) { - const decodedEventLog = decodeEventLog({ ...log, abi: rollupCreator.abi }); + const decodedEventLog = decodeEventLog({ ...log, abi: rollupCreatorABI }); if (decodedEventLog.eventName !== 'RollupCreated') { throw new Error(`Expected "RollupCreated" event but found: ${decodedEventLog.eventName}`); diff --git a/src/createRollupPrepareTransactionRequest.ts b/src/createRollupPrepareTransactionRequest.ts index a7836a50..dc90315a 100644 --- a/src/createRollupPrepareTransactionRequest.ts +++ b/src/createRollupPrepareTransactionRequest.ts @@ -3,7 +3,7 @@ import { Address, PublicClient, Transport, Chain, encodeFunctionData, zeroAddres import { defaults } from './createRollupDefaults'; import { createRollupGetCallValue } from './createRollupGetCallValue'; import { createRollupGetMaxDataSize } from './createRollupGetMaxDataSize'; -import { rollupCreator } from './contracts'; +import { rollupCreatorABI } from './contracts/RollupCreator'; import { validateParentChain } from './types/ParentChain'; import { isCustomFeeTokenAddress } from './utils/isCustomFeeTokenAddress'; import { ChainConfig } from './types/ChainConfig'; @@ -21,7 +21,7 @@ import { function createRollupEncodeFunctionData(args: CreateRollupFunctionInputs) { return encodeFunctionData({ - abi: rollupCreator.abi, + abi: rollupCreatorABI, functionName: 'createRollup', args, }); diff --git a/src/createRollupPrepareTransactionRequest.unit.test.ts b/src/createRollupPrepareTransactionRequest.unit.test.ts index 185d75c8..24439734 100644 --- a/src/createRollupPrepareTransactionRequest.unit.test.ts +++ b/src/createRollupPrepareTransactionRequest.unit.test.ts @@ -6,7 +6,7 @@ import { generateChainId } from './utils'; import { prepareChainConfig } from './prepareChainConfig'; import { createRollupPrepareDeploymentParamsConfig } from './createRollupPrepareDeploymentParamsConfig'; import { createRollupPrepareTransactionRequest } from './createRollupPrepareTransactionRequest'; -import { rollupCreator } from './contracts'; +import { rollupCreatorAddress } from './contracts/RollupCreator'; import { getNitroTestnodePrivateKeyAccounts } from './testHelpers'; @@ -196,7 +196,7 @@ it(`successfully prepares a transaction request with the default rollup creator expect(txRequest.account).toEqual(deployer.address); expect(txRequest.from).toEqual(deployer.address); - expect(txRequest.to).toEqual(rollupCreator.address[arbitrumSepolia.id]); + expect(txRequest.to).toEqual(rollupCreatorAddress[arbitrumSepolia.id]); expect(txRequest.chainId).toEqual(arbitrumSepolia.id); expect(txRequest.gas).toEqual(1_000n); }); diff --git a/src/createTokenBridge.integration.test.ts b/src/createTokenBridge.integration.test.ts index 40cbca6c..99e68507 100644 --- a/src/createTokenBridge.integration.test.ts +++ b/src/createTokenBridge.integration.test.ts @@ -15,7 +15,7 @@ import { createTokenBridgePrepareTransactionReceipt } from './createTokenBridgeP import { deployTokenBridgeCreator } from './createTokenBridge-testHelpers'; import { CreateTokenBridgeEnoughCustomFeeTokenAllowanceParams } from './createTokenBridgeEnoughCustomFeeTokenAllowance'; import { createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest } from './createTokenBridgePrepareCustomFeeTokenApprovalTransactionRequest'; -import { erc20 } from './contracts'; +import { erc20ABI } from './contracts/ERC20'; import { createTokenBridgePrepareSetWethGatewayTransactionRequest } from './createTokenBridgePrepareSetWethGatewayTransactionRequest'; import { createTokenBridgePrepareSetWethGatewayTransactionReceipt } from './createTokenBridgePrepareSetWethGatewayTransactionReceipt'; import { createTokenBridge } from './createTokenBridge'; @@ -216,7 +216,7 @@ describe('createTokenBridge utils function', () => { chain: nitroTestnodeL2Client.chain, to: testnodeInformation.l3NativeToken, data: encodeFunctionData({ - abi: erc20.abi, + abi: erc20ABI, functionName: 'transfer', args: [l3RollupOwner.address, parseEther('500')], }), @@ -382,7 +382,7 @@ describe('createTokenBridge', () => { chain: nitroTestnodeL2Client.chain, to: testnodeInformation.l3NativeToken, data: encodeFunctionData({ - abi: erc20.abi, + abi: erc20ABI, functionName: 'transfer', args: [l3RollupOwner.address, parseEther('500')], }), diff --git a/src/createTokenBridgeFetchTokenBridgeContracts.ts b/src/createTokenBridgeFetchTokenBridgeContracts.ts index f53ed953..f4121be8 100644 --- a/src/createTokenBridgeFetchTokenBridgeContracts.ts +++ b/src/createTokenBridgeFetchTokenBridgeContracts.ts @@ -1,6 +1,6 @@ import { Address, PublicClient, Transport, Chain } from 'viem'; -import { tokenBridgeCreator } from './contracts'; +import { tokenBridgeCreatorABI } from './contracts/TokenBridgeCreator'; import { Prettify } from './types/utils'; import { WithTokenBridgeCreatorAddressOverride } from './types/createTokenBridgeTypes'; @@ -32,14 +32,14 @@ export async function createTokenBridgeFetchTokenBridgeContracts log.topics[0] === eventSelector); @@ -36,7 +36,7 @@ function findOrbitTokenBridgeCreatedEventLog(txReceipt: TransactionReceipt) { } function decodeOrbitTokenBridgeCreatedEventLog(log: Log) { - const decodedEventLog = decodeEventLog({ ...log, abi: tokenBridgeCreator.abi }); + const decodedEventLog = decodeEventLog({ ...log, abi: tokenBridgeCreatorABI }); if (decodedEventLog.eventName !== 'OrbitTokenBridgeCreated') { throw new Error( diff --git a/src/createTokenBridgePrepareTransactionRequest.ts b/src/createTokenBridgePrepareTransactionRequest.ts index 82494b88..e357bf9f 100644 --- a/src/createTokenBridgePrepareTransactionRequest.ts +++ b/src/createTokenBridgePrepareTransactionRequest.ts @@ -1,6 +1,6 @@ import { Address, PublicClient, Transport, Chain, encodeFunctionData } from 'viem'; -import { tokenBridgeCreator } from './contracts'; +import { tokenBridgeCreatorABI } from './contracts/TokenBridgeCreator'; import { validateParentChain } from './types/ParentChain'; import { createTokenBridgeGetInputs } from './createTokenBridge-ethers'; import { isCustomFeeTokenChain } from './utils/isCustomFeeTokenChain'; @@ -72,7 +72,7 @@ export async function createTokenBridgePrepareTransactionRequest< chain: parentChainPublicClient.chain, to: tokenBridgeCreatorAddress, data: encodeFunctionData({ - abi: tokenBridgeCreator.abi, + abi: tokenBridgeCreatorABI, functionName: 'createTokenBridge', args: [inbox, params.rollupOwner, maxGasForContracts, gasPrice], }), diff --git a/src/decorators/sequencerInboxActions.integration.test.ts b/src/decorators/sequencerInboxActions.integration.test.ts index e68317fe..8b329051 100644 --- a/src/decorators/sequencerInboxActions.integration.test.ts +++ b/src/decorators/sequencerInboxActions.integration.test.ts @@ -9,7 +9,7 @@ import { createRollupHelper, } from '../testHelpers'; import { sequencerInboxActions } from './sequencerInboxActions'; -import { sequencerInboxABI } from '../abi/sequencerInboxABI'; +import { sequencerInboxABI } from '../contracts/SequencerInbox'; const { l3RollupOwner, l3TokenBridgeDeployer, deployer } = getNitroTestnodePrivateKeyAccounts(); diff --git a/src/generated.ts b/src/generated.ts deleted file mode 100644 index dea6f0b5..00000000 --- a/src/generated.ts +++ /dev/null @@ -1,1413 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ArbAggregator -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006d) - */ -export const arbAggregatorABI = [ - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'newBatchPoster', internalType: 'address', type: 'address' }], - name: 'addBatchPoster', - outputs: [], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getBatchPosters', - outputs: [{ name: '', internalType: 'address[]', type: 'address[]' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getDefaultAggregator', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'batchPoster', internalType: 'address', type: 'address' }], - name: 'getFeeCollector', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'addr', internalType: 'address', type: 'address' }], - name: 'getPreferredAggregator', - outputs: [ - { name: '', internalType: 'address', type: 'address' }, - { name: '', internalType: 'bool', type: 'bool' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'aggregator', internalType: 'address', type: 'address' }], - name: 'getTxBaseFee', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'batchPoster', internalType: 'address', type: 'address' }, - { name: 'newFeeCollector', internalType: 'address', type: 'address' }, - ], - name: 'setFeeCollector', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'aggregator', internalType: 'address', type: 'address' }, - { name: 'feeInL1Gas', internalType: 'uint256', type: 'uint256' }, - ], - name: 'setTxBaseFee', - outputs: [], - }, -] as const; - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006d) - */ -export const arbAggregatorAddress = { - 421614: '0x000000000000000000000000000000000000006D', -} as const; - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006d) - */ -export const arbAggregatorConfig = { - address: arbAggregatorAddress, - abi: arbAggregatorABI, -} as const; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ArbGasInfo -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006c) - */ -export const arbGasInfoABI = [ - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getAmortizedCostCapBips', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getCurrentTxL1GasFees', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getGasAccountingParams', - outputs: [ - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getGasBacklog', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getGasBacklogTolerance', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1BaseFeeEstimate', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1BaseFeeEstimateInertia', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1FeesAvailable', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1GasPriceEstimate', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1PricingEquilibrationUnits', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1PricingFundsDueForRewards', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1PricingSurplus', - outputs: [{ name: '', internalType: 'int256', type: 'int256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1PricingUnitsSinceUpdate', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1RewardRate', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getL1RewardRecipient', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getLastL1PricingSurplus', - outputs: [{ name: '', internalType: 'int256', type: 'int256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getLastL1PricingUpdateTime', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getMinimumGasPrice', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getPerBatchGasCharge', - outputs: [{ name: '', internalType: 'int64', type: 'int64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getPricesInArbGas', - outputs: [ - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'aggregator', internalType: 'address', type: 'address' }], - name: 'getPricesInArbGasWithAggregator', - outputs: [ - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getPricesInWei', - outputs: [ - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'aggregator', internalType: 'address', type: 'address' }], - name: 'getPricesInWeiWithAggregator', - outputs: [ - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - { name: '', internalType: 'uint256', type: 'uint256' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getPricingInertia', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, -] as const; - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006c) - */ -export const arbGasInfoAddress = { - 421614: '0x000000000000000000000000000000000000006C', -} as const; - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006c) - */ -export const arbGasInfoConfig = { address: arbGasInfoAddress, abi: arbGasInfoABI } as const; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ArbOwner -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x0000000000000000000000000000000000000070) - */ -export const arbOwnerABI = [ - { - type: 'event', - anonymous: false, - inputs: [ - { name: 'method', internalType: 'bytes4', type: 'bytes4', indexed: true }, - { name: 'owner', internalType: 'address', type: 'address', indexed: true }, - { name: 'data', internalType: 'bytes', type: 'bytes', indexed: false }, - ], - name: 'OwnerActs', - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], - name: 'addChainOwner', - outputs: [], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getAllChainOwners', - outputs: [{ name: '', internalType: 'address[]', type: 'address[]' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getInfraFeeAccount', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getNetworkFeeAccount', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'addr', internalType: 'address', type: 'address' }], - name: 'isChainOwner', - outputs: [{ name: '', internalType: 'bool', type: 'bool' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'maxWeiToRelease', internalType: 'uint256', type: 'uint256' }], - name: 'releaseL1PricerSurplusFunds', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'ownerToRemove', internalType: 'address', type: 'address' }], - name: 'removeChainOwner', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'newVersion', internalType: 'uint64', type: 'uint64' }, - { name: 'timestamp', internalType: 'uint64', type: 'uint64' }, - ], - name: 'scheduleArbOSUpgrade', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'cap', internalType: 'uint64', type: 'uint64' }], - name: 'setAmortizedCostCapBips', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'level', internalType: 'uint64', type: 'uint64' }], - name: 'setBrotliCompressionLevel', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'chainConfig', internalType: 'string', type: 'string' }], - name: 'setChainConfig', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'newInfraFeeAccount', internalType: 'address', type: 'address' }], - name: 'setInfraFeeAccount', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'inertia', internalType: 'uint64', type: 'uint64' }], - name: 'setL1BaseFeeEstimateInertia', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'pricePerUnit', internalType: 'uint256', type: 'uint256' }], - name: 'setL1PricePerUnit', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'equilibrationUnits', internalType: 'uint256', type: 'uint256' }], - name: 'setL1PricingEquilibrationUnits', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'inertia', internalType: 'uint64', type: 'uint64' }], - name: 'setL1PricingInertia', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'weiPerUnit', internalType: 'uint64', type: 'uint64' }], - name: 'setL1PricingRewardRate', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'recipient', internalType: 'address', type: 'address' }], - name: 'setL1PricingRewardRecipient', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'priceInWei', internalType: 'uint256', type: 'uint256' }], - name: 'setL2BaseFee', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'sec', internalType: 'uint64', type: 'uint64' }], - name: 'setL2GasBacklogTolerance', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'sec', internalType: 'uint64', type: 'uint64' }], - name: 'setL2GasPricingInertia', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'limit', internalType: 'uint64', type: 'uint64' }], - name: 'setMaxTxGasLimit', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'priceInWei', internalType: 'uint256', type: 'uint256' }], - name: 'setMinimumL2BaseFee', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'newNetworkFeeAccount', internalType: 'address', type: 'address' }], - name: 'setNetworkFeeAccount', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'cost', internalType: 'int64', type: 'int64' }], - name: 'setPerBatchGasCharge', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'limit', internalType: 'uint64', type: 'uint64' }], - name: 'setSpeedLimit', - outputs: [], - }, -] as const; - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x0000000000000000000000000000000000000070) - */ -export const arbOwnerAddress = { - 421614: '0x0000000000000000000000000000000000000070', -} as const; - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x0000000000000000000000000000000000000070) - */ -export const arbOwnerConfig = { address: arbOwnerAddress, abi: arbOwnerABI } as const; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ArbOwnerPublic -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006b) - */ -export const arbOwnerPublicABI = [ - { - type: 'event', - anonymous: false, - inputs: [{ name: 'rectifiedOwner', internalType: 'address', type: 'address', indexed: false }], - name: 'ChainOwnerRectified', - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getAllChainOwners', - outputs: [{ name: '', internalType: 'address[]', type: 'address[]' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getBrotliCompressionLevel', - outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getInfraFeeAccount', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getNetworkFeeAccount', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'getScheduledUpgrade', - outputs: [ - { name: 'arbosVersion', internalType: 'uint64', type: 'uint64' }, - { name: 'scheduledForTimestamp', internalType: 'uint64', type: 'uint64' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'addr', internalType: 'address', type: 'address' }], - name: 'isChainOwner', - outputs: [{ name: '', internalType: 'bool', type: 'bool' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'ownerToRectify', internalType: 'address', type: 'address' }], - name: 'rectifyChainOwner', - outputs: [], - }, -] as const; - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006b) - */ -export const arbOwnerPublicAddress = { - 421614: '0x000000000000000000000000000000000000006b', -} as const; - -/** - * [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x000000000000000000000000000000000000006b) - */ -export const arbOwnerPublicConfig = { - address: arbOwnerPublicAddress, - abi: arbOwnerPublicABI, -} as const; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ERC20 -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -export const erc20ABI = [ - { - type: 'event', - inputs: [ - { name: 'owner', type: 'address', indexed: true }, - { name: 'spender', type: 'address', indexed: true }, - { name: 'value', type: 'uint256', indexed: false }, - ], - name: 'Approval', - }, - { - type: 'event', - inputs: [ - { name: 'from', type: 'address', indexed: true }, - { name: 'to', type: 'address', indexed: true }, - { name: 'value', type: 'uint256', indexed: false }, - ], - name: 'Transfer', - }, - { - stateMutability: 'view', - type: 'function', - inputs: [ - { name: 'owner', type: 'address' }, - { name: 'spender', type: 'address' }, - ], - name: 'allowance', - outputs: [{ type: 'uint256' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'spender', type: 'address' }, - { name: 'amount', type: 'uint256' }, - ], - name: 'approve', - outputs: [{ type: 'bool' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'account', type: 'address' }], - name: 'balanceOf', - outputs: [{ type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'decimals', - outputs: [{ type: 'uint8' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'name', - outputs: [{ type: 'string' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'symbol', - outputs: [{ type: 'string' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'totalSupply', - outputs: [{ type: 'uint256' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'recipient', type: 'address' }, - { name: 'amount', type: 'uint256' }, - ], - name: 'transfer', - outputs: [{ type: 'bool' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'sender', type: 'address' }, - { name: 'recipient', type: 'address' }, - { name: 'amount', type: 'uint256' }, - ], - name: 'transferFrom', - outputs: [{ type: 'bool' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'spender', type: 'address' }, - { name: 'addedValue', type: 'uint256' }, - ], - name: 'increaseAllowance', - outputs: [{ type: 'bool' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'spender', type: 'address' }, - { name: 'subtractedValue', type: 'uint256' }, - ], - name: 'decreaseAllowance', - outputs: [{ type: 'bool' }], - }, -] as const; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// RollupCreator -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x90d68b056c411015eae3ec0b98ad94e2c91419f1) - * - - * - [__View Contract on Base Basescan__](https://basescan.org/address/0x850F050C65B34966895AdA26a4D06923901916DB) - * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) - * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) - * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x1E0921818df948c338380e722C8aE91Bb285763C) - * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x06E341073b2749e0Bb9912461351f716DeCDa9b0) - * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfbd0b034e6305788007f6e0123cc5eae701a5751) - */ -export const rollupCreatorABI = [ - { stateMutability: 'nonpayable', type: 'constructor', inputs: [] }, - { - type: 'event', - anonymous: false, - inputs: [ - { name: 'previousOwner', internalType: 'address', type: 'address', indexed: true }, - { name: 'newOwner', internalType: 'address', type: 'address', indexed: true }, - ], - name: 'OwnershipTransferred', - }, - { - type: 'event', - anonymous: false, - inputs: [ - { name: 'rollupAddress', internalType: 'address', type: 'address', indexed: true }, - { name: 'nativeToken', internalType: 'address', type: 'address', indexed: true }, - { name: 'inboxAddress', internalType: 'address', type: 'address', indexed: false }, - { name: 'outbox', internalType: 'address', type: 'address', indexed: false }, - { name: 'rollupEventInbox', internalType: 'address', type: 'address', indexed: false }, - { name: 'challengeManager', internalType: 'address', type: 'address', indexed: false }, - { name: 'adminProxy', internalType: 'address', type: 'address', indexed: false }, - { name: 'sequencerInbox', internalType: 'address', type: 'address', indexed: false }, - { name: 'bridge', internalType: 'address', type: 'address', indexed: false }, - { name: 'upgradeExecutor', internalType: 'address', type: 'address', indexed: false }, - { name: 'validatorUtils', internalType: 'address', type: 'address', indexed: false }, - { name: 'validatorWalletCreator', internalType: 'address', type: 'address', indexed: false }, - ], - name: 'RollupCreated', - }, - { type: 'event', anonymous: false, inputs: [], name: 'TemplatesUpdated' }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'bridgeCreator', - outputs: [{ name: '', internalType: 'contract BridgeCreator', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'challengeManagerTemplate', - outputs: [{ name: '', internalType: 'contract IChallengeManager', type: 'address' }], - }, - { - stateMutability: 'payable', - type: 'function', - inputs: [ - { - name: 'deployParams', - internalType: 'struct RollupCreator.RollupDeploymentParams', - type: 'tuple', - components: [ - { - name: 'config', - internalType: 'struct Config', - type: 'tuple', - components: [ - { name: 'confirmPeriodBlocks', internalType: 'uint64', type: 'uint64' }, - { name: 'extraChallengeTimeBlocks', internalType: 'uint64', type: 'uint64' }, - { name: 'stakeToken', internalType: 'address', type: 'address' }, - { name: 'baseStake', internalType: 'uint256', type: 'uint256' }, - { name: 'wasmModuleRoot', internalType: 'bytes32', type: 'bytes32' }, - { name: 'owner', internalType: 'address', type: 'address' }, - { name: 'loserStakeEscrow', internalType: 'address', type: 'address' }, - { name: 'chainId', internalType: 'uint256', type: 'uint256' }, - { name: 'chainConfig', internalType: 'string', type: 'string' }, - { name: 'genesisBlockNum', internalType: 'uint64', type: 'uint64' }, - { - name: 'sequencerInboxMaxTimeVariation', - internalType: 'struct ISequencerInbox.MaxTimeVariation', - type: 'tuple', - components: [ - { name: 'delayBlocks', internalType: 'uint256', type: 'uint256' }, - { name: 'futureBlocks', internalType: 'uint256', type: 'uint256' }, - { name: 'delaySeconds', internalType: 'uint256', type: 'uint256' }, - { name: 'futureSeconds', internalType: 'uint256', type: 'uint256' }, - ], - }, - ], - }, - { name: 'batchPoster', internalType: 'address', type: 'address' }, - { name: 'validators', internalType: 'address[]', type: 'address[]' }, - { name: 'maxDataSize', internalType: 'uint256', type: 'uint256' }, - { name: 'nativeToken', internalType: 'address', type: 'address' }, - { name: 'deployFactoriesToL2', internalType: 'bool', type: 'bool' }, - { name: 'maxFeePerGasForRetryables', internalType: 'uint256', type: 'uint256' }, - ], - }, - ], - name: 'createRollup', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l2FactoriesDeployer', - outputs: [{ name: '', internalType: 'contract DeployHelper', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'osp', - outputs: [{ name: '', internalType: 'contract IOneStepProofEntry', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'owner', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [], - name: 'renounceOwnership', - outputs: [], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'rollupAdminLogic', - outputs: [{ name: '', internalType: 'contract IRollupAdmin', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'rollupUserLogic', - outputs: [{ name: '', internalType: 'contract IRollupUser', type: 'address' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: '_bridgeCreator', internalType: 'contract BridgeCreator', type: 'address' }, - { name: '_osp', internalType: 'contract IOneStepProofEntry', type: 'address' }, - { - name: '_challengeManagerLogic', - internalType: 'contract IChallengeManager', - type: 'address', - }, - { name: '_rollupAdminLogic', internalType: 'contract IRollupAdmin', type: 'address' }, - { name: '_rollupUserLogic', internalType: 'contract IRollupUser', type: 'address' }, - { name: '_upgradeExecutorLogic', internalType: 'contract IUpgradeExecutor', type: 'address' }, - { name: '_validatorUtils', internalType: 'address', type: 'address' }, - { name: '_validatorWalletCreator', internalType: 'address', type: 'address' }, - { name: '_l2FactoriesDeployer', internalType: 'contract DeployHelper', type: 'address' }, - ], - name: 'setTemplates', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], - name: 'transferOwnership', - outputs: [], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'upgradeExecutorLogic', - outputs: [{ name: '', internalType: 'contract IUpgradeExecutor', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'validatorUtils', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'validatorWalletCreator', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { stateMutability: 'payable', type: 'receive' }, -] as const; - -/** - * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x90d68b056c411015eae3ec0b98ad94e2c91419f1) - * - - * - [__View Contract on Base Basescan__](https://basescan.org/address/0x850F050C65B34966895AdA26a4D06923901916DB) - * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) - * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) - * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x1E0921818df948c338380e722C8aE91Bb285763C) - * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x06E341073b2749e0Bb9912461351f716DeCDa9b0) - * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfbd0b034e6305788007f6e0123cc5eae701a5751) - */ -export const rollupCreatorAddress = { - 1: '0x90D68B056c411015eaE3EC0b98AD94E2C91419F1', - 1337: '0x596eAbE0291D4cdAfAC7ef53D16C92Bf6922b5e0', - 8453: '0x850F050C65B34966895AdA26a4D06923901916DB', - 17000: '0xB512078282F462Ba104231ad856464Ceb0a7747e', - 42161: '0x9CAd81628aB7D8e239F1A5B497313341578c5F71', - 42170: '0x9CAd81628aB7D8e239F1A5B497313341578c5F71', - 84532: '0x1E0921818df948c338380e722C8aE91Bb285763C', - 412346: '0x3BaF9f08bAD68869eEdEa90F2Cc546Bd80F1A651', - 421614: '0x06E341073b2749e0Bb9912461351f716DeCDa9b0', - 11155111: '0xfBD0B034e6305788007f6e0123cc5EaE701a5751', -} as const; - -/** - * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x90d68b056c411015eae3ec0b98ad94e2c91419f1) - * - - * - [__View Contract on Base Basescan__](https://basescan.org/address/0x850F050C65B34966895AdA26a4D06923901916DB) - * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) - * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9CAd81628aB7D8e239F1A5B497313341578c5F71) - * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x1E0921818df948c338380e722C8aE91Bb285763C) - * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x06E341073b2749e0Bb9912461351f716DeCDa9b0) - * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfbd0b034e6305788007f6e0123cc5eae701a5751) - */ -export const rollupCreatorConfig = { - address: rollupCreatorAddress, - abi: rollupCreatorABI, -} as const; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// TokenBridgeCreator -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660) - * - - * - [__View Contract on Base Basescan__](https://basescan.org/address/0x4C240987d6fE4fa8C7a0004986e3db563150CA55) - * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e) - * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x8B9D9490a68B1F16ac8A21DdAE5Fd7aB9d708c14) - * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3) - * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E) - * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570) - */ -export const tokenBridgeCreatorABI = [ - { stateMutability: 'nonpayable', type: 'constructor', inputs: [] }, - { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_L2FactoryCannotBeChanged' }, - { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_OnlyRollupOwner' }, - { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_ProxyAdminNotFound' }, - { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_RollupOwnershipMisconfig' }, - { type: 'error', inputs: [], name: 'L1AtomicTokenBridgeCreator_TemplatesNotSet' }, - { - type: 'event', - anonymous: false, - inputs: [{ name: 'version', internalType: 'uint8', type: 'uint8', indexed: false }], - name: 'Initialized', - }, - { - type: 'event', - anonymous: false, - inputs: [ - { name: 'inbox', internalType: 'address', type: 'address', indexed: true }, - { name: 'owner', internalType: 'address', type: 'address', indexed: true }, - { - name: 'l1Deployment', - internalType: 'struct L1DeploymentAddresses', - type: 'tuple', - components: [ - { name: 'router', internalType: 'address', type: 'address' }, - { name: 'standardGateway', internalType: 'address', type: 'address' }, - { name: 'customGateway', internalType: 'address', type: 'address' }, - { name: 'wethGateway', internalType: 'address', type: 'address' }, - { name: 'weth', internalType: 'address', type: 'address' }, - ], - indexed: false, - }, - { - name: 'l2Deployment', - internalType: 'struct L2DeploymentAddresses', - type: 'tuple', - components: [ - { name: 'router', internalType: 'address', type: 'address' }, - { name: 'standardGateway', internalType: 'address', type: 'address' }, - { name: 'customGateway', internalType: 'address', type: 'address' }, - { name: 'wethGateway', internalType: 'address', type: 'address' }, - { name: 'weth', internalType: 'address', type: 'address' }, - { name: 'proxyAdmin', internalType: 'address', type: 'address' }, - { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, - { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, - { name: 'multicall', internalType: 'address', type: 'address' }, - ], - indexed: false, - }, - { name: 'proxyAdmin', internalType: 'address', type: 'address', indexed: false }, - { name: 'upgradeExecutor', internalType: 'address', type: 'address', indexed: false }, - ], - name: 'OrbitTokenBridgeCreated', - }, - { - type: 'event', - anonymous: false, - inputs: [ - { name: 'inbox', internalType: 'address', type: 'address', indexed: true }, - { - name: 'l1', - internalType: 'struct L1DeploymentAddresses', - type: 'tuple', - components: [ - { name: 'router', internalType: 'address', type: 'address' }, - { name: 'standardGateway', internalType: 'address', type: 'address' }, - { name: 'customGateway', internalType: 'address', type: 'address' }, - { name: 'wethGateway', internalType: 'address', type: 'address' }, - { name: 'weth', internalType: 'address', type: 'address' }, - ], - indexed: false, - }, - { - name: 'l2', - internalType: 'struct L2DeploymentAddresses', - type: 'tuple', - components: [ - { name: 'router', internalType: 'address', type: 'address' }, - { name: 'standardGateway', internalType: 'address', type: 'address' }, - { name: 'customGateway', internalType: 'address', type: 'address' }, - { name: 'wethGateway', internalType: 'address', type: 'address' }, - { name: 'weth', internalType: 'address', type: 'address' }, - { name: 'proxyAdmin', internalType: 'address', type: 'address' }, - { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, - { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, - { name: 'multicall', internalType: 'address', type: 'address' }, - ], - indexed: false, - }, - ], - name: 'OrbitTokenBridgeDeploymentSet', - }, - { type: 'event', anonymous: false, inputs: [], name: 'OrbitTokenBridgeTemplatesUpdated' }, - { - type: 'event', - anonymous: false, - inputs: [ - { name: 'previousOwner', internalType: 'address', type: 'address', indexed: true }, - { name: 'newOwner', internalType: 'address', type: 'address', indexed: true }, - ], - name: 'OwnershipTransferred', - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'canonicalL2FactoryAddress', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'payable', - type: 'function', - inputs: [ - { name: 'inbox', internalType: 'address', type: 'address' }, - { name: 'rollupOwner', internalType: 'address', type: 'address' }, - { name: 'maxGasForContracts', internalType: 'uint256', type: 'uint256' }, - { name: 'gasPriceBid', internalType: 'uint256', type: 'uint256' }, - ], - name: 'createTokenBridge', - outputs: [], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'gasLimitForL2FactoryDeployment', - outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: 'inbox', internalType: 'address', type: 'address' }], - name: 'getRouter', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: '', internalType: 'address', type: 'address' }], - name: 'inboxToL1Deployment', - outputs: [ - { name: 'router', internalType: 'address', type: 'address' }, - { name: 'standardGateway', internalType: 'address', type: 'address' }, - { name: 'customGateway', internalType: 'address', type: 'address' }, - { name: 'wethGateway', internalType: 'address', type: 'address' }, - { name: 'weth', internalType: 'address', type: 'address' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [{ name: '', internalType: 'address', type: 'address' }], - name: 'inboxToL2Deployment', - outputs: [ - { name: 'router', internalType: 'address', type: 'address' }, - { name: 'standardGateway', internalType: 'address', type: 'address' }, - { name: 'customGateway', internalType: 'address', type: 'address' }, - { name: 'wethGateway', internalType: 'address', type: 'address' }, - { name: 'weth', internalType: 'address', type: 'address' }, - { name: 'proxyAdmin', internalType: 'address', type: 'address' }, - { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, - { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, - { name: 'multicall', internalType: 'address', type: 'address' }, - ], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { - name: '_retryableSender', - internalType: 'contract L1TokenBridgeRetryableSender', - type: 'address', - }, - ], - name: 'initialize', - outputs: [], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l1Multicall', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l1Templates', - outputs: [ - { name: 'routerTemplate', internalType: 'contract L1GatewayRouter', type: 'address' }, - { name: 'standardGatewayTemplate', internalType: 'contract L1ERC20Gateway', type: 'address' }, - { name: 'customGatewayTemplate', internalType: 'contract L1CustomGateway', type: 'address' }, - { name: 'wethGatewayTemplate', internalType: 'contract L1WethGateway', type: 'address' }, - { - name: 'feeTokenBasedRouterTemplate', - internalType: 'contract L1OrbitGatewayRouter', - type: 'address', - }, - { - name: 'feeTokenBasedStandardGatewayTemplate', - internalType: 'contract L1OrbitERC20Gateway', - type: 'address', - }, - { - name: 'feeTokenBasedCustomGatewayTemplate', - internalType: 'contract L1OrbitCustomGateway', - type: 'address', - }, - { name: 'upgradeExecutor', internalType: 'contract IUpgradeExecutor', type: 'address' }, - ], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l1Weth', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l2CustomGatewayTemplate', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l2MulticallTemplate', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l2RouterTemplate', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l2StandardGatewayTemplate', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l2TokenBridgeFactoryTemplate', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l2WethGatewayTemplate', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'l2WethTemplate', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'owner', - outputs: [{ name: '', internalType: 'address', type: 'address' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [], - name: 'renounceOwnership', - outputs: [], - }, - { - stateMutability: 'view', - type: 'function', - inputs: [], - name: 'retryableSender', - outputs: [{ name: '', internalType: 'contract L1TokenBridgeRetryableSender', type: 'address' }], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { name: 'inbox', internalType: 'address', type: 'address' }, - { - name: 'l1Deployment', - internalType: 'struct L1DeploymentAddresses', - type: 'tuple', - components: [ - { name: 'router', internalType: 'address', type: 'address' }, - { name: 'standardGateway', internalType: 'address', type: 'address' }, - { name: 'customGateway', internalType: 'address', type: 'address' }, - { name: 'wethGateway', internalType: 'address', type: 'address' }, - { name: 'weth', internalType: 'address', type: 'address' }, - ], - }, - { - name: 'l2Deployment', - internalType: 'struct L2DeploymentAddresses', - type: 'tuple', - components: [ - { name: 'router', internalType: 'address', type: 'address' }, - { name: 'standardGateway', internalType: 'address', type: 'address' }, - { name: 'customGateway', internalType: 'address', type: 'address' }, - { name: 'wethGateway', internalType: 'address', type: 'address' }, - { name: 'weth', internalType: 'address', type: 'address' }, - { name: 'proxyAdmin', internalType: 'address', type: 'address' }, - { name: 'beaconProxyFactory', internalType: 'address', type: 'address' }, - { name: 'upgradeExecutor', internalType: 'address', type: 'address' }, - { name: 'multicall', internalType: 'address', type: 'address' }, - ], - }, - ], - name: 'setDeployment', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [ - { - name: '_l1Templates', - internalType: 'struct L1AtomicTokenBridgeCreator.L1Templates', - type: 'tuple', - components: [ - { name: 'routerTemplate', internalType: 'contract L1GatewayRouter', type: 'address' }, - { - name: 'standardGatewayTemplate', - internalType: 'contract L1ERC20Gateway', - type: 'address', - }, - { - name: 'customGatewayTemplate', - internalType: 'contract L1CustomGateway', - type: 'address', - }, - { name: 'wethGatewayTemplate', internalType: 'contract L1WethGateway', type: 'address' }, - { - name: 'feeTokenBasedRouterTemplate', - internalType: 'contract L1OrbitGatewayRouter', - type: 'address', - }, - { - name: 'feeTokenBasedStandardGatewayTemplate', - internalType: 'contract L1OrbitERC20Gateway', - type: 'address', - }, - { - name: 'feeTokenBasedCustomGatewayTemplate', - internalType: 'contract L1OrbitCustomGateway', - type: 'address', - }, - { name: 'upgradeExecutor', internalType: 'contract IUpgradeExecutor', type: 'address' }, - ], - }, - { name: '_l2TokenBridgeFactoryTemplate', internalType: 'address', type: 'address' }, - { name: '_l2RouterTemplate', internalType: 'address', type: 'address' }, - { name: '_l2StandardGatewayTemplate', internalType: 'address', type: 'address' }, - { name: '_l2CustomGatewayTemplate', internalType: 'address', type: 'address' }, - { name: '_l2WethGatewayTemplate', internalType: 'address', type: 'address' }, - { name: '_l2WethTemplate', internalType: 'address', type: 'address' }, - { name: '_l2MulticallTemplate', internalType: 'address', type: 'address' }, - { name: '_l1Weth', internalType: 'address', type: 'address' }, - { name: '_l1Multicall', internalType: 'address', type: 'address' }, - { name: '_gasLimitForL2FactoryDeployment', internalType: 'uint256', type: 'uint256' }, - ], - name: 'setTemplates', - outputs: [], - }, - { - stateMutability: 'nonpayable', - type: 'function', - inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], - name: 'transferOwnership', - outputs: [], - }, -] as const; - -/** - * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660) - * - - * - [__View Contract on Base Basescan__](https://basescan.org/address/0x4C240987d6fE4fa8C7a0004986e3db563150CA55) - * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e) - * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x8B9D9490a68B1F16ac8A21DdAE5Fd7aB9d708c14) - * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3) - * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E) - * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570) - */ -export const tokenBridgeCreatorAddress = { - 1: '0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660', - 1337: '0x54B4D4e578E10178a6cA602bdb6df0F213296Af4', - 8453: '0x4C240987d6fE4fa8C7a0004986e3db563150CA55', - 17000: '0xac890ED9bC2494C053cE701F138958df95966d94', - 42161: '0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e', - 42170: '0x8B9D9490a68B1F16ac8A21DdAE5Fd7aB9d708c14', - 84532: '0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3', - 412346: '0x38F35Af53bF913c439eaB06A367e09D6eb253492', - 421614: '0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E', - 11155111: '0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570', -} as const; - -/** - * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660) - * - - * - [__View Contract on Base Basescan__](https://basescan.org/address/0x4C240987d6fE4fa8C7a0004986e3db563150CA55) - * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e) - * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x8B9D9490a68B1F16ac8A21DdAE5Fd7aB9d708c14) - * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3) - * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E) - * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0x7edb2dfBeEf9417e0454A80c51EE0C034e45a570) - */ -export const tokenBridgeCreatorConfig = { - address: tokenBridgeCreatorAddress, - abi: tokenBridgeCreatorABI, -} as const; diff --git a/src/getBatchPosters.ts b/src/getBatchPosters.ts index 7dd3e50c..c67a166a 100644 --- a/src/getBatchPosters.ts +++ b/src/getBatchPosters.ts @@ -8,20 +8,24 @@ import { getAbiItem, getFunctionSelector, } from 'viem'; -import { rollupCreator, upgradeExecutor } from './contracts'; -import { safeL2ABI, sequencerInboxABI } from './abi'; + +import { rollupCreatorABI } from './contracts/RollupCreator'; +import { sequencerInboxABI } from './contracts/SequencerInbox'; +import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; +import { gnosisSafeL2ABI } from './contracts/GnosisSafeL2'; + import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; -const createRollupABI = getAbiItem({ abi: rollupCreator.abi, name: 'createRollup' }); +const createRollupABI = getAbiItem({ abi: rollupCreatorABI, name: 'createRollup' }); const createRollupFunctionSelector = getFunctionSelector(createRollupABI); const setIsBatchPosterABI = getAbiItem({ abi: sequencerInboxABI, name: 'setIsBatchPoster' }); const setIsBatchPosterFunctionSelector = getFunctionSelector(setIsBatchPosterABI); -const executeCallABI = getAbiItem({ abi: upgradeExecutor.abi, name: 'executeCall' }); +const executeCallABI = getAbiItem({ abi: upgradeExecutorABI, name: 'executeCall' }); const upgradeExecutorExecuteCallFunctionSelector = getFunctionSelector(executeCallABI); -const execTransactionABI = getAbiItem({ abi: safeL2ABI, name: 'execTransaction' }); +const execTransactionABI = getAbiItem({ abi: gnosisSafeL2ABI, name: 'execTransaction' }); const safeL2FunctionSelector = getFunctionSelector(execTransactionABI); const ownerFunctionCalledEventAbi = getAbiItem({ diff --git a/src/getBatchPosters.unit.test.ts b/src/getBatchPosters.unit.test.ts index 1dd965bf..176d0c23 100644 --- a/src/getBatchPosters.unit.test.ts +++ b/src/getBatchPosters.unit.test.ts @@ -9,7 +9,10 @@ import { } from 'viem'; import { arbitrum, arbitrumSepolia } from 'viem/chains'; import { it, expect, vi, describe } from 'vitest'; -import { safeL2ABI, sequencerInboxABI } from './abi'; + +import { gnosisSafeL2ABI } from './contracts/GnosisSafeL2'; +import { sequencerInboxABI } from './contracts/SequencerInbox'; + import { sequencerInboxPrepareFunctionData } from './sequencerInboxPrepareTransactionRequest'; import { getBatchPosters } from './getBatchPosters'; @@ -123,7 +126,7 @@ function upgradeExecutorSetBatchPosterHelper(args: [Address, boolean]) { function safeSetBatchPosterHelper(args: [Address, boolean]) { const bytes = upgradeExecutorSetBatchPosterHelper(args); return encodeFunctionData({ - abi: safeL2ABI, + abi: gnosisSafeL2ABI, functionName: 'execTransaction', args: [ rollupAddress, diff --git a/src/getKeysets.ts b/src/getKeysets.ts index a1de2a00..56e1e4df 100644 --- a/src/getKeysets.ts +++ b/src/getKeysets.ts @@ -1,5 +1,6 @@ import { Address, Chain, Hex, PublicClient, Transport, getAbiItem } from 'viem'; -import { sequencerInboxABI } from './abi'; + +import { sequencerInboxABI } from './contracts/SequencerInbox'; import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; const SetValidKeysetEventAbi = getAbiItem({ abi: sequencerInboxABI, name: 'SetValidKeyset' }); diff --git a/src/getValidators.ts b/src/getValidators.ts index 24fbae37..9951b4fb 100644 --- a/src/getValidators.ts +++ b/src/getValidators.ts @@ -8,26 +8,27 @@ import { getAbiItem, getFunctionSelector, } from 'viem'; -import { rollupCreator, upgradeExecutor } from './contracts'; -import { rollupAdminLogicABI, safeL2ABI } from './abi'; + +import { rollupCreatorABI } from './contracts/RollupCreator'; +import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; +import { gnosisSafeL2ABI } from './contracts/GnosisSafeL2'; +import { rollupABI } from './contracts/Rollup'; + import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; -const createRollupABI = getAbiItem({ abi: rollupCreator.abi, name: 'createRollup' }); +const createRollupABI = getAbiItem({ abi: rollupCreatorABI, name: 'createRollup' }); const createRollupFunctionSelector = getFunctionSelector(createRollupABI); -const setValidatorABI = getAbiItem({ abi: rollupAdminLogicABI, name: 'setValidator' }); +const setValidatorABI = getAbiItem({ abi: rollupABI, name: 'setValidator' }); const setValidatorFunctionSelector = getFunctionSelector(setValidatorABI); -const executeCallABI = getAbiItem({ abi: upgradeExecutor.abi, name: 'executeCall' }); +const executeCallABI = getAbiItem({ abi: upgradeExecutorABI, name: 'executeCall' }); const upgradeExecutorExecuteCallFunctionSelector = getFunctionSelector(executeCallABI); -const execTransactionABI = getAbiItem({ abi: safeL2ABI, name: 'execTransaction' }); +const execTransactionABI = getAbiItem({ abi: gnosisSafeL2ABI, name: 'execTransaction' }); const safeL2FunctionSelector = getFunctionSelector(execTransactionABI); -const ownerFunctionCalledEventAbi = getAbiItem({ - abi: rollupAdminLogicABI, - name: 'OwnerFunctionCalled', -}); +const ownerFunctionCalledEventAbi = getAbiItem({ abi: rollupABI, name: 'OwnerFunctionCalled' }); function getValidatorsFromFunctionData< TAbi extends (typeof createRollupABI)[] | (typeof setValidatorABI)[], diff --git a/src/getValidators.unit.test.ts b/src/getValidators.unit.test.ts index 18186056..b2b4b987 100644 --- a/src/getValidators.unit.test.ts +++ b/src/getValidators.unit.test.ts @@ -9,8 +9,11 @@ import { } from 'viem'; import { arbitrum, arbitrumSepolia } from 'viem/chains'; import { it, expect, vi, describe } from 'vitest'; + +import { gnosisSafeL2ABI } from './contracts/GnosisSafeL2'; +import { rollupABI } from './contracts/Rollup'; + import { getValidators } from './getValidators'; -import { rollupAdminLogicABI, safeL2ABI } from './abi'; import { rollupAdminLogicPrepareFunctionData } from './rollupAdminLogicPrepareTransactionRequest'; const client = createPublicClient({ @@ -104,7 +107,7 @@ const rollupAddress = '0xe0875cbd144fe66c015a95e5b2d2c15c3b612179'; function setValidatorHelper(args: [Address[], boolean[]]) { return encodeFunctionData({ - abi: rollupAdminLogicABI, + abi: rollupABI, functionName: 'setValidator', args, }); @@ -114,14 +117,14 @@ function upgradeExecutorSetValidatorHelper(args: [Address[], boolean[]]) { rollup: rollupAddress, functionName: 'setValidator', args, - abi: rollupAdminLogicABI, + abi: rollupABI, upgradeExecutor: upgradeExecutorAddress, }).data; } function safeSetValidatorHelper(args: [Address[], boolean[]]) { const bytes = upgradeExecutorSetValidatorHelper(args); return encodeFunctionData({ - abi: safeL2ABI, + abi: gnosisSafeL2ABI, functionName: 'execTransaction', args: [ rollupAddress, diff --git a/src/isAnyTrust.ts b/src/isAnyTrust.ts index 24947371..fdfbebaa 100644 --- a/src/isAnyTrust.ts +++ b/src/isAnyTrust.ts @@ -1,8 +1,8 @@ import { Address, Chain, PublicClient, Transport, decodeFunctionData, getAbiItem } from 'viem'; import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; -import { rollupCreator } from './contracts'; +import { rollupCreatorABI } from './contracts/RollupCreator'; -const createRollupABI = getAbiItem({ abi: rollupCreator.abi, name: 'createRollup' }); +const createRollupABI = getAbiItem({ abi: rollupCreatorABI, name: 'createRollup' }); export async function isAnyTrust({ rollup, publicClient, diff --git a/src/package.json b/src/package.json index 890db794..de763d2e 100644 --- a/src/package.json +++ b/src/package.json @@ -15,10 +15,6 @@ "types": "./dist/chains.d.ts", "default": "./dist/chains.js" }, - "./contracts": { - "types": "./dist/contracts.d.ts", - "default": "./dist/contracts.js" - }, "./utils": { "types": "./dist/utils/index.d.ts", "default": "./dist/utils/index.js" @@ -33,9 +29,6 @@ "chains": [ "./dist/chains.d.ts" ], - "contracts": [ - "./dist/contracts.d.ts" - ], "utils": [ "./dist/utils/index.d.ts" ], diff --git a/src/rollupAdminLogicPrepareTransactionRequest.ts b/src/rollupAdminLogicPrepareTransactionRequest.ts index cbe34e09..59f7260d 100644 --- a/src/rollupAdminLogicPrepareTransactionRequest.ts +++ b/src/rollupAdminLogicPrepareTransactionRequest.ts @@ -7,12 +7,13 @@ import { Chain, } from 'viem'; -import { rollupAdminLogicABI } from './abi/rollupAdminLogicABI'; +import { rollupABI } from './contracts/Rollup'; + import { upgradeExecutorEncodeFunctionData } from './upgradeExecutorEncodeFunctionData'; import { GetFunctionName } from './types/utils'; import { validateParentChainPublicClient } from './types/ParentChain'; -export type RollupAdminLogicAbi = typeof rollupAdminLogicABI; +export type RollupAdminLogicAbi = typeof rollupABI; export type RollupAdminLogicFunctionName = GetFunctionName; type RollupAdminLogicEncodeFunctionDataParameters< @@ -87,7 +88,7 @@ export async function rollupAdminLogicPrepareTransactionRequest< // params is extending RollupAdminLogicPrepareFunctionDataParameters, it's safe to cast const { to, data, value } = rollupAdminLogicPrepareFunctionData({ ...params, - abi: rollupAdminLogicABI, + abi: rollupABI, } as unknown as RollupAdminLogicPrepareFunctionDataParameters); // @ts-ignore (todo: fix viem type issue) diff --git a/src/rollupAdminLogicReadContract.ts b/src/rollupAdminLogicReadContract.ts index 8c0ae01f..a3ca90c2 100644 --- a/src/rollupAdminLogicReadContract.ts +++ b/src/rollupAdminLogicReadContract.ts @@ -7,12 +7,12 @@ import { ReadContractReturnType, Transport, } from 'viem'; +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory'; import { GetFunctionName } from './types/utils'; -import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory'; -import { rollupAdminLogicABI } from './abi/rollupAdminLogicABI'; +import { rollupABI } from './contracts/Rollup'; -export type RollupAdminLogicAbi = typeof rollupAdminLogicABI; +export type RollupAdminLogicAbi = typeof rollupABI; export type RollupAdminLogicFunctionName = GetFunctionName; export type RollupAdminLogicReadContractParameters< diff --git a/src/sequencerInboxPrepareTransactionRequest.ts b/src/sequencerInboxPrepareTransactionRequest.ts index 2e539566..1bbd63e3 100644 --- a/src/sequencerInboxPrepareTransactionRequest.ts +++ b/src/sequencerInboxPrepareTransactionRequest.ts @@ -7,12 +7,12 @@ import { Chain, } from 'viem'; -import { sequencerInbox } from './contracts'; +import { sequencerInboxABI } from './contracts/SequencerInbox'; import { upgradeExecutorEncodeFunctionData } from './upgradeExecutorEncodeFunctionData'; import { GetFunctionName } from './types/utils'; import { validateParentChainPublicClient } from './types/ParentChain'; -export type SequencerInboxAbi = typeof sequencerInbox.abi; +export type SequencerInboxAbi = typeof sequencerInboxABI; export type SequencerInboxFunctionName = GetFunctionName; type SequencerInboxEncodeFunctionDataParameters = @@ -85,7 +85,7 @@ export async function sequencerInboxPrepareTransactionRequest< // params is extending SequencerInboxPrepareFunctionDataParameters, it's safe to cast const { to, data, value } = sequencerInboxPrepareFunctionData({ ...params, - abi: sequencerInbox.abi, + abi: sequencerInboxABI, } as unknown as SequencerInboxPrepareFunctionDataParameters); // @ts-ignore (todo: fix viem type issue) diff --git a/src/sequencerInboxReadContract.ts b/src/sequencerInboxReadContract.ts index 7b2b607d..581fd36d 100644 --- a/src/sequencerInboxReadContract.ts +++ b/src/sequencerInboxReadContract.ts @@ -7,7 +7,7 @@ import { Transport, } from 'viem'; -import { sequencerInbox } from './contracts'; +import { sequencerInboxABI } from './contracts/SequencerInbox'; import { SequencerInboxAbi, SequencerInboxFunctionName, @@ -33,7 +33,7 @@ export function sequencerInboxReadContract< // @ts-ignore (todo: fix viem type issue) return client.readContract({ address: params.sequencerInbox, - abi: sequencerInbox.abi, + abi: sequencerInboxABI, functionName: params.functionName, args: params.args, }); diff --git a/src/setValidKeyset.ts b/src/setValidKeyset.ts index 631b98b4..145089dc 100644 --- a/src/setValidKeyset.ts +++ b/src/setValidKeyset.ts @@ -1,6 +1,6 @@ import { PublicClient, Transport, Chain, WalletClient } from 'viem'; -import { upgradeExecutor } from './contracts'; +import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; import { validateParentChain } from './types/ParentChain'; import { CoreContracts } from './types/CoreContracts'; import { setValidKeysetEncodeFunctionData } from './setValidKeysetEncodeFunctionData'; @@ -28,7 +28,7 @@ export async function setValidKeyset({ // @ts-ignore (todo: fix viem type issue) const { request } = await publicClient.simulateContract({ address: coreContracts.upgradeExecutor, - abi: upgradeExecutor.abi, + abi: upgradeExecutorABI, functionName: 'executeCall', args: [ coreContracts.sequencerInbox, // target diff --git a/src/types/createRollupTypes.ts b/src/types/createRollupTypes.ts index 966e6879..5980fe25 100644 --- a/src/types/createRollupTypes.ts +++ b/src/types/createRollupTypes.ts @@ -1,9 +1,9 @@ import { Address, GetFunctionArgs } from 'viem'; -import { rollupCreator } from '../contracts'; +import { rollupCreatorABI } from '../contracts/RollupCreator'; export type CreateRollupFunctionInputs = GetFunctionArgs< - typeof rollupCreator.abi, + typeof rollupCreatorABI, 'createRollup' >['args']; diff --git a/src/upgradeExecutorEncodeFunctionData.ts b/src/upgradeExecutorEncodeFunctionData.ts index 0b0d43bf..6db426e2 100644 --- a/src/upgradeExecutorEncodeFunctionData.ts +++ b/src/upgradeExecutorEncodeFunctionData.ts @@ -1,5 +1,6 @@ import { encodeFunctionData, EncodeFunctionDataParameters, keccak256, toHex } from 'viem'; -import { upgradeExecutor } from './contracts'; + +import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; import { GetFunctionName, Prettify } from './types/utils'; // Roles @@ -17,7 +18,7 @@ export type UpgradeExecutorRole = | typeof UPGRADE_EXECUTOR_ROLE_EXECUTOR; // Types for upgradeExecutorEncodeFunctionData -export type UpgradeExecutorAbi = typeof upgradeExecutor.abi; +export type UpgradeExecutorAbi = typeof upgradeExecutorABI; export type UpgradeExecutorFunctionName = GetFunctionName; export type UpgradeExecutorEncodeFunctionDataParameters< TFunctionName extends UpgradeExecutorFunctionName, @@ -29,7 +30,7 @@ export function upgradeExecutorEncodeFunctionData< >({ functionName, args }: UpgradeExecutorEncodeFunctionDataParameters) { // @ts-ignore (todo: fix viem type issue) return encodeFunctionData({ - abi: upgradeExecutor.abi, + abi: upgradeExecutorABI, functionName, args, }); diff --git a/src/upgradeExecutorPrepareAddExecutorTransactionRequest.ts b/src/upgradeExecutorPrepareAddExecutorTransactionRequest.ts index 00f0e223..3f1b8106 100644 --- a/src/upgradeExecutorPrepareAddExecutorTransactionRequest.ts +++ b/src/upgradeExecutorPrepareAddExecutorTransactionRequest.ts @@ -6,7 +6,8 @@ import { encodeFunctionData, PrepareTransactionRequestReturnType, } from 'viem'; -import { upgradeExecutor } from './contracts'; + +import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; import { UPGRADE_EXECUTOR_ROLE_EXECUTOR, upgradeExecutorEncodeFunctionData, @@ -59,7 +60,7 @@ export async function upgradeExecutorPrepareAddExecutorTransactionRequest< // 0. Verify that the account doesn't have the EXECUTOR role already const accountHasExecutorRole = await publicClient.readContract({ address: upgradeExecutorAddress, - abi: upgradeExecutor.abi, + abi: upgradeExecutorABI, functionName: 'hasRole', args: [UPGRADE_EXECUTOR_ROLE_EXECUTOR, account], }); @@ -69,7 +70,7 @@ export async function upgradeExecutorPrepareAddExecutorTransactionRequest< // 1. Encode the calldata to be sent in the transaction (through the UpgradeExecutor) const grantRoleCalldata = encodeFunctionData({ - abi: upgradeExecutor.abi, + abi: upgradeExecutorABI, functionName: 'grantRole', args: [ UPGRADE_EXECUTOR_ROLE_EXECUTOR, // role diff --git a/src/upgradeExecutorPrepareRemoveExecutorTransactionRequest.ts b/src/upgradeExecutorPrepareRemoveExecutorTransactionRequest.ts index f4b88507..c0677799 100644 --- a/src/upgradeExecutorPrepareRemoveExecutorTransactionRequest.ts +++ b/src/upgradeExecutorPrepareRemoveExecutorTransactionRequest.ts @@ -6,7 +6,8 @@ import { encodeFunctionData, PrepareTransactionRequestReturnType, } from 'viem'; -import { upgradeExecutor } from './contracts'; + +import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; import { UPGRADE_EXECUTOR_ROLE_EXECUTOR, upgradeExecutorEncodeFunctionData, @@ -59,7 +60,7 @@ export async function upgradeExecutorPrepareRemoveExecutorTransactionRequest< // 0. Verify that the account doesn't have the EXECUTOR role already const accountHasExecutorRole = await publicClient.readContract({ address: upgradeExecutorAddress, - abi: upgradeExecutor.abi, + abi: upgradeExecutorABI, functionName: 'hasRole', args: [UPGRADE_EXECUTOR_ROLE_EXECUTOR, account], }); @@ -69,7 +70,7 @@ export async function upgradeExecutorPrepareRemoveExecutorTransactionRequest< // 1. Encode the calldata to be sent in the transaction (through the UpgradeExecutor) const revokeRoleCalldata = encodeFunctionData({ - abi: upgradeExecutor.abi, + abi: upgradeExecutorABI, functionName: 'revokeRole', args: [ UPGRADE_EXECUTOR_ROLE_EXECUTOR, // role diff --git a/src/utils/erc20.ts b/src/utils/erc20.ts index 989f8563..830f2621 100644 --- a/src/utils/erc20.ts +++ b/src/utils/erc20.ts @@ -1,10 +1,10 @@ import { Address, PublicClient, Transport, Chain, WalletClient, encodeFunctionData } from 'viem'; -import { erc20 } from '../contracts'; +import { erc20ABI } from '../contracts/ERC20'; function approveEncodeFunctionData({ spender, amount }: { spender: Address; amount: bigint }) { return encodeFunctionData({ - abi: erc20.abi, + abi: erc20ABI, functionName: 'approve', args: [spender, amount], }); @@ -59,7 +59,7 @@ export async function approve({ // @ts-ignore (todo: fix viem type issue) const { request } = await publicClient.simulateContract({ address: address, - abi: erc20.abi, + abi: erc20ABI, functionName: 'approve', args: [spender, amount], account, @@ -84,7 +84,7 @@ export async function fetchAllowance({ }: FetchAllowanceProps) { return publicClient.readContract({ address, - abi: erc20.abi, + abi: erc20ABI, functionName: 'allowance', args: [owner, spender], }); @@ -99,7 +99,7 @@ export function fetchDecimals({ }) { return publicClient.readContract({ address, - abi: erc20.abi, + abi: erc20ABI, functionName: 'decimals', }); } diff --git a/src/utils/getters.ts b/src/utils/getters.ts index b9d1eb84..e22fa15f 100644 --- a/src/utils/getters.ts +++ b/src/utils/getters.ts @@ -1,6 +1,7 @@ import { Client, Transport, Chain } from 'viem'; -import { rollupCreator, tokenBridgeCreator } from '../contracts'; +import { rollupCreatorAddress } from '../contracts/RollupCreator'; +import { tokenBridgeCreatorAddress } from '../contracts/TokenBridgeCreator'; import { validateParentChain } from '../types/ParentChain'; export function getRollupCreatorAddress( @@ -8,11 +9,11 @@ export function getRollupCreatorAddress( ) { const chainId = validateParentChain(client); - if (!rollupCreator.address[chainId]) { + if (!rollupCreatorAddress[chainId]) { throw new Error(`Parent chain not supported: ${chainId}`); } - return rollupCreator.address[chainId]; + return rollupCreatorAddress[chainId]; } export function getTokenBridgeCreatorAddress( @@ -20,11 +21,11 @@ export function getTokenBridgeCreatorAddress( ) { const chainId = validateParentChain(client); - if (!tokenBridgeCreator.address[chainId]) { + if (!tokenBridgeCreatorAddress[chainId]) { throw new Error(`Parent chain not supported: ${chainId}`); } - return tokenBridgeCreator.address[chainId]; + return tokenBridgeCreatorAddress[chainId]; } export function getBlockExplorerUrl(chain: Chain) { diff --git a/wagmi.config.ts b/wagmi.config.ts index f0291f0e..23d954f9 100644 --- a/wagmi.config.ts +++ b/wagmi.config.ts @@ -1,3 +1,4 @@ +import { Config } from '@wagmi/cli'; import { erc, etherscan } from '@wagmi/cli/plugins'; import { hashMessage, createPublicClient, http, zeroAddress } from 'viem'; import dotenv from 'dotenv'; @@ -241,30 +242,35 @@ async function updateContractWithImplementationIfProxy(contract: ContractConfig) } export default async function () { - console.log(`Checking if contracts match by comparing hashed JSON ABIs.\n`); + const configs: Config[] = [ + { + out: 'src/contracts/ERC20.ts', + plugins: [erc({ 20: true, 721: false, 4626: false })], + }, + ]; for (const contract of contracts) { await assertContractAbisMatch(contract); await updateContractWithImplementationIfProxy(contract); await sleep(); // sleep to avoid rate limiting - } - console.log(`Done.\n`); + const filePath = + typeof contract.version !== 'undefined' + ? `${contract.name}/v${contract.version}` + : contract.name; + + configs.push({ + out: `src/contracts/${filePath}.ts`, + plugins: [ + etherscan({ + chainId: arbitrumSepolia.id, + apiKey: arbiscanApiKey, + contracts: [contract], + cacheDuration: 0, + }), + ], + }); + } - return { - out: 'src/generated.ts', - plugins: [ - erc({ - 20: true, - 721: false, - 4626: false, - }), - etherscan({ - chainId: arbitrumSepolia.id, - apiKey: arbiscanApiKey, - contracts, - cacheDuration: 0, - }), - ], - }; + return configs; } From 85ded163f161d6f9aba6d59cbe4f7523d9fb2d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20FP?= <105675159+TucksonDev@users.noreply.github.com> Date: Fri, 9 Aug 2024 11:31:16 +0100 Subject: [PATCH 12/54] feat: add AEP fee routing utils with examples (#80) --- examples/setup-aep-fee-router/.env.example | 18 ++ examples/setup-aep-fee-router/README.md | 57 ++++ examples/setup-aep-fee-router/index.ts | 283 ++++++++++++++++++ examples/setup-aep-fee-router/package.json | 13 + examples/setup-aep-fee-router/tsconfig.json | 4 + .../.env.example | 24 ++ .../setup-fee-distributor-contract/README.md | 50 ++++ .../setup-fee-distributor-contract/index.ts | 174 +++++++++++ .../package.json | 13 + .../tsconfig.json | 4 + src/feeRouter.integration.test.ts | 135 +++++++++ ...eeRouterDeployChildToParentRewardRouter.ts | 153 ++++++++++ src/feeRouterDeployRewardDistributor.ts | 80 +++++ src/index.ts | 15 + src/package.json | 1 + yarn.lock | 23 +- 16 files changed, 1046 insertions(+), 1 deletion(-) create mode 100644 examples/setup-aep-fee-router/.env.example create mode 100644 examples/setup-aep-fee-router/README.md create mode 100644 examples/setup-aep-fee-router/index.ts create mode 100644 examples/setup-aep-fee-router/package.json create mode 100644 examples/setup-aep-fee-router/tsconfig.json create mode 100644 examples/setup-fee-distributor-contract/.env.example create mode 100644 examples/setup-fee-distributor-contract/README.md create mode 100644 examples/setup-fee-distributor-contract/index.ts create mode 100644 examples/setup-fee-distributor-contract/package.json create mode 100644 examples/setup-fee-distributor-contract/tsconfig.json create mode 100644 src/feeRouter.integration.test.ts create mode 100644 src/feeRouterDeployChildToParentRewardRouter.ts create mode 100644 src/feeRouterDeployRewardDistributor.ts diff --git a/examples/setup-aep-fee-router/.env.example b/examples/setup-aep-fee-router/.env.example new file mode 100644 index 00000000..e78b34e4 --- /dev/null +++ b/examples/setup-aep-fee-router/.env.example @@ -0,0 +1,18 @@ +# Address of the Rollup contract +ROLLUP_ADDRESS= + +# Private key of the account with executor privileges in the UpgradeExecutor admin contract for the chain +# (usually, the deployer of the chain) +CHAIN_OWNER_PRIVATE_KEY= + +# Orbit chain configuration +ORBIT_CHAIN_ID= +ORBIT_CHAIN_RPC= + +# Parent chain id +PARENT_CHAIN_ID=1 + +# Parent chain target address. It will receive 10% of the chain revenue on L1 +# NOTE: This is the ParentToChildRewardRouter contract on Ethereum (https://etherscan.io/address/0x40Cd7D713D7ae463f95cE5d342Ea6E7F5cF7C999) +# that bridges the funds received to the Arbitrum Foundation Treasury Timelock contract on Arbitrum One (https://arbiscan.io/address/0xbFc1FECa8B09A5c5D3EFfE7429eBE24b9c09EF58) +PARENT_CHAIN_TARGET_ADDRESS=0x40Cd7D713D7ae463f95cE5d342Ea6E7F5cF7C999 \ No newline at end of file diff --git a/examples/setup-aep-fee-router/README.md b/examples/setup-aep-fee-router/README.md new file mode 100644 index 00000000..d57dc002 --- /dev/null +++ b/examples/setup-aep-fee-router/README.md @@ -0,0 +1,57 @@ +# Arbitrum Orbit SDK + +## Setup fee routing for Orbit chains settling to non-Arbitrum chains (including Ethereum) + +This example script shows how to setup the appropriate fee routing to comply with the [Arbitrum Expansion Program](https://forum.arbitrum.foundation/t/the-arbitrum-expansion-program-and-developer-guild/20722) requirement of sharing 10% of the revenue back to the Arbitrum ecosystem. + +The script performs the following operations: + +1. Obtain all chain contracts (needed to execute the next steps) +2. Obtain the current fee collectors of the chain: Orbit base fee collector, Orbit surplus fee collector, Parent chain surplus fee collector +3. Deploy the ChildToParentRouter contract, configured to send the amounts received to the appropriate Arbitrum Foundation or Arbitrum DAO controlled address on the parent chain +4. Deploy a RewardDistributor contract for each different fee collector account, configured to distribute 90% of the amounts received to the current fee collector, and 10% to the ChildToParentRouter contract +5. Set each of the fee collectors to the RewardDistributor contracts + +Note that if all three fee types are collected by the same address, only one RewardDistributor contract will be deployed that will collect all those fees. + +## Variables needed + +- ROLLUP_ADDRESS: address of the Rollup contract +- CHAIN_OWNER_PRIVATE_KEY: private key of the account with executor privileges in the UpgradeExecutor admin contract for the chain +- ORBIT_CHAIN_ID: chainId of the Orbit chain +- ORBIT_CHAIN_RPC: RPC of the Orbit chain +- PARENT_CHAIN_ID: chainId of the parent chain (should be a non-Arbitrum chain, including Ethereum) +- PARENT_CHAIN_TARGET_ADDRESS: address on the parent chain where 10% of the revenue will be sent to (more information below) + +### What PARENT_CHAIN_TARGET_ADDRESS to use + +When executing this script, the RewardDistributor contract will be configured to send 10% of the funds received (10% of the revenue of the chain) to the address specified in PARENT_CHAIN_TARGET_ADDRESS, in the parent chain. + +The PARENT_CHAIN_TARGET_ADDRESS should be an address controlled by the Arbitrum Foundation or the Arbitrum DAO. For L2 Orbit chains settling to Ethereum that use ETH as the native gas token, this variable should be `0x40Cd7D713D7ae463f95cE5d342Ea6E7F5cF7C999`, which is a ParentToChildRewardRouter contract that sends its balance in ETH to the Arbitrum Foundation Treasury Timelock contract on Arbitrum One. + +If your chain is an L2 Orbit chain that uses a different native gas token, or if it is an L3 Orbit chain that settles to a non-Arbitrum chain, you should set PARENT_CHAIN_TARGET_ADDRESS to a different address. Please reach out to the Arbitrum Foundation to get the appropriate address. + +## Setup + +1. Install dependencies + + ```bash + yarn install + ``` + +2. Create .env file and add the env vars + + ```bash + cp .env.example .env + ``` + +3. Run the example + ```bash + yarn dev + ``` + +## References + +- [Arbitrum Expansion Program governance forum post](https://forum.arbitrum.foundation/t/the-arbitrum-expansion-program-and-developer-guild/20722) +- [ChildToParentRouter contract](https://github.com/OffchainLabs/fund-distribution-contracts/blob/main/src/FeeRouter/ChildToParentRewardRouter.sol) +- [RewardDistributor contract](https://github.com/OffchainLabs/fund-distribution-contracts/blob/main/src/RewardDistributor.sol) diff --git a/examples/setup-aep-fee-router/index.ts b/examples/setup-aep-fee-router/index.ts new file mode 100644 index 00000000..6d126b78 --- /dev/null +++ b/examples/setup-aep-fee-router/index.ts @@ -0,0 +1,283 @@ +import { + createPublicClient, + createWalletClient, + http, + defineChain, + parseAbi, + getAddress, +} from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { + feeRouterDeployChildToParentRewardRouter, + feeRouterDeployRewardDistributor, + createRollupFetchCoreContracts, + createTokenBridgeFetchTokenBridgeContracts, + arbOwnerPublicActions, + arbGasInfoPublicActions, + parentChainIsArbitrum, +} from '@arbitrum/orbit-sdk'; +import { sanitizePrivateKey, getParentChainFromId } from '@arbitrum/orbit-sdk/utils'; +import { config } from 'dotenv'; +config(); + +// environent variables check +if ( + typeof process.env.ROLLUP_ADDRESS === 'undefined' || + typeof process.env.CHAIN_OWNER_PRIVATE_KEY === 'undefined' || + typeof process.env.ORBIT_CHAIN_ID === 'undefined' || + typeof process.env.ORBIT_CHAIN_RPC === 'undefined' || + typeof process.env.PARENT_CHAIN_ID === 'undefined' || + typeof process.env.PARENT_CHAIN_TARGET_ADDRESS === 'undefined' +) { + throw new Error( + `Please provide the following environment variables: ROLLUP_ADDRESS, CHAIN_OWNER_PRIVATE_KEY, ORBIT_CHAIN_ID, ORBIT_CHAIN_RPC, PARENT_CHAIN_ID, PARENT_CHAIN_TARGET_ADDRESS.`, + ); +} + +// load the chain owner account (or any account that has the executor role in the UpgradeExecutor) +const chainOwner = privateKeyToAccount(sanitizePrivateKey(process.env.CHAIN_OWNER_PRIVATE_KEY)); + +// set the parent chain and create a public client for it +const parentChain = getParentChainFromId(Number(process.env.PARENT_CHAIN_ID)); +const parentChainPublicClient = createPublicClient({ + chain: parentChain, + transport: http(), +}); + +// define chain config for the orbit chain +const orbitChain = defineChain({ + id: Number(process.env.ORBIT_CHAIN_ID), + network: 'Orbit chain', + name: 'orbit', + nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, + rpcUrls: { + default: { + http: [process.env.ORBIT_CHAIN_RPC], + }, + public: { + http: [process.env.ORBIT_CHAIN_RPC], + }, + }, + testnet: true, +}); +const orbitChainPublicClient = createPublicClient({ chain: orbitChain, transport: http() }) + .extend(arbOwnerPublicActions) + .extend(arbGasInfoPublicActions); +const orbitChainWalletClient = createWalletClient({ + chain: orbitChain, + transport: http(), + account: chainOwner, +}); + +// Parent chain target address. It will receive 10% of the chain revenue on L1. +const parentChainTargetAddress = getAddress(process.env.PARENT_CHAIN_TARGET_ADDRESS); + +async function main() { + // Verify that this is an orbit chain settling to a non-Arbitrum chain + if (parentChainIsArbitrum(parentChainPublicClient.chain.id)) { + throw new Error( + 'This script is intended to be used only by Orbit chains settling to non Arbitrum chains.', + ); + } + + // Step 0. Collect information + // (We need to obtain all chain contracts and the current fee collectors of all fee types) + // --------------------------- + + // getting all chain contracts + const rollupCoreContracts = await createRollupFetchCoreContracts({ + rollup: process.env.ROLLUP_ADDRESS as `0x${string}`, + publicClient: parentChainPublicClient, + }); + + const inbox = await parentChainPublicClient.readContract({ + address: rollupCoreContracts.rollup, + abi: parseAbi(['function inbox() view returns (address)']), + functionName: 'inbox', + }); + const tokenBridgeContracts = await createTokenBridgeFetchTokenBridgeContracts({ + inbox, + parentChainPublicClient, + }); + + // getting Orbit base fee collector (infraFeeAccount) + const infraFeeAccount = await orbitChainPublicClient.arbOwnerReadContract({ + functionName: 'getInfraFeeAccount', + }); + + // getting Orbit surplus fee collector (networkFeeAccount) + const networkFeeAccount = await orbitChainPublicClient.arbOwnerReadContract({ + functionName: 'getNetworkFeeAccount', + }); + + // getting parent chain surplus fee collector (L1RewardRecipient) + // Note: Arbiscan (Sepolia) doesn't have the updated ABI for ArbGasInfo, so we need to + // fetch the reward recipient this way + const parentChainRewardRecipient = await orbitChainPublicClient.readContract({ + address: '0x000000000000000000000000000000000000006C', + abi: parseAbi(['function getL1RewardRecipient() view returns (address)']), + functionName: 'getL1RewardRecipient', + }); + + // Step 1. Deploy the ChildToParentRouter + // (This contract will transfer the amounts received by the contract to a specific address in the parent chain) + // -------------------------------------- + console.log('Deploying contract ChildToParentRouter...'); + const childToParentRouterDeploymentTransactionHash = + await feeRouterDeployChildToParentRewardRouter({ + parentChainPublicClient, + orbitChainWalletClient, + parentChainTargetAddress, + }); + + const childToParentRouterDeploymentTransactionReceipt = + await orbitChainPublicClient.waitForTransactionReceipt({ + hash: childToParentRouterDeploymentTransactionHash, + }); + + if (!childToParentRouterDeploymentTransactionReceipt.contractAddress) { + throw new Error('ChildToParentRouter was not successfully deployed.'); + } + + const childToParentRouterAddress = getAddress( + childToParentRouterDeploymentTransactionReceipt.contractAddress, + ); + console.log(`ChildToParentRouter contract deployed at ${childToParentRouterAddress}`); + console.log(''); + + // Step 2. Deploy a RewardDistributor for each distinct fee collector + // + // These contracts will distribute the amounts received by them to the configured recipients + // Each contract will have the following recipients configured: + // - Previous fee collector, to receive 90% of the amount + // - Deployed childToParentRouter, to receive 10% of the amount + // ------------------------------------ + const feeCollectors = [ + ...new Set([infraFeeAccount, networkFeeAccount, parentChainRewardRecipient]), + ]; + const feeCollectorToRewardDistributor: { [key: `0x${string}`]: `0x${string}` } = {}; + + for await (const feeCollector of feeCollectors) { + const recipients = [ + { + account: feeCollector, + weight: 9000n, + }, + { + account: childToParentRouterAddress, + weight: 1000n, + }, + ]; + console.log('Deploying RewardDistributor contract...'); + const rewardDistributorDeploymentTransactionHash = await feeRouterDeployRewardDistributor({ + orbitChainWalletClient, + recipients, + }); + + const rewardDistributorDeploymentTransactionReceipt = + await orbitChainPublicClient.waitForTransactionReceipt({ + hash: rewardDistributorDeploymentTransactionHash, + }); + + if (!rewardDistributorDeploymentTransactionReceipt.contractAddress) { + throw new Error('RewardDistributor was not successfully deployed.'); + } + + const rewardDistributorAddress = getAddress( + rewardDistributorDeploymentTransactionReceipt.contractAddress, + ); + console.log(`RewardDistributor contract deployed at ${rewardDistributorAddress}`); + console.log(''); + + feeCollectorToRewardDistributor[feeCollector] = rewardDistributorAddress; + } + + // Step 3. Set the fee collectors to the new RewardDistributor contracts + // ----------------------------------------------------------------------------- + console.log('Setting the RewardDistributors as the fee new collectors...'); + + // setting Orbit base fee collector (infraFeeAccount) + const setOrbitBaseFeeCollectorTransactionRequest = + await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({ + functionName: 'setInfraFeeAccount', + args: [feeCollectorToRewardDistributor[infraFeeAccount]], + upgradeExecutor: tokenBridgeContracts.orbitChainContracts.upgradeExecutor, + account: chainOwner.address, + }); + await orbitChainPublicClient.sendRawTransaction({ + serializedTransaction: await chainOwner.signTransaction( + setOrbitBaseFeeCollectorTransactionRequest, + ), + }); + + // setting Orbit surplus fee collector (networkFeeAccount) + const setOrbitSurplusFeeCollectorTransactionRequest = + await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({ + functionName: 'setNetworkFeeAccount', + args: [feeCollectorToRewardDistributor[networkFeeAccount]], + upgradeExecutor: tokenBridgeContracts.orbitChainContracts.upgradeExecutor, + account: chainOwner.address, + }); + await orbitChainPublicClient.sendRawTransaction({ + serializedTransaction: await chainOwner.signTransaction( + setOrbitSurplusFeeCollectorTransactionRequest, + ), + }); + + // setting parent chain surplus fee collector (L1RewardRecipient) + const setParentChainSurplusFeeCollectorTransactionRequest = + await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({ + functionName: 'setL1PricingRewardRecipient', + args: [feeCollectorToRewardDistributor[parentChainRewardRecipient]], + upgradeExecutor: tokenBridgeContracts.orbitChainContracts.upgradeExecutor, + account: chainOwner.address, + }); + await orbitChainPublicClient.sendRawTransaction({ + serializedTransaction: await chainOwner.signTransaction( + setParentChainSurplusFeeCollectorTransactionRequest, + ), + }); + + // checking that the fee collectors were correctly set + const currentInfraFeeAccount = await orbitChainPublicClient.arbOwnerReadContract({ + functionName: 'getInfraFeeAccount', + }); + if (currentInfraFeeAccount != feeCollectorToRewardDistributor[infraFeeAccount]) { + throw new Error( + `Orbit base fee collector was not correctly set. It is now set to ${currentInfraFeeAccount}`, + ); + } + console.log( + `Orbit base fee collector correctly set to the RewardDistributor contract ${currentInfraFeeAccount}`, + ); + + const currentNetworkFeeAccount = await orbitChainPublicClient.arbOwnerReadContract({ + functionName: 'getNetworkFeeAccount', + }); + if (currentNetworkFeeAccount != feeCollectorToRewardDistributor[networkFeeAccount]) { + throw new Error( + `Orbit surplus fee collector was not correctly set. It is now set to ${currentNetworkFeeAccount}`, + ); + } + console.log( + `Orbit surplus fee collector correctly set to the RewardDistributor contract ${currentNetworkFeeAccount}`, + ); + + const currentParentChainRewardRecipient = await orbitChainPublicClient.readContract({ + address: '0x000000000000000000000000000000000000006C', + abi: parseAbi(['function getL1RewardRecipient() view returns (address)']), + functionName: 'getL1RewardRecipient', + }); + if ( + currentParentChainRewardRecipient != feeCollectorToRewardDistributor[parentChainRewardRecipient] + ) { + throw new Error( + `Parent chain surplus fee collector was not correctly set. It is now set to ${currentParentChainRewardRecipient}`, + ); + } + console.log( + `Parent chain surplus fee collector correctly set to the RewardDistributor contract ${currentParentChainRewardRecipient}`, + ); +} + +main(); diff --git a/examples/setup-aep-fee-router/package.json b/examples/setup-aep-fee-router/package.json new file mode 100644 index 00000000..011a2cd6 --- /dev/null +++ b/examples/setup-aep-fee-router/package.json @@ -0,0 +1,13 @@ +{ + "name": "setup-aep-fee-router", + "private": true, + "version": "0.1.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/setup-aep-fee-router/tsconfig.json b/examples/setup-aep-fee-router/tsconfig.json new file mode 100644 index 00000000..abf0a90d --- /dev/null +++ b/examples/setup-aep-fee-router/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.base.json", + "include": ["./**/*"] +} diff --git a/examples/setup-fee-distributor-contract/.env.example b/examples/setup-fee-distributor-contract/.env.example new file mode 100644 index 00000000..da330785 --- /dev/null +++ b/examples/setup-fee-distributor-contract/.env.example @@ -0,0 +1,24 @@ +# Address of the Rollup contract +ROLLUP_ADDRESS= + +# Private key of the account with executor privileges in the UpgradeExecutor admin contract for the chain +# (usually, the deployer of the chain) +CHAIN_OWNER_PRIVATE_KEY= + +# Orbit chain configuration +ORBIT_CHAIN_ID= +ORBIT_CHAIN_RPC= + +# Parent chain id +PARENT_CHAIN_ID=421614 + +# The RewardDistributor contract will distribute the amounts received among the recipients configured here, +# based on the weight of each recipient. For example, if one recipient has a weight of 75%, they will receive +# 75% of the amount held in the contract at the time of distribution. +# +# Weights are expressed in percentages multiplied by 100. For example, to allocate 12,5% of the amount to +# a specific recipient, you'll define the weight as 1250. To allocate 80%, you'll define the weight as 8000. +# +# You can configure as many recipients as you wish. +RECIPIENT_ADDRESSES=["0x1234567890123456789012345678901234567890", "0x1234567890123456789012345678901234567890"] +RECIPIENT_WEIGHTS=[7500, 2500] diff --git a/examples/setup-fee-distributor-contract/README.md b/examples/setup-fee-distributor-contract/README.md new file mode 100644 index 00000000..716556f9 --- /dev/null +++ b/examples/setup-fee-distributor-contract/README.md @@ -0,0 +1,50 @@ +# Arbitrum Orbit SDK + +## Setup fee distributor contract + +By default, individual addresses are set to collect each of the fee types of an Orbit chain. However, some chains may require multiple addresses to receive the collected fees of any of the available types. In those cases, there's the possibility of using a distributor contract that can gather all fees of a specific type and distribute those among multiple addresses. + +This example shows how to configure a distributor contract to manage the Orbit base fees of a chain. You can also use this same example to configure additional distributor contracts to manage other fee types. + +You can find more information about the different fee types, and how to configure other fee types in [How to manage fee collector addresses](https://docs.arbitrum.io/launch-orbit-chain/how-tos/manage-fee-collectors) + +## Variables needed + +- ROLLUP_ADDRESS: address of the Rollup contract +- CHAIN_OWNER_PRIVATE_KEY: private key of the account with executor privileges in the UpgradeExecutor admin contract for the chain +- ORBIT_CHAIN_ID: chainId of the Orbit chain +- ORBIT_CHAIN_RPC: RPC of the Orbit chain +- PARENT_CHAIN_ID: chainId of the parent chain +- RECIPIENT_ADDRESSES: Array of addresses to configure in the distributor contract +- RECIPIENT_WEIGHTS: Array of weights of each of the configured addresses + +## How to configure the distribution addresses in the .env file + +The .env file contains two arrays: RECIPIENT_ADDRESSES and RECIPIENT_WEIGHTS. The first one will have the addresses that will receive the amounts that the distributor contract receives. The second one will define the weights of each of those addresses. For example, if one recipient has a weight of 75%, they will receive 75% of the amount held in the contract at the time of distribution. Both arrays must have the same length. + +Weights are expressed in percentages multiplied by 100. For example, to allocate 12,5% of the amount to a specific recipient, you'll define the weight as 1250. To allocate 80%, you'll define the weight as 8000. + +You can configure as many recipients as you wish. + +## Setup + +1. Install dependencies + + ```bash + yarn install + ``` + +2. Create .env file and add the env vars + + ```bash + cp .env.example .env + ``` + +3. Run the example + ```bash + yarn dev + ``` + +## References + +- [How to manage fee collector addresses](https://docs.arbitrum.io/launch-orbit-chain/how-tos/manage-fee-collectors) diff --git a/examples/setup-fee-distributor-contract/index.ts b/examples/setup-fee-distributor-contract/index.ts new file mode 100644 index 00000000..38069a3f --- /dev/null +++ b/examples/setup-fee-distributor-contract/index.ts @@ -0,0 +1,174 @@ +import { + createPublicClient, + createWalletClient, + http, + defineChain, + parseAbi, + getAddress, +} from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { + feeRouterDeployRewardDistributor, + createRollupFetchCoreContracts, + createTokenBridgeFetchTokenBridgeContracts, + arbOwnerPublicActions, +} from '@arbitrum/orbit-sdk'; +import { getParentChainFromId, sanitizePrivateKey } from '@arbitrum/orbit-sdk/utils'; +import { config } from 'dotenv'; +config(); + +// environent variables check +if ( + typeof process.env.ROLLUP_ADDRESS === 'undefined' || + typeof process.env.CHAIN_OWNER_PRIVATE_KEY === 'undefined' || + typeof process.env.ORBIT_CHAIN_ID === 'undefined' || + typeof process.env.ORBIT_CHAIN_RPC === 'undefined' || + typeof process.env.PARENT_CHAIN_ID === 'undefined' || + typeof process.env.RECIPIENT_ADDRESSES === 'undefined' || + typeof process.env.RECIPIENT_WEIGHTS === 'undefined' +) { + throw new Error( + `Please provide the following environment variables: ROLLUP_ADDRESS, CHAIN_OWNER_PRIVATE_KEY, ORBIT_CHAIN_ID, ORBIT_CHAIN_RPC, PARENT_CHAIN_ID, RECIPIENT_ADDRESSES, RECIPIENT_WEIGHTS.`, + ); +} + +// load the chain owner account (or any account that has the executor role in the UpgradeExecutor) +const chainOwner = privateKeyToAccount(sanitizePrivateKey(process.env.CHAIN_OWNER_PRIVATE_KEY)); + +// set the parent chain and create a public client for it +const parentChain = getParentChainFromId(Number(process.env.PARENT_CHAIN_ID)); +const parentChainPublicClient = createPublicClient({ + chain: parentChain, + transport: http(), +}); + +// define chain config for the orbit chain +const orbitChain = defineChain({ + id: Number(process.env.ORBIT_CHAIN_ID), + network: 'Orbit chain', + name: 'orbit', + nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, + rpcUrls: { + default: { + http: [process.env.ORBIT_CHAIN_RPC], + }, + public: { + http: [process.env.ORBIT_CHAIN_RPC], + }, + }, + testnet: true, +}); +const orbitChainPublicClient = createPublicClient({ chain: orbitChain, transport: http() }).extend( + arbOwnerPublicActions, +); +const orbitChainWalletClient = createWalletClient({ + chain: orbitChain, + transport: http(), + account: chainOwner, +}); + +async function main() { + // Step 0. Collect information + // (We need to obtain the upgrade executor contract for setting the fee collector in the last step) + // --------------------------- + + // getting all chain contracts + const rollupCoreContracts = await createRollupFetchCoreContracts({ + rollup: process.env.ROLLUP_ADDRESS as `0x${string}`, + publicClient: parentChainPublicClient, + }); + + const inbox = await parentChainPublicClient.readContract({ + address: rollupCoreContracts.rollup, + abi: parseAbi(['function inbox() view returns (address)']), + functionName: 'inbox', + }); + const tokenBridgeContracts = await createTokenBridgeFetchTokenBridgeContracts({ + inbox, + parentChainPublicClient, + }); + + // Step 1. Define the recipients of the fees + // + // The RewardDistributor contract will distribute the amounts received among the recipients configured here, + // based on the weight of each recipient. For example, if one recipient has a weight of 75%, they will receive + // 75% of the amount held in the contract at the time of distribution. + // + // Weights are expressed in percentages multiplied by 100. For example, to allocate 12,5% of the amount to + // a specific recipient, you'll define the weight as 1250. To allocate 80%, you'll define the weight as 8000. + // + // You can configure as many recipients as you wish in the .env file + // --------------------------- + const recipientAddresses = JSON.parse(process.env.RECIPIENT_ADDRESSES!); + const recipientWeights = JSON.parse(process.env.RECIPIENT_WEIGHTS!); + + if (recipientAddresses.length != recipientWeights.length) { + throw new Error( + `Env variables RECIPIENT_ADDRESSES and RECIPIENT_WEIGHTS must have the same length.`, + ); + } + + const recipients = recipientAddresses.map((address: `0x${string}`, index: number) => ({ + account: address as `0x${string}`, + weight: BigInt(recipientWeights[index]), + })); + + // Step 2. Deploy the RewardDistributor + // + // This contract will distribute the amounts received by the contract to the configured recipients + // ------------------------------------ + console.log('Deploying RewardDistributor contract...'); + const rewardDistributorDeploymentTransactionHash = await feeRouterDeployRewardDistributor({ + orbitChainWalletClient, + recipients, + }); + + const rewardDistributorDeploymentTransactionReceipt = + await orbitChainPublicClient.waitForTransactionReceipt({ + hash: rewardDistributorDeploymentTransactionHash, + }); + + if (!rewardDistributorDeploymentTransactionReceipt.contractAddress) { + throw new Error('RewardDistributor was not successfully deployed.'); + } + + const rewardDistributorAddress = getAddress( + rewardDistributorDeploymentTransactionReceipt.contractAddress, + ); + console.log(`RewardDistributor contract deployed at ${rewardDistributorAddress}`); + console.log(''); + + // Step 3. Set the appropriate fee collector account to the RewardDistributor + // + // In this example, we will set the infraFeeAccount (the account that receives the fees corresponding to + // the Orbit chain's execution gas) + // + // However, you can set the RewardDistributor as the collector of any of the fee types. You can find more + // information about the different fee collectors in [How to manage fee collectors](https://docs.arbitrum.io/launch-orbit-chain/how-tos/manage-fee-collectors) + // -------------------------------------------------------------------------- + console.log( + 'Setting the RewardDistributor as the collector of the Orbit chain execution fees...', + ); + const setFeeCollectorTransactionRequest = + await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({ + functionName: 'setInfraFeeAccount', + args: [rewardDistributorAddress], + upgradeExecutor: tokenBridgeContracts.orbitChainContracts.upgradeExecutor, + account: chainOwner.address, + }); + + await orbitChainPublicClient.sendRawTransaction({ + serializedTransaction: await chainOwner.signTransaction(setFeeCollectorTransactionRequest), + }); + + // checking that the fee collector was correctly set + const currentFeeCollector = await orbitChainPublicClient.arbOwnerReadContract({ + functionName: 'getInfraFeeAccount', + }); + if (currentFeeCollector != rewardDistributorAddress) { + throw new Error(`Fee collector was not correctly set. It is now set to ${currentFeeCollector}`); + } + console.log('Fee collector correctly set to the RewardDistributor contract'); +} + +main(); diff --git a/examples/setup-fee-distributor-contract/package.json b/examples/setup-fee-distributor-contract/package.json new file mode 100644 index 00000000..58c51da1 --- /dev/null +++ b/examples/setup-fee-distributor-contract/package.json @@ -0,0 +1,13 @@ +{ + "name": "setup-fee-distributor-contract", + "private": true, + "version": "0.1.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/setup-fee-distributor-contract/tsconfig.json b/examples/setup-fee-distributor-contract/tsconfig.json new file mode 100644 index 00000000..abf0a90d --- /dev/null +++ b/examples/setup-fee-distributor-contract/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.base.json", + "include": ["./**/*"] +} diff --git a/src/feeRouter.integration.test.ts b/src/feeRouter.integration.test.ts new file mode 100644 index 00000000..a0073220 --- /dev/null +++ b/src/feeRouter.integration.test.ts @@ -0,0 +1,135 @@ +import { describe, it, expect } from 'vitest'; +import { + createPublicClient, + http, + createWalletClient, + getAddress, + parseAbi, + encodePacked, + keccak256, + pad, +} from 'viem'; +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; + +import { nitroTestnodeL1, nitroTestnodeL2 } from './chains'; +import { getNitroTestnodePrivateKeyAccounts } from './testHelpers'; +import { feeRouterDeployChildToParentRewardRouter } from './feeRouterDeployChildToParentRewardRouter'; +import { feeRouterDeployRewardDistributor } from './feeRouterDeployRewardDistributor'; + +const testnodeAccounts = getNitroTestnodePrivateKeyAccounts(); +const deployer = testnodeAccounts.deployer; +const randomAccount = privateKeyToAccount(generatePrivateKey()); +const randomAccount2 = privateKeyToAccount(generatePrivateKey()); + +const nitroTestnodeL1Client = createPublicClient({ + chain: nitroTestnodeL1, + transport: http(nitroTestnodeL1.rpcUrls.default.http[0]), +}); + +const nitroTestnodeL2Client = createPublicClient({ + chain: nitroTestnodeL2, + transport: http(nitroTestnodeL2.rpcUrls.default.http[0]), +}); +const nitroTestnodeL2WalletClient = createWalletClient({ + chain: nitroTestnodeL2, + transport: http(nitroTestnodeL2.rpcUrls.default.http[0]), + account: deployer, +}); + +describe('Fee routing tests', () => { + it(`successfully deploys and configures the ChildToParentRewardRouter`, async () => { + const childToParentRewardRouterDeploymentTransactionHash = + await feeRouterDeployChildToParentRewardRouter({ + parentChainPublicClient: nitroTestnodeL1Client, + orbitChainWalletClient: nitroTestnodeL2WalletClient, + parentChainTargetAddress: randomAccount.address, + }); + + const childToParentRewardRouterDeploymentTransactionReceipt = + await nitroTestnodeL2Client.waitForTransactionReceipt({ + hash: childToParentRewardRouterDeploymentTransactionHash, + }); + + expect(childToParentRewardRouterDeploymentTransactionReceipt).to.have.property( + 'contractAddress', + ); + + const childToParentRewardRouterAddress = getAddress( + childToParentRewardRouterDeploymentTransactionReceipt.contractAddress as `0x${string}`, + ); + + // reading the parentChainTarget + const parentChainTarget = await nitroTestnodeL2Client.readContract({ + address: childToParentRewardRouterAddress, + abi: parseAbi(['function parentChainTarget() view returns (address)']), + functionName: 'parentChainTarget', + }); + + expect(parentChainTarget).toEqual(randomAccount.address); + }); + + it(`successfully deploys and configures the RewardDistributor`, async () => { + const recipients = [ + { + account: randomAccount.address, + weight: 9000n, + }, + { + account: randomAccount2.address, + weight: 1000n, + }, + ]; + const rewardDistributorDeploymentTransactionHash = await feeRouterDeployRewardDistributor({ + orbitChainWalletClient: nitroTestnodeL2WalletClient, + recipients, + }); + + const rewardDistributorDeploymentTransactionReceipt = + await nitroTestnodeL2Client.waitForTransactionReceipt({ + hash: rewardDistributorDeploymentTransactionHash, + }); + + expect(rewardDistributorDeploymentTransactionReceipt).to.have.property('contractAddress'); + + const rewardDistributorAddress = getAddress( + rewardDistributorDeploymentTransactionReceipt.contractAddress as `0x${string}`, + ); + + // hashing the recipient addresses + // keccak256(abi.encodePacked(addresses)) + // Note: we need to pad the addresses to 32-bytes, since the packing in Solidity is done that way + const recipientGroup = keccak256( + encodePacked( + ['bytes32', 'bytes32'], + [ + pad(randomAccount.address, { + size: 32, + }), + pad(randomAccount2.address, { + size: 32, + }), + ], + ), + ); + + // hashing the weights + // keccak256(abi.encodePacked(addresses)) + const recipientWeights = keccak256(encodePacked(['uint256', 'uint256'], [9000n, 1000n])); + + // reading the currentRecipientGroup and currentRecipientWeights + const currentRecipientGroup = await nitroTestnodeL2Client.readContract({ + address: rewardDistributorAddress, + abi: parseAbi(['function currentRecipientGroup() view returns (bytes32)']), + functionName: 'currentRecipientGroup', + }); + + const currentRecipientWeights = await nitroTestnodeL2Client.readContract({ + address: rewardDistributorAddress, + abi: parseAbi(['function currentRecipientWeights() view returns (bytes32)']), + functionName: 'currentRecipientWeights', + }); + + expect(currentRecipientGroup).toEqual(recipientGroup); + expect(currentRecipientWeights).toEqual(recipientWeights); + }); +}); diff --git a/src/feeRouterDeployChildToParentRewardRouter.ts b/src/feeRouterDeployChildToParentRewardRouter.ts new file mode 100644 index 00000000..40dc9ffe --- /dev/null +++ b/src/feeRouterDeployChildToParentRewardRouter.ts @@ -0,0 +1,153 @@ +import { + Address, + Chain, + PublicClient, + Transport, + WalletClient, + getAddress, + pad, + parseAbi, +} from 'viem'; + +import arbChildToParentRewardRouter from '@offchainlabs/fund-distribution-contracts/out/ArbChildToParentRewardRouter.sol/ArbChildToParentRewardRouter.json'; + +import { createTokenBridgeFetchTokenBridgeContracts } from './createTokenBridgeFetchTokenBridgeContracts'; +import { Prettify } from './types/utils'; +import { validateParentChain } from './types/ParentChain'; +import { WithTokenBridgeCreatorAddressOverride } from './types/createTokenBridgeTypes'; + +/** + * This type is for the params of the feeRouterDeployChildToParentRewardRouter function + */ +export type FeeRouterDeployChildToParentRewardRouterParams = + Prettify< + WithTokenBridgeCreatorAddressOverride<{ + parentChainPublicClient: PublicClient; + orbitChainWalletClient: WalletClient; + parentChainTargetAddress: Address; + minDistributionInvervalSeconds?: bigint; + rollup?: Address; + parentChainTokenAddress?: Address; + }> + >; + +// Default minimum distribution interval seconds +const DEFAULT_MIN_DISTRIBUTION_INVERVAL_SECONDS = BigInt(60 * 60 * 24 * 7); // 1 week + +// Default address 1 +const oneAddress = getAddress( + pad('0x1', { + size: 20, + }), +); + +/** + * Deploys the ArbChildToParentRewardRouter smart contract and initializes it with the provided configuration. + * + * If the router is intended to route the native asset, there's no need to include the rollup and parentChainTokenAddress parameters. + * + * References: + * - ArbChildToParentRewardRouter contract: https://github.com/OffchainLabs/fund-distribution-contracts/blob/main/src/FeeRouter/ArbChildToParentRewardRouter.sol + * + * Example: [Setup fee routing for the AEP](https://github.com/OffchainLabs/arbitrum-orbit-sdk/blob/main/examples/setup-aep-fee-router/index.ts) + * + * @param {FeeRouterDeployChildToParentRewardRouterParams} feeRouterDeployChildToParentRewardRouterParams {@link FeeRouterDeployChildToParentRewardRouterParams} + * @param {PublicClient} feeRouterDeployChildToParentRewardRouterParams.parentChainPublicClient - The parent chain Viem public client + * @param {WalletClient} feeRouterDeployChildToParentRewardRouterParams.orbitChainWalletClient - The orbit chain Viem wallet client (this account will deploy the contract) + * @param {Address} feeRouterDeployChildToParentRewardRouterParams.parentChainTargetAddress - The address where funds will be sent in the parent chain + * @param {bigint} feeRouterDeployChildToParentRewardRouterParams.minDistributionInvervalSeconds - [Optional] The number of seconds that needs to pass before funds can be sent again (to prevent griefing) + * @param {Address} feeRouterDeployChildToParentRewardRouterParams.rollup - [Optional] If sending a token different than the native token of the Orbit chain, the Rollup contract address of the chain + * @param {Address} feeRouterDeployChildToParentRewardRouterParams.parentChainTokenAddress - [Optional] If sending a token different than the native token of the Orbit chain, address of the token in the parent chain + * + * @returns Promise<0x${string}> - The hash of the deployment transaction + * + * @example + * const childToParentRewardRouterDeploymentTransactionHash = await feeRouterDeployChildToParentRewardRouter({ + * parentChainPublicClient, + * orbitChainWalletClient, + * parentChainTargetAddress, + * }); + * const childToParentRewardRouterDeploymentTransactionReceipt = + * await nitroTestnodeL2Client.waitForTransactionReceipt({ + * hash: childToParentRewardRouterDeploymentTransactionHash, + * }); + * const childToParentRewardRouterAddress = getAddress( + * childToParentRewardRouterDeploymentTransactionReceipt.contractAddress as `0x${string}`, + * ); + */ +export async function feeRouterDeployChildToParentRewardRouter({ + parentChainPublicClient, + orbitChainWalletClient, + parentChainTargetAddress, + minDistributionInvervalSeconds, + rollup, + parentChainTokenAddress, + tokenBridgeCreatorAddressOverride, +}: FeeRouterDeployChildToParentRewardRouterParams) { + validateParentChain(parentChainPublicClient); + + const constructorArguments = { + parentChainTargetAddress, + minDistributionInvervalSeconds: + minDistributionInvervalSeconds ?? DEFAULT_MIN_DISTRIBUTION_INVERVAL_SECONDS, + + // setting the default values here + // (when routing the native token, these three arguments need to be set to the oneAddress) + parentChainTokenAddress: oneAddress, + orbitChainTokenAddress: oneAddress, + orbitChainGatewayRouter: oneAddress, + }; + + if (parentChainTokenAddress) { + // routing a token different than the native token of the Orbit chain + + if (!rollup) { + throw new Error( + 'Rollup address is needed when routing a token different than the native token', + ); + } + + // obtain the GatewayRouter of the Orbit chain + const inbox = await parentChainPublicClient.readContract({ + address: rollup, + abi: parseAbi(['function inbox() view returns (address)']), + functionName: 'inbox', + }); + const tokenBridgeContracts = await createTokenBridgeFetchTokenBridgeContracts({ + inbox, + parentChainPublicClient, + tokenBridgeCreatorAddressOverride, + }); + const orbitChainGatewayRouter = tokenBridgeContracts.orbitChainContracts.router; + + // obtain the token address in the Orbit chain + // (we can use either gateway router to obtain the "L2 token address") + const orbitChainTokenAddress = await parentChainPublicClient.readContract({ + address: orbitChainGatewayRouter, + abi: parseAbi(['function calculateL2TokenAddress(address) view returns (address)']), + functionName: 'calculateL2TokenAddress', + args: [parentChainTokenAddress], + }); + + // replacing the values in the arguments object + constructorArguments.parentChainTokenAddress = parentChainTokenAddress; + constructorArguments.orbitChainTokenAddress = orbitChainTokenAddress; + constructorArguments.orbitChainGatewayRouter = orbitChainGatewayRouter; + } + + const transactionHash = await orbitChainWalletClient.deployContract({ + abi: arbChildToParentRewardRouter.abi, + account: orbitChainWalletClient.account!, + chain: orbitChainWalletClient.chain, + args: [ + constructorArguments.parentChainTargetAddress, + constructorArguments.minDistributionInvervalSeconds, + constructorArguments.parentChainTokenAddress, + constructorArguments.orbitChainTokenAddress, + constructorArguments.orbitChainGatewayRouter, + ], + bytecode: arbChildToParentRewardRouter.bytecode.object as `0x${string}`, + }); + + return transactionHash; +} diff --git a/src/feeRouterDeployRewardDistributor.ts b/src/feeRouterDeployRewardDistributor.ts new file mode 100644 index 00000000..cc6b2235 --- /dev/null +++ b/src/feeRouterDeployRewardDistributor.ts @@ -0,0 +1,80 @@ +import { Address, WalletClient } from 'viem'; + +import rewardDistributor from '@offchainlabs/fund-distribution-contracts/out/RewardDistributor.sol/RewardDistributor.json'; + +/** + * This type is for the recipients of the rewards + */ +export type RewardDistributorRecipient = { + account: Address; + weight: bigint; +}; + +/** + * This type is for the params of the feeRouterDeployRewardDistributor function + */ +export type FeeRouterDeployRewardDistributorParams = { + orbitChainWalletClient: WalletClient; + recipients: RewardDistributorRecipient[]; +}; + +/** + * Deploys the RewardDistributor smart contract and initializes it with the provided configuration. + * + * Note that weights are expressed in percentages multiplied by 100. For example, to allocate 12,5% of the amount to + * a specific recipient, you'll define the weight as 1250. To allocate 80%, you'll define the weight as 8000. + * + * References: + * - ChildToParentRouter contract: https://github.com/OffchainLabs/fund-distribution-contracts/blob/main/src/RewardDistributor.sol + * + * Example 1: [Setup fee routing for the AEP](https://github.com/OffchainLabs/arbitrum-orbit-sdk/blob/main/examples/setup-aep-fee-router/index.ts) + * Example 2: [Setup fee distributor contract](https://github.com/OffchainLabs/arbitrum-orbit-sdk/blob/main/examples/setup-fee-distributor-contract/index.ts) + * + * @param {FeeRouterDeployRewardDistributorParams} feeRouterDeployRewardDistributorParams {@link FeeRouterDeployRewardDistributorParams} + * @param {WalletClient} feeRouterDeployRewardDistributorParams.orbitChainWalletClient - The orbit chain Viem wallet client (this account will deploy the contract) + * @param {RewardDistributorRecipient[]} feeRouterDeployRewardDistributorParams.recipients - The recipients of the rewards (array objects with properties "account" and "weight") {@link RewardDistributorRecipient} + * @param {Address} feeRouterDeployRewardDistributorParams.recipients.account - Recipient of rewards + * @param {Address} feeRouterDeployRewardDistributorParams.recipients.weight - Percentage of the reward obtained multiplied by 100 (e.g., for obtaining 25%, the weight would be 2500) + * + * @returns Promise<0x${string}> - The hash of the deployment transaction + * + * @example + * const recipients = [ + * { + * account: randomAccount.address, + * weight: 9000n, + * }, + * { + * account: randomAccount2.address, + * weight: 1000n, + * }, + * ]; + * const rewardDistributorDeploymentTransactionHash = await feeRouterDeployRewardDistributor({ + * orbitChainWalletClient, + * recipients, + * }); + * const rewardDistributorDeploymentTransactionReceipt = + * await nitroTestnodeL2Client.waitForTransactionReceipt({ + * hash: rewardDistributorDeploymentTransactionHash, + * }); + * const rewardDistributorAddress = getAddress( + * rewardDistributorDeploymentTransactionReceipt.contractAddress as `0x${string}`, + * ); + */ +export async function feeRouterDeployRewardDistributor({ + orbitChainWalletClient, + recipients, +}: FeeRouterDeployRewardDistributorParams) { + const transactionHash = await orbitChainWalletClient.deployContract({ + abi: rewardDistributor.abi, + account: orbitChainWalletClient.account!, + chain: orbitChainWalletClient.chain, + args: [ + recipients.map((recipient) => recipient.account), + recipients.map((recipient) => recipient.weight), + ], + bytecode: rewardDistributor.bytecode.object as `0x${string}`, + }); + + return transactionHash; +} diff --git a/src/index.ts b/src/index.ts index fd43d9f1..1b16600e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -93,6 +93,14 @@ import { createTokenBridgeFetchTokenBridgeContracts } from './createTokenBridgeF import { createTokenBridgePrepareSetWethGatewayTransactionRequest } from './createTokenBridgePrepareSetWethGatewayTransactionRequest'; import { createTokenBridgePrepareSetWethGatewayTransactionReceipt } from './createTokenBridgePrepareSetWethGatewayTransactionReceipt'; import { prepareKeyset } from './prepareKeyset'; +import { + feeRouterDeployChildToParentRewardRouter, + FeeRouterDeployChildToParentRewardRouterParams, +} from './feeRouterDeployChildToParentRewardRouter'; +import { + feeRouterDeployRewardDistributor, + FeeRouterDeployRewardDistributorParams, +} from './feeRouterDeployRewardDistributor'; import * as utils from './utils'; import { getDefaultConfirmPeriodBlocks } from './getDefaultConfirmPeriodBlocks'; @@ -108,6 +116,7 @@ import { } from './getBatchPosters'; import { getKeysets, GetKeysetsParams, GetKeysetsReturnType } from './getKeysets'; import { isAnyTrust } from './isAnyTrust'; +import { parentChainIsArbitrum } from './parentChainIsArbitrum'; import { createSafePrepareTransactionRequest, CreateSafePrepareTransactionRequestParams, @@ -198,6 +207,11 @@ export { createTokenBridgePrepareSetWethGatewayTransactionRequest, createTokenBridgePrepareSetWethGatewayTransactionReceipt, // + feeRouterDeployChildToParentRewardRouter, + FeeRouterDeployChildToParentRewardRouterParams, + feeRouterDeployRewardDistributor, + FeeRouterDeployRewardDistributorParams, + // getDefaultConfirmPeriodBlocks, getDefaultSequencerInboxMaxTimeVariation, SequencerInboxMaxTimeVariation, @@ -215,6 +229,7 @@ export { GetKeysetsReturnType, // isAnyTrust, + parentChainIsArbitrum, // createSafePrepareTransactionRequest, CreateSafePrepareTransactionRequestParams, diff --git a/src/package.json b/src/package.json index de763d2e..98f07c9d 100644 --- a/src/package.json +++ b/src/package.json @@ -46,6 +46,7 @@ "dependencies": { "@arbitrum/sdk": "^4.0.0", "@arbitrum/token-bridge-contracts": "^1.2.1", + "@offchainlabs/fund-distribution-contracts": "^1.0.1", "@safe-global/protocol-kit": "^4.0.2", "ethers": "^5.7.2" } diff --git a/yarn.lock b/yarn.lock index 82d2292e..bcb0e722 100644 --- a/yarn.lock +++ b/yarn.lock @@ -662,6 +662,15 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@offchainlabs/fund-distribution-contracts@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@offchainlabs/fund-distribution-contracts/-/fund-distribution-contracts-1.0.1.tgz#3d7c05cb5ad0d5057e74286a8db8a72bf0571da6" + integrity sha512-ig1aAmfWPpq9474td6M/f/ltseipM2c5xs3nAsv9JX6YBhRF4OlNBczfdtjTgEh069rCnu4DcFSdoNzuaHDxBg== + dependencies: + "@types/yargs" "^17.0.32" + dotenv "^16.3.1" + yargs "^17.7.2" + "@offchainlabs/prettier-config@0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@offchainlabs/prettier-config/-/prettier-config-0.2.1.tgz#e3b57e013935269d84bf6379cdc529b3bbca9ae5" @@ -901,6 +910,18 @@ dependencies: "@types/node" "*" +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.32": + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + "@vitest/expect@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.6.0.tgz#0b3ba0914f738508464983f4d811bc122b51fb30" @@ -3717,7 +3738,7 @@ yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.0.0: +yargs@^17.0.0, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 7f072f0d2a9132f9fe79cc318120160591addcf6 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Mon, 12 Aug 2024 14:43:24 +0200 Subject: [PATCH 13/54] test: update implementation address in assertion (#161) --- src/utils/getImplementation.unit.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/getImplementation.unit.test.ts b/src/utils/getImplementation.unit.test.ts index 437e43cc..3c72c7b5 100644 --- a/src/utils/getImplementation.unit.test.ts +++ b/src/utils/getImplementation.unit.test.ts @@ -17,10 +17,10 @@ it('fetches no implementation address for RollupCreator v1.1.0 on Arbitrum Sepol expect(implementation).toEqual(zeroAddress); }); -it('fetches implementation address for TokenBridgeCreator v1.2.0 on Arbitrum Sepolia', async () => { +it('fetches implementation address for TokenBridgeCreator v1.2.2 on Arbitrum Sepolia', async () => { const implementation = await getImplementation({ client: arbitrumSepoliaPublicClient, address: '0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E', }); - expect(implementation).toEqual('0x4d80b4fd42abd6934df7d9ba536e5cfe2fb7e730'); + expect(implementation).toEqual('0x6b6e01852716f2d7dab6b8729bb50e67be68bf04'); }); From e52980acd8499db4534eaa6a9d4eda97a2dc61ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Mon, 12 Aug 2024 17:12:50 +0200 Subject: [PATCH 14/54] chore: omit patch number from contract version --- src/contracts/RollupCreator/index.ts | 2 +- src/contracts/RollupCreator/{v1.1.0.ts => v1.1.ts} | 0 src/contracts/TokenBridgeCreator/index.ts | 2 +- src/contracts/TokenBridgeCreator/{v1.2.0.ts => v1.2.ts} | 0 wagmi.config.ts | 4 ++-- 5 files changed, 4 insertions(+), 4 deletions(-) rename src/contracts/RollupCreator/{v1.1.0.ts => v1.1.ts} (100%) rename src/contracts/TokenBridgeCreator/{v1.2.0.ts => v1.2.ts} (100%) diff --git a/src/contracts/RollupCreator/index.ts b/src/contracts/RollupCreator/index.ts index 3c275a4f..e195e575 100644 --- a/src/contracts/RollupCreator/index.ts +++ b/src/contracts/RollupCreator/index.ts @@ -1,2 +1,2 @@ // export the latest version -export * from './v1.1.0'; +export * from './v1.1'; diff --git a/src/contracts/RollupCreator/v1.1.0.ts b/src/contracts/RollupCreator/v1.1.ts similarity index 100% rename from src/contracts/RollupCreator/v1.1.0.ts rename to src/contracts/RollupCreator/v1.1.ts diff --git a/src/contracts/TokenBridgeCreator/index.ts b/src/contracts/TokenBridgeCreator/index.ts index 1e0e8d08..94a27615 100644 --- a/src/contracts/TokenBridgeCreator/index.ts +++ b/src/contracts/TokenBridgeCreator/index.ts @@ -1,2 +1,2 @@ // export the latest version -export * from './v1.2.0'; +export * from './v1.2'; diff --git a/src/contracts/TokenBridgeCreator/v1.2.0.ts b/src/contracts/TokenBridgeCreator/v1.2.ts similarity index 100% rename from src/contracts/TokenBridgeCreator/v1.2.0.ts rename to src/contracts/TokenBridgeCreator/v1.2.ts diff --git a/wagmi.config.ts b/wagmi.config.ts index 23d954f9..4db2c02a 100644 --- a/wagmi.config.ts +++ b/wagmi.config.ts @@ -120,7 +120,7 @@ type ContractConfig = { const contracts: ContractConfig[] = [ { name: 'RollupCreator', - version: '1.1.0', + version: '1.1', address: { // mainnet L1 [mainnet.id]: '0x90d68b056c411015eae3ec0b98ad94e2c91419f1', @@ -141,7 +141,7 @@ const contracts: ContractConfig[] = [ }, { name: 'TokenBridgeCreator', - version: '1.2.0', + version: '1.2', address: { // mainnet L1 [mainnet.id]: '0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660', From 8522dd838fe624422d20d9d2f085d8a29a1f5c4d Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 13 Aug 2024 12:23:16 +0200 Subject: [PATCH 15/54] feat: remove deprecated createRollupPrepareConfig (#163) BREAKING CHANGE: The function `createRollupPrepareConfig` was removed. Use `createRollupPrepareDeploymentParamsConfig` instead. --- src/createRollupPrepareConfig.ts | 48 ---------------------- src/createRollupPrepareConfig.unit.test.ts | 44 -------------------- src/index.ts | 9 ---- 3 files changed, 101 deletions(-) delete mode 100644 src/createRollupPrepareConfig.ts delete mode 100644 src/createRollupPrepareConfig.unit.test.ts diff --git a/src/createRollupPrepareConfig.ts b/src/createRollupPrepareConfig.ts deleted file mode 100644 index 89310123..00000000 --- a/src/createRollupPrepareConfig.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { ChainConfig } from './types/ChainConfig'; -import { CreateRollupFunctionInputs } from './types/createRollupTypes'; -import { prepareChainConfig } from './prepareChainConfig'; -import { defaults as defaultsCommon } from './createRollupPrepareDeploymentParamsConfigDefaults'; -// importing for jsdoc @link to work -import { createRollupPrepareDeploymentParamsConfig } from './createRollupPrepareDeploymentParamsConfig'; -import { Prettify } from './types/utils'; - -export type CreateRollupPrepareConfigResult = CreateRollupFunctionInputs[0]['config']; - -type RequiredKeys = 'chainId' | 'owner'; -type RequiredParams = Pick; -type OptionalParams = Partial>; - -export type CreateRollupPrepareConfigParams = Prettify< - RequiredParams & { chainConfig?: ChainConfig } & OptionalParams ->; - -export const defaults = { - ...defaultsCommon, - confirmPeriodBlocks: BigInt(150), - sequencerInboxMaxTimeVariation: { - delayBlocks: BigInt(5_760), - futureBlocks: BigInt(48), - delaySeconds: BigInt(86_400), - futureSeconds: BigInt(3_600), - }, -} as const; - -/** - * @deprecated Will be removed in a future release. Please use {@link createRollupPrepareDeploymentParamsConfig} instead. - */ -export function createRollupPrepareConfig({ - chainConfig, - ...params -}: CreateRollupPrepareConfigParams): CreateRollupPrepareConfigResult { - return { - ...defaults, - ...params, - chainConfig: JSON.stringify( - chainConfig ?? - prepareChainConfig({ - chainId: Number(params.chainId), - arbitrum: { InitialChainOwner: params.owner }, - }), - ), - }; -} diff --git a/src/createRollupPrepareConfig.unit.test.ts b/src/createRollupPrepareConfig.unit.test.ts deleted file mode 100644 index a363df29..00000000 --- a/src/createRollupPrepareConfig.unit.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { expect, it } from 'vitest'; - -import { prepareChainConfig } from './prepareChainConfig'; -import { createRollupPrepareConfig } from './createRollupPrepareConfig'; - -const chainId = 69_420n; -const vitalik: `0x${string}` = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'; - -it('creates config with defaults', () => { - expect( - createRollupPrepareConfig({ - owner: vitalik, - chainId, - }), - ).toMatchSnapshot(); -}); - -it('creates config with overrides', () => { - expect( - createRollupPrepareConfig({ - owner: vitalik, - chainId, - chainConfig: prepareChainConfig({ - chainId: 69_420, - arbitrum: { - InitialChainOwner: vitalik, - InitialArbOSVersion: 30, - DataAvailabilityCommittee: true, - }, - }), - confirmPeriodBlocks: 4200n, - extraChallengeTimeBlocks: 5n, - loserStakeEscrow: '0x0000000000000000000000000000000000000001', - sequencerInboxMaxTimeVariation: { - delayBlocks: 200n, - delaySeconds: 5n, - futureBlocks: 100n, - futureSeconds: 1n, - }, - stakeToken: '0x0000000000000000000000000000000000000002', - wasmModuleRoot: '0xWasmModuleRoot', - }), - ).toMatchSnapshot(); -}); diff --git a/src/index.ts b/src/index.ts index 1b16600e..e3b532ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,3 @@ -import { - createRollupPrepareConfig, - CreateRollupPrepareConfigParams, - CreateRollupPrepareConfigResult, -} from './createRollupPrepareConfig'; import { createRollupPrepareDeploymentParamsConfig, CreateRollupPrepareDeploymentParamsConfigParams, @@ -141,10 +136,6 @@ export { CreateRollupFunctionInputs, CreateRollupParams, // - createRollupPrepareConfig, - CreateRollupPrepareConfigParams, - CreateRollupPrepareConfigResult, - // createRollupPrepareDeploymentParamsConfig, CreateRollupPrepareDeploymentParamsConfigParams, CreateRollupPrepareDeploymentParamsConfigResult, From 3266be71aa50c05305cb50608d2579959d8039d0 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 13 Aug 2024 17:12:58 +0200 Subject: [PATCH 16/54] feat: add support for RollupCreator v2.1 (#153) --- .env.example | 2 +- .github/workflows/build-test.yml | 12 +- .../create-rollup-custom-fee-token/README.md | 2 +- .../create-rollup-custom-fee-token/index.ts | 2 +- .../low_level.ts | 2 +- examples/create-rollup-eth/README.md | 2 +- examples/create-rollup-eth/index.ts | 2 +- examples/create-rollup-eth/low_level.ts | 2 +- src/contracts/RollupCreator/index.ts | 2 +- src/contracts/RollupCreator/v2.1.ts | 243 ++++++++++++++++++ src/contracts/TokenBridgeCreator/v1.2.ts | 2 +- src/createRollup.integration.test.ts | 25 +- src/createRollup.ts | 2 +- src/createRollupPrepareTransactionRequest.ts | 7 +- ...llupPrepareTransactionRequest.unit.test.ts | 48 +++- .../sequencerInboxActions.integration.test.ts | 11 +- src/getBatchPosters.ts | 19 +- src/getBatchPosters.unit.test.ts | 25 ++ src/getKeysets.integration.test.ts | 7 +- src/getValidators.ts | 17 +- src/getValidators.unit.test.ts | 23 ++ src/isAnyTrust.ts | 44 +++- src/isAnyTrust.unit.test.ts | 35 ++- src/testHelpers.ts | 8 +- src/types/createRollupTypes.ts | 2 +- wagmi.config.ts | 30 ++- 26 files changed, 500 insertions(+), 76 deletions(-) create mode 100644 src/contracts/RollupCreator/v2.1.ts diff --git a/.env.example b/.env.example index 4e7414a5..01fba995 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,7 @@ BASESCAN_API_KEY= NITRO_TESTNODE_DEPLOYER_PRIVATE_KEY=0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659 NITRO_TESTNODE_L2_ROLLUP_OWNER_PRIVATE_KEY=0xdc04c5399f82306ec4b4d654a342f40e2e0620fe39950d967e1e574b32d4dd36 -NITRO_TESTNODE_L2_TOKEN_BRIDGE_DEPLOYER_PRIVATE_KEY=0xadd3d9301e184194943ce6244aa25c90e73c5843db16a994d202091f97f5bb27 +NITRO_TESTNODE_L2_TOKEN_BRIDGE_DEPLOYER_PRIVATE_KEY=0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659 NITRO_TESTNODE_L3_ROLLUP_OWNER_PRIVATE_KEY=0xecdf21cb41c65afb51f91df408b7656e2c8739a5877f2814add0afd780cc210e NITRO_TESTNODE_L3_TOKEN_BRIDGE_DEPLOYER_PRIVATE_KEY=0xadd3d9301e184194943ce6244aa25c90e73c5843db16a994d202091f97f5bb27 diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 050ac983..578586b6 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -69,16 +69,10 @@ jobs: uses: OffchainLabs/actions/node-modules/install@main - name: Set up the local node - uses: OffchainLabs/actions/run-nitro-test-node@main + uses: OffchainLabs/actions/run-nitro-test-node@feat-simplify with: - nitro-testnode-ref: 1647de2c5f75ee0fbe5986e3f20d35bc75191ea6 # https://github.com/OffchainLabs/nitro-testnode/pull/42 - # Use simple mode - no-simple: false - # RollupCreator on L1 is deployed by default - # RollupCreator on L2 is deployed with --l3node - l3-node: true - # L3 node with custom fee token when using --l3-fee-token - args: --l3-fee-token + nitro-testnode-ref: executor-owner + args: --tokenbridge --l3node --l3-token-bridge --l3-fee-token - name: Copy .env run: cp ./.env.example ./.env diff --git a/examples/create-rollup-custom-fee-token/README.md b/examples/create-rollup-custom-fee-token/README.md index 63902c5d..1f3dd638 100644 --- a/examples/create-rollup-custom-fee-token/README.md +++ b/examples/create-rollup-custom-fee-token/README.md @@ -23,7 +23,7 @@ const createRollupConfig = createRollupPrepareDeploymentParamsConfig(parentChain await createRollup({ params: { config: createRollupConfig, - batchPoster, + batchPosters: [batchPoster], validators: [validator], nativeToken, }, diff --git a/examples/create-rollup-custom-fee-token/index.ts b/examples/create-rollup-custom-fee-token/index.ts index ac31a625..97f7ceb1 100644 --- a/examples/create-rollup-custom-fee-token/index.ts +++ b/examples/create-rollup-custom-fee-token/index.ts @@ -72,7 +72,7 @@ async function main() { await createRollup({ params: { config: createRollupConfig, - batchPoster, + batchPosters: [batchPoster], validators: [validator], nativeToken, }, diff --git a/examples/create-rollup-custom-fee-token/low_level.ts b/examples/create-rollup-custom-fee-token/low_level.ts index 5782ab56..1f1254d6 100644 --- a/examples/create-rollup-custom-fee-token/low_level.ts +++ b/examples/create-rollup-custom-fee-token/low_level.ts @@ -110,7 +110,7 @@ async function main() { owner: deployer.address, chainConfig, }), - batchPoster, + batchPosters: [batchPoster], validators: [validator], nativeToken, }, diff --git a/examples/create-rollup-eth/README.md b/examples/create-rollup-eth/README.md index ca2ce883..d4babfa6 100644 --- a/examples/create-rollup-eth/README.md +++ b/examples/create-rollup-eth/README.md @@ -20,7 +20,7 @@ const createRollupConfig = createRollupPrepareDeploymentParamsConfig(parentChain await createRollup({ params: { config: createRollupConfig, - batchPoster, + batchPosters: [batchPoster], validators: [validator], }, account: deployer, diff --git a/examples/create-rollup-eth/index.ts b/examples/create-rollup-eth/index.ts index 09d9366c..b04bbbb1 100644 --- a/examples/create-rollup-eth/index.ts +++ b/examples/create-rollup-eth/index.ts @@ -66,7 +66,7 @@ async function main() { await createRollup({ params: { config: createRollupConfig, - batchPoster, + batchPosters: [batchPoster], validators: [validator], }, account: deployer, diff --git a/examples/create-rollup-eth/low_level.ts b/examples/create-rollup-eth/low_level.ts index a4a6445f..c947eb5a 100644 --- a/examples/create-rollup-eth/low_level.ts +++ b/examples/create-rollup-eth/low_level.ts @@ -69,7 +69,7 @@ async function main() { owner: deployer.address, chainConfig, }), - batchPoster, + batchPosters: [batchPoster], validators: [validator], }, account: deployer.address, diff --git a/src/contracts/RollupCreator/index.ts b/src/contracts/RollupCreator/index.ts index e195e575..65e52bda 100644 --- a/src/contracts/RollupCreator/index.ts +++ b/src/contracts/RollupCreator/index.ts @@ -1,2 +1,2 @@ // export the latest version -export * from './v1.1'; +export * from './v2.1'; diff --git a/src/contracts/RollupCreator/v2.1.ts b/src/contracts/RollupCreator/v2.1.ts new file mode 100644 index 00000000..ab1582cd --- /dev/null +++ b/src/contracts/RollupCreator/v2.1.ts @@ -0,0 +1,243 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// RollupCreator +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x8c88430658a03497D13cDff7684D37b15aA2F3e1) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x091b8FC0F48613b191f81009797ce55Cf97Af7C8) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x79607f00e61E6d7C0E6330bd7E9c4AC320D50FC9) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9B523BF5F77e8d90e0E9eb0924aEA6E40B081aE6) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0xd2Ec8376B1dF436fAb18120E416d3F2BeC61275b) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfb774ea8a92ae528a596c8d90cbcf1bdbc4cee79) + */ +export const rollupCreatorABI = [ + { stateMutability: 'nonpayable', type: 'constructor', inputs: [] }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'previousOwner', internalType: 'address', type: 'address', indexed: true }, + { name: 'newOwner', internalType: 'address', type: 'address', indexed: true }, + ], + name: 'OwnershipTransferred', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'rollupAddress', internalType: 'address', type: 'address', indexed: true }, + { name: 'nativeToken', internalType: 'address', type: 'address', indexed: true }, + { name: 'inboxAddress', internalType: 'address', type: 'address', indexed: false }, + { name: 'outbox', internalType: 'address', type: 'address', indexed: false }, + { name: 'rollupEventInbox', internalType: 'address', type: 'address', indexed: false }, + { name: 'challengeManager', internalType: 'address', type: 'address', indexed: false }, + { name: 'adminProxy', internalType: 'address', type: 'address', indexed: false }, + { name: 'sequencerInbox', internalType: 'address', type: 'address', indexed: false }, + { name: 'bridge', internalType: 'address', type: 'address', indexed: false }, + { name: 'upgradeExecutor', internalType: 'address', type: 'address', indexed: false }, + { name: 'validatorUtils', internalType: 'address', type: 'address', indexed: false }, + { name: 'validatorWalletCreator', internalType: 'address', type: 'address', indexed: false }, + ], + name: 'RollupCreated', + }, + { type: 'event', anonymous: false, inputs: [], name: 'TemplatesUpdated' }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'bridgeCreator', + outputs: [{ name: '', internalType: 'contract BridgeCreator', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'challengeManagerTemplate', + outputs: [{ name: '', internalType: 'contract IChallengeManager', type: 'address' }], + }, + { + stateMutability: 'payable', + type: 'function', + inputs: [ + { + name: 'deployParams', + internalType: 'struct RollupCreator.RollupDeploymentParams', + type: 'tuple', + components: [ + { + name: 'config', + internalType: 'struct Config', + type: 'tuple', + components: [ + { name: 'confirmPeriodBlocks', internalType: 'uint64', type: 'uint64' }, + { name: 'extraChallengeTimeBlocks', internalType: 'uint64', type: 'uint64' }, + { name: 'stakeToken', internalType: 'address', type: 'address' }, + { name: 'baseStake', internalType: 'uint256', type: 'uint256' }, + { name: 'wasmModuleRoot', internalType: 'bytes32', type: 'bytes32' }, + { name: 'owner', internalType: 'address', type: 'address' }, + { name: 'loserStakeEscrow', internalType: 'address', type: 'address' }, + { name: 'chainId', internalType: 'uint256', type: 'uint256' }, + { name: 'chainConfig', internalType: 'string', type: 'string' }, + { name: 'genesisBlockNum', internalType: 'uint64', type: 'uint64' }, + { + name: 'sequencerInboxMaxTimeVariation', + internalType: 'struct ISequencerInbox.MaxTimeVariation', + type: 'tuple', + components: [ + { name: 'delayBlocks', internalType: 'uint256', type: 'uint256' }, + { name: 'futureBlocks', internalType: 'uint256', type: 'uint256' }, + { name: 'delaySeconds', internalType: 'uint256', type: 'uint256' }, + { name: 'futureSeconds', internalType: 'uint256', type: 'uint256' }, + ], + }, + ], + }, + { name: 'validators', internalType: 'address[]', type: 'address[]' }, + { name: 'maxDataSize', internalType: 'uint256', type: 'uint256' }, + { name: 'nativeToken', internalType: 'address', type: 'address' }, + { name: 'deployFactoriesToL2', internalType: 'bool', type: 'bool' }, + { name: 'maxFeePerGasForRetryables', internalType: 'uint256', type: 'uint256' }, + { name: 'batchPosters', internalType: 'address[]', type: 'address[]' }, + { name: 'batchPosterManager', internalType: 'address', type: 'address' }, + ], + }, + ], + name: 'createRollup', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'l2FactoriesDeployer', + outputs: [{ name: '', internalType: 'contract DeployHelper', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'osp', + outputs: [{ name: '', internalType: 'contract IOneStepProofEntry', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'owner', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [], + name: 'renounceOwnership', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'rollupAdminLogic', + outputs: [{ name: '', internalType: 'contract IRollupAdmin', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'rollupUserLogic', + outputs: [{ name: '', internalType: 'contract IRollupUser', type: 'address' }], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: '_bridgeCreator', internalType: 'contract BridgeCreator', type: 'address' }, + { name: '_osp', internalType: 'contract IOneStepProofEntry', type: 'address' }, + { + name: '_challengeManagerLogic', + internalType: 'contract IChallengeManager', + type: 'address', + }, + { name: '_rollupAdminLogic', internalType: 'contract IRollupAdmin', type: 'address' }, + { name: '_rollupUserLogic', internalType: 'contract IRollupUser', type: 'address' }, + { name: '_upgradeExecutorLogic', internalType: 'contract IUpgradeExecutor', type: 'address' }, + { name: '_validatorUtils', internalType: 'address', type: 'address' }, + { name: '_validatorWalletCreator', internalType: 'address', type: 'address' }, + { name: '_l2FactoriesDeployer', internalType: 'contract DeployHelper', type: 'address' }, + ], + name: 'setTemplates', + outputs: [], + }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], + name: 'transferOwnership', + outputs: [], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'upgradeExecutorLogic', + outputs: [{ name: '', internalType: 'contract IUpgradeExecutor', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'validatorUtils', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'validatorWalletCreator', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + }, + { stateMutability: 'payable', type: 'receive' }, +] as const; + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x8c88430658a03497D13cDff7684D37b15aA2F3e1) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x091b8FC0F48613b191f81009797ce55Cf97Af7C8) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x79607f00e61E6d7C0E6330bd7E9c4AC320D50FC9) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9B523BF5F77e8d90e0E9eb0924aEA6E40B081aE6) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0xd2Ec8376B1dF436fAb18120E416d3F2BeC61275b) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfb774ea8a92ae528a596c8d90cbcf1bdbc4cee79) + */ +export const rollupCreatorAddress = { + 1: '0x8c88430658a03497D13cDff7684D37b15aA2F3e1', + 1337: '0x82A3c114b40ecF1FC34745400A1B9B9115c33d31', + 8453: '0x091b8FC0F48613b191f81009797ce55Cf97Af7C8', + 17000: '0x03c70F125Df471E4fd0515ca38504edFE6900F19', + 42161: '0x79607f00e61E6d7C0E6330bd7E9c4AC320D50FC9', + 42170: '0x9B523BF5F77e8d90e0E9eb0924aEA6E40B081aE6', + 84532: '0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502', + 412346: '0x4287839696d650A0cf93b98351e85199102335D0', + 421614: '0xd2Ec8376B1dF436fAb18120E416d3F2BeC61275b', + 11155111: '0xfb774eA8A92ae528A596c8D90CBCF1bdBC4Cee79', +} as const; + +/** + * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x8c88430658a03497D13cDff7684D37b15aA2F3e1) + * - + * - [__View Contract on Base Basescan__](https://basescan.org/address/0x091b8FC0F48613b191f81009797ce55Cf97Af7C8) + * - + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x79607f00e61E6d7C0E6330bd7E9c4AC320D50FC9) + * - [__View Contract on Arbitrum Nova Arbiscan__](https://nova.arbiscan.io/address/0x9B523BF5F77e8d90e0E9eb0924aEA6E40B081aE6) + * - [__View Contract on Base Sepolia Blockscout__](https://base-sepolia.blockscout.com/address/0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502) + * - [__View Contract on Arbitrum Sepolia Blockscout__](https://sepolia-explorer.arbitrum.io/address/0xd2Ec8376B1dF436fAb18120E416d3F2BeC61275b) + * - [__View Contract on Sepolia Etherscan__](https://sepolia.etherscan.io/address/0xfb774ea8a92ae528a596c8d90cbcf1bdbc4cee79) + */ +export const rollupCreatorConfig = { + address: rollupCreatorAddress, + abi: rollupCreatorABI, +} as const; diff --git a/src/contracts/TokenBridgeCreator/v1.2.ts b/src/contracts/TokenBridgeCreator/v1.2.ts index dbc6d575..91340622 100644 --- a/src/contracts/TokenBridgeCreator/v1.2.ts +++ b/src/contracts/TokenBridgeCreator/v1.2.ts @@ -415,7 +415,7 @@ export const tokenBridgeCreatorABI = [ */ export const tokenBridgeCreatorAddress = { 1: '0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660', - 1337: '0x54B4D4e578E10178a6cA602bdb6df0F213296Af4', + 1337: '0x4Af567288e68caD4aA93A272fe6139Ca53859C70', 8453: '0x4C240987d6fE4fa8C7a0004986e3db563150CA55', 17000: '0xac890ED9bC2494C053cE701F138958df95966d94', 42161: '0x2f5624dc8800dfA0A82AC03509Ef8bb8E7Ac000e', diff --git a/src/createRollup.integration.test.ts b/src/createRollup.integration.test.ts index 4c8fac1f..278c9a5f 100644 --- a/src/createRollup.integration.test.ts +++ b/src/createRollup.integration.test.ts @@ -2,7 +2,11 @@ import { describe, it, expect } from 'vitest'; import { Address, createPublicClient, http, parseGwei, zeroAddress } from 'viem'; import { nitroTestnodeL2 } from './chains'; -import { getNitroTestnodePrivateKeyAccounts, createRollupHelper } from './testHelpers'; +import { + createRollupHelper, + getNitroTestnodePrivateKeyAccounts, + getInformationFromTestnode, +} from './testHelpers'; import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; const parentChainPublicClient = createPublicClient({ @@ -13,13 +17,13 @@ const parentChainPublicClient = createPublicClient({ // test inputs const testnodeAccounts = getNitroTestnodePrivateKeyAccounts(); const l3TokenBridgeDeployer = testnodeAccounts.l3TokenBridgeDeployer; -const batchPoster = testnodeAccounts.deployer.address; -const validators: [Address] = [testnodeAccounts.deployer.address]; +const batchPosters = [testnodeAccounts.deployer.address]; +const validators = [testnodeAccounts.deployer.address]; describe(`create an AnyTrust chain that uses ETH as gas token`, async () => { const { createRollupConfig, createRollupInformation } = await createRollupHelper({ deployer: l3TokenBridgeDeployer, - batchPoster, + batchPosters, validators, nativeToken: zeroAddress, client: parentChainPublicClient, @@ -29,7 +33,7 @@ describe(`create an AnyTrust chain that uses ETH as gas token`, async () => { // assert all inputs are correct const [arg] = createRollupInformation.transaction.getInputs(); expect(arg.config).toEqual(createRollupConfig); - expect(arg.batchPoster).toEqual(batchPoster); + expect(arg.batchPosters).toEqual(batchPosters); expect(arg.validators).toEqual(validators); expect(arg.maxDataSize).toEqual(104_857n); expect(arg.nativeToken).toEqual(zeroAddress); @@ -54,14 +58,13 @@ describe(`create an AnyTrust chain that uses ETH as gas token`, async () => { }); describe(`create an AnyTrust chain that uses a custom gas token`, async () => { - // deployed during nitro testnode running process - const customGasTokenAddress = '0xc57a290f65F1D433f081381B2A7A523Ea70f1134'; + const nativeToken = getInformationFromTestnode().l3NativeToken; const { createRollupConfig, createRollupInformation } = await createRollupHelper({ deployer: l3TokenBridgeDeployer, - batchPoster, + batchPosters, validators, - nativeToken: customGasTokenAddress, + nativeToken, client: parentChainPublicClient, }); @@ -69,10 +72,10 @@ describe(`create an AnyTrust chain that uses a custom gas token`, async () => { // assert all inputs are correct const [arg] = createRollupInformation.transaction.getInputs(); expect(arg.config).toEqual(createRollupConfig); - expect(arg.batchPoster).toEqual(batchPoster); + expect(arg.batchPosters).toEqual(batchPosters); expect(arg.validators).toEqual(validators); expect(arg.maxDataSize).toEqual(104_857n); - expect(arg.nativeToken).toEqual(customGasTokenAddress); + expect(arg.nativeToken).toEqual(nativeToken); expect(arg.deployFactoriesToL2).toEqual(true); expect(arg.maxFeePerGasForRetryables).toEqual(parseGwei('0.1')); diff --git a/src/createRollup.ts b/src/createRollup.ts index de653df8..eeb20b37 100644 --- a/src/createRollup.ts +++ b/src/createRollup.ts @@ -144,7 +144,7 @@ export type CreateRollupResults = { * } = await createRollup({ * params: { * config: createRollupConfig, - * batchPoster, + * batchPosters, * validators, * }, * account: deployer, diff --git a/src/createRollupPrepareTransactionRequest.ts b/src/createRollupPrepareTransactionRequest.ts index dc90315a..76eee497 100644 --- a/src/createRollupPrepareTransactionRequest.ts +++ b/src/createRollupPrepareTransactionRequest.ts @@ -46,8 +46,8 @@ export async function createRollupPrepareTransactionRequest) { const chainId = validateParentChain(publicClient); - if (params.batchPoster === zeroAddress) { - throw new Error(`"params.batchPoster" can't be set to the zero address.`); + if (params.batchPosters.length === 0 || params.batchPosters.includes(zeroAddress)) { + throw new Error(`"params.batchPosters" can't be empty or contain the zero address.`); } if (params.validators.length === 0 || params.validators.includes(zeroAddress)) { @@ -73,7 +73,8 @@ export async function createRollupPrepareTransactionRequest { +it(`fails to prepare transaction request if "params.batchPosters" is set to an empty array`, async () => { // generate a random chain id const chainId = generateChainId(); @@ -37,14 +37,42 @@ it(`fails to prepare transaction request if "params.batchPoster" is set to the z owner: deployer.address, chainConfig, }), - // set batch poster to the zero address - batchPoster: zeroAddress, + batchPosters: [], validators: [deployer.address], }, account: deployer.address, publicClient, }), - ).rejects.toThrowError(`"params.batchPoster" can't be set to the zero address.`); + ).rejects.toThrowError(`"params.batchPosters" can't be empty or contain the zero address.`); +}); + +it(`fails to prepare transaction request if "params.batchPosters" includes the zero address`, async () => { + // generate a random chain id + const chainId = generateChainId(); + + // create the chain config + const chainConfig = prepareChainConfig({ + chainId, + arbitrum: { InitialChainOwner: deployer.address }, + }); + + // prepare the transaction for deploying the core contracts + await expect( + createRollupPrepareTransactionRequest({ + params: { + config: createRollupPrepareDeploymentParamsConfig(publicClient, { + chainId: BigInt(chainId), + owner: deployer.address, + chainConfig, + }), + // set batch posters array to include zero address + batchPosters: [zeroAddress, deployer.address], + validators: [deployer.address], + }, + account: deployer.address, + publicClient, + }), + ).rejects.toThrowError(`"params.batchPosters" can't be empty or contain the zero address.`); }); it(`fails to prepare transaction request if "params.validators" is set to an empty array`, async () => { @@ -66,7 +94,7 @@ it(`fails to prepare transaction request if "params.validators" is set to an emp owner: deployer.address, chainConfig, }), - batchPoster: deployer.address, + batchPosters: [deployer.address], // set validators to an empty array validators: [], }, @@ -95,7 +123,7 @@ it(`fails to prepare transaction request if "params.validators" includes the zer owner: deployer.address, chainConfig, }), - batchPoster: deployer.address, + batchPosters: [deployer.address], // set validators to zero address validators: [zeroAddress], }, @@ -124,7 +152,7 @@ it(`fails to prepare transaction request if "params.nativeToken" is custom and c owner: deployer.address, chainConfig, }), - batchPoster: deployer.address, + batchPosters: [deployer.address], validators: [deployer.address], // set native token to anything custom nativeToken: deployer.address, @@ -156,7 +184,7 @@ it(`fails to prepare transaction request if "params.nativeToken" doesn't use 18 owner: deployer.address, chainConfig, }), - batchPoster: deployer.address, + batchPosters: [deployer.address], validators: [deployer.address], // USDC on Arbitrum Sepolia has 6 decimals nativeToken: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d', @@ -186,7 +214,7 @@ it(`successfully prepares a transaction request with the default rollup creator owner: deployer.address, chainConfig, }), - batchPoster: deployer.address, + batchPosters: [deployer.address], validators: [deployer.address], }, account: deployer.address, @@ -218,7 +246,7 @@ it(`successfully prepares a transaction request with a custom rollup creator and owner: deployer.address, chainConfig, }), - batchPoster: deployer.address, + batchPosters: [deployer.address], validators: [deployer.address], }, account: deployer.address, diff --git a/src/decorators/sequencerInboxActions.integration.test.ts b/src/decorators/sequencerInboxActions.integration.test.ts index 8b329051..8c02744c 100644 --- a/src/decorators/sequencerInboxActions.integration.test.ts +++ b/src/decorators/sequencerInboxActions.integration.test.ts @@ -37,7 +37,7 @@ describe('sequencerInboxReadContract', () => { sequencerInbox: l3SequencerInbox, }); - expect(result.toLowerCase()).toEqual(l3Bridge); + expect(result.toLowerCase()).toEqual(l3Bridge.toLowerCase()); }); it('successfully fetches dasKeySetInfo', async () => { @@ -102,7 +102,7 @@ describe('sequencerInboxReadContract', () => { sequencerInbox: l3SequencerInbox, }); - expect(result.toLowerCase()).toEqual(l3Rollup); + expect(result.toLowerCase()).toEqual(l3Rollup.toLowerCase()); }); it('successfully call totalDelayedMessagesRead', async () => { @@ -118,13 +118,12 @@ describe('sequencerInboxReadContract', () => { describe('sequencerInboxPrepareTransactionRequest', () => { it('successfully call setValidKeyset', async () => { // Keyset needs to be set on anytrust chain - const deployerAddress = deployer.address; - const batchPoster = deployer.address; - const validators: [Address] = [deployerAddress]; + const batchPosters = [deployer.address]; + const validators = [deployer.address]; const { createRollupInformation } = await createRollupHelper({ deployer: l3TokenBridgeDeployer, - batchPoster, + batchPosters, validators, nativeToken: zeroAddress, client, diff --git a/src/getBatchPosters.ts b/src/getBatchPosters.ts index c67a166a..5b7fa744 100644 --- a/src/getBatchPosters.ts +++ b/src/getBatchPosters.ts @@ -10,6 +10,7 @@ import { } from 'viem'; import { rollupCreatorABI } from './contracts/RollupCreator'; +import { rollupCreatorABI as rollupCreatorV1Dot1ABI } from './contracts/RollupCreator/v1.1'; import { sequencerInboxABI } from './contracts/SequencerInbox'; import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; import { gnosisSafeL2ABI } from './contracts/GnosisSafeL2'; @@ -19,6 +20,9 @@ import { createRollupFetchTransactionHash } from './createRollupFetchTransaction const createRollupABI = getAbiItem({ abi: rollupCreatorABI, name: 'createRollup' }); const createRollupFunctionSelector = getFunctionSelector(createRollupABI); +const createRollupV1Dot1ABI = getAbiItem({ abi: rollupCreatorV1Dot1ABI, name: 'createRollup' }); +const createRollupV1Dot1FunctionSelector = getFunctionSelector(createRollupV1Dot1ABI); + const setIsBatchPosterABI = getAbiItem({ abi: sequencerInboxABI, name: 'setIsBatchPoster' }); const setIsBatchPosterFunctionSelector = getFunctionSelector(setIsBatchPosterABI); @@ -34,7 +38,10 @@ const ownerFunctionCalledEventAbi = getAbiItem({ }); function getBatchPostersFromFunctionData< - TAbi extends (typeof createRollupABI)[] | (typeof setIsBatchPosterABI)[], + TAbi extends + | (typeof createRollupABI)[] + | (typeof createRollupV1Dot1ABI)[] + | (typeof setIsBatchPosterABI)[], >({ abi, data }: { abi: TAbi; data: Hex }) { const { args } = decodeFunctionData({ abi, @@ -142,11 +149,19 @@ export async function getBatchPosters( switch (txSelectedFunction) { case createRollupFunctionSelector: { - const [{ batchPoster }] = getBatchPostersFromFunctionData({ + const [{ batchPosters }] = getBatchPostersFromFunctionData({ abi: [createRollupABI], data: tx.input, }); + return new Set([...acc, ...batchPosters]); + } + case createRollupV1Dot1FunctionSelector: { + const [{ batchPoster }] = getBatchPostersFromFunctionData({ + abi: [createRollupV1Dot1ABI], + data: tx.input, + }); + return new Set([...acc, batchPoster]); } case setIsBatchPosterFunctionSelector: { diff --git a/src/getBatchPosters.unit.test.ts b/src/getBatchPosters.unit.test.ts index 176d0c23..16f0f45e 100644 --- a/src/getBatchPosters.unit.test.ts +++ b/src/getBatchPosters.unit.test.ts @@ -21,6 +21,11 @@ const client = createPublicClient({ transport: http(), }); +const arbitrumSepoliaClient = createPublicClient({ + chain: arbitrumSepolia, + transport: http(), +}); + function mockLog(transactionHash: string) { return { address: '0x193e2887031c148ab54f5e856ea51ae521661200', @@ -152,6 +157,26 @@ it('getBatchPosters returns all batch posters (Xai)', async () => { expect(isAccurate).toBeTruthy(); }); +// https://sepolia.arbiscan.io/tx/0x5b0b49e0259289fc89949a55a5ad35a8939440a55065d29b14e5e7ef7494efff +it('getBatchPosters returns batch posters for a chain created with RollupCreator v1.1', async () => { + const { isAccurate, batchPosters } = await getBatchPosters(arbitrumSepoliaClient, { + rollup: '0x1644590Fd2223264ea8Cda8927B038CcCFE0Da76', + sequencerInbox: '0x96bA492C55Af83dfC88D52A1e584e4061716e9e8', + }); + expect(batchPosters).toEqual(['0x3C3A5b44FAB0e2025160a765348c21C08e41d1Af']); + expect(isAccurate).toBeTruthy(); +}); + +// https://sepolia.arbiscan.io/tx/0xfd638529dec24963075ee8fcd9df0d319c21190a9e3f3cb5e91d7da353666b06 +it('getBatchPosters returns batch posters for a chain created with RollupCreator v2.1', async () => { + const { isAccurate, batchPosters } = await getBatchPosters(arbitrumSepoliaClient, { + rollup: '0x16A95119425638cAaD6d302D75B270ecDBf37649', + sequencerInbox: '0xbE20C632d1DaD19285575580Aaa60C9B1207d531', + }); + expect(batchPosters).toEqual(['0x551B0B7DA75530544aF467183E626778412491Da']); + expect(isAccurate).toBeTruthy(); +}); + describe('createRollupFunctionSelector', () => { it('getBatchPosters returns all batch posters with isAccurate flag set to true', async () => { const mockTransport = () => diff --git a/src/getKeysets.integration.test.ts b/src/getKeysets.integration.test.ts index 6697dcf8..e34ae5ea 100644 --- a/src/getKeysets.integration.test.ts +++ b/src/getKeysets.integration.test.ts @@ -94,13 +94,12 @@ const keyset = const keysetHash = '0xf8bb9a67839d1767e79afe52d21e97a04ee0bf5f816d5b52c10df60cccb7f822'; async function createAnytrustRollup() { - const deployerAddress = deployer.address; - const batchPoster = deployer.address; - const validators: [Address] = [deployerAddress]; + const batchPosters = [deployer.address]; + const validators = [deployer.address]; return createRollupHelper({ deployer: l3TokenBridgeDeployer, - batchPoster, + batchPosters, validators, nativeToken: zeroAddress, client, diff --git a/src/getValidators.ts b/src/getValidators.ts index 9951b4fb..36237c74 100644 --- a/src/getValidators.ts +++ b/src/getValidators.ts @@ -10,6 +10,7 @@ import { } from 'viem'; import { rollupCreatorABI } from './contracts/RollupCreator'; +import { rollupCreatorABI as rollupCreatorV1Dot1ABI } from './contracts/RollupCreator/v1.1'; import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; import { gnosisSafeL2ABI } from './contracts/GnosisSafeL2'; import { rollupABI } from './contracts/Rollup'; @@ -19,6 +20,9 @@ import { createRollupFetchTransactionHash } from './createRollupFetchTransaction const createRollupABI = getAbiItem({ abi: rollupCreatorABI, name: 'createRollup' }); const createRollupFunctionSelector = getFunctionSelector(createRollupABI); +const createRollupV1Dot1ABI = getAbiItem({ abi: rollupCreatorV1Dot1ABI, name: 'createRollup' }); +const createRollupV1Dot1FunctionSelector = getFunctionSelector(createRollupV1Dot1ABI); + const setValidatorABI = getAbiItem({ abi: rollupABI, name: 'setValidator' }); const setValidatorFunctionSelector = getFunctionSelector(setValidatorABI); @@ -31,7 +35,10 @@ const safeL2FunctionSelector = getFunctionSelector(execTransactionABI); const ownerFunctionCalledEventAbi = getAbiItem({ abi: rollupABI, name: 'OwnerFunctionCalled' }); function getValidatorsFromFunctionData< - TAbi extends (typeof createRollupABI)[] | (typeof setValidatorABI)[], + TAbi extends + | (typeof createRollupABI)[] + | (typeof createRollupV1Dot1ABI)[] + | (typeof setValidatorABI)[], >({ abi, data }: { abi: TAbi; data: Hex }) { const { args } = decodeFunctionData({ abi, @@ -140,6 +147,14 @@ export async function getValidators( return new Set([...acc, ...validators]); } + case createRollupV1Dot1FunctionSelector: { + const [{ validators }] = getValidatorsFromFunctionData({ + abi: [createRollupV1Dot1ABI], + data: tx.input, + }); + + return new Set([...acc, ...validators]); + } case setValidatorFunctionSelector: { return updateAccumulator(acc, tx.input); } diff --git a/src/getValidators.unit.test.ts b/src/getValidators.unit.test.ts index b2b4b987..0f7b9d47 100644 --- a/src/getValidators.unit.test.ts +++ b/src/getValidators.unit.test.ts @@ -21,6 +21,11 @@ const client = createPublicClient({ transport: http(), }); +const arbitrumSepoliaClient = createPublicClient({ + chain: arbitrumSepolia, + transport: http(), +}); + function mockLog(transactionHash: string) { return { address: '0x193e2887031c148ab54f5e856ea51ae521661200', @@ -149,6 +154,24 @@ it('getValidators return all validators (Xai)', async () => { expect(isAccurate).toBeTruthy(); }); +// https://sepolia.arbiscan.io/tx/0x5b0b49e0259289fc89949a55a5ad35a8939440a55065d29b14e5e7ef7494efff +it('getValidators returns validators for a chain created with RollupCreator v1.1', async () => { + const { isAccurate, validators } = await getValidators(arbitrumSepoliaClient, { + rollup: '0x1644590Fd2223264ea8Cda8927B038CcCFE0Da76', + }); + expect(validators).toEqual(['0x8E842599F71ABD661737bb3108a53E5b1787c791']); + expect(isAccurate).toBeTruthy(); +}); + +// https://sepolia.arbiscan.io/tx/0xfd638529dec24963075ee8fcd9df0d319c21190a9e3f3cb5e91d7da353666b06 +it('getValidators returns validators for a chain created with RollupCreator v2.1', async () => { + const { isAccurate, validators } = await getValidators(arbitrumSepoliaClient, { + rollup: '0x16A95119425638cAaD6d302D75B270ecDBf37649', + }); + expect(validators).toEqual(['0xbD7621A2bB0e4B768F1e1756dC500e2c44f02649']); + expect(isAccurate).toBeTruthy(); +}); + describe('createRollupFunctionSelector', () => { it('getValidators return all validators with isAccurate flag set to true', async () => { const mockTransport = () => diff --git a/src/isAnyTrust.ts b/src/isAnyTrust.ts index fdfbebaa..2e0c345e 100644 --- a/src/isAnyTrust.ts +++ b/src/isAnyTrust.ts @@ -1,8 +1,16 @@ import { Address, Chain, PublicClient, Transport, decodeFunctionData, getAbiItem } from 'viem'; import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; + import { rollupCreatorABI } from './contracts/RollupCreator'; +import { rollupCreatorABI as rollupCreatorV1Dot1ABI } from './contracts/RollupCreator/v1.1'; const createRollupABI = getAbiItem({ abi: rollupCreatorABI, name: 'createRollup' }); +const createRollupV1Dot1ABI = getAbiItem({ abi: rollupCreatorV1Dot1ABI, name: 'createRollup' }); + +function parseConfig(config: { chainConfig: string }): boolean { + return JSON.parse(config.chainConfig).arbitrum.DataAvailabilityCommittee; +} + export async function isAnyTrust({ rollup, publicClient, @@ -18,12 +26,34 @@ export async function isAnyTrust({ const transaction = await publicClient.getTransaction({ hash: createRollupTransactionHash, }); - const { - args: [{ config }], - } = decodeFunctionData({ - abi: [createRollupABI], - data: transaction.input, + + let result: boolean | null = null; + // try parsing from multiple RollupCreator versions + [ + // v2.1 + createRollupABI, + // v1.1 + createRollupV1Dot1ABI, + ].forEach((abi) => { + try { + const { + args: [{ config }], + } = decodeFunctionData({ + abi: [abi], + data: transaction.input, + }); + + result = parseConfig(config); + } catch (error) { + // do nothing + } }); - const chainConfig = JSON.parse(config.chainConfig); - return chainConfig.arbitrum.DataAvailabilityCommittee; + + if (result === null) { + throw new Error( + `[isAnyTrust] failed to decode input data for transaction ${createRollupTransactionHash}`, + ); + } + + return result; } diff --git a/src/isAnyTrust.unit.test.ts b/src/isAnyTrust.unit.test.ts index 3ff89023..1dc2db32 100644 --- a/src/isAnyTrust.unit.test.ts +++ b/src/isAnyTrust.unit.test.ts @@ -1,9 +1,10 @@ import { expect, it } from 'vitest'; -import { isAnyTrust } from './isAnyTrust'; import { createPublicClient, http } from 'viem'; -import { arbitrumNova, arbitrumSepolia, sepolia } from 'viem/chains'; +import { arbitrumNova, arbitrumSepolia } from 'viem/chains'; + +import { isAnyTrust } from './isAnyTrust'; -it('should return true for AnyTrust chain', async () => { +it('should return true for AnyTrust chain (RollupCreator v1.1)', async () => { const client = createPublicClient({ chain: arbitrumNova, transport: http(), @@ -16,7 +17,20 @@ it('should return true for AnyTrust chain', async () => { expect(isPlaynanceAnyTrust).toBeTruthy(); }); -it('should return false for non AnyTrust chain', async () => { +it('should return true for AnyTrust chain (RollupCreator v2.1)', async () => { + const client = createPublicClient({ + chain: arbitrumSepolia, + transport: http(), + }); + // https://sepolia.arbiscan.io/tx/0xc1d9513cee57252ab9a0987e3ac4bf23aca7f5c58478a29439ecb1ef815cd379 + const isAnyTrustChain = await isAnyTrust({ + publicClient: client, + rollup: '0x66Ef747DFDb01a0c0A3a2CB308216704E64B4A78', + }); + expect(isAnyTrustChain).toBeTruthy(); +}); + +it('should return false for non AnyTrust chain (RollupCreator v1.1)', async () => { const client = createPublicClient({ chain: arbitrumSepolia, transport: http(), @@ -28,3 +42,16 @@ it('should return false for non AnyTrust chain', async () => { }); expect(isAnyTrustChain).toBeFalsy(); }); + +it('should return false for non AnyTrust chain (RollupCreator v2.1)', async () => { + const client = createPublicClient({ + chain: arbitrumSepolia, + transport: http(), + }); + // https://sepolia.arbiscan.io/tx/0xfd638529dec24963075ee8fcd9df0d319c21190a9e3f3cb5e91d7da353666b06 + const isAnyTrustChain = await isAnyTrust({ + publicClient: client, + rollup: '0xD0c7B5C4E8f72E0750ed9dc70A10cf6F5Afd4787', + }); + expect(isAnyTrustChain).toBeFalsy(); +}); diff --git a/src/testHelpers.ts b/src/testHelpers.ts index fcf38377..eb8c3893 100644 --- a/src/testHelpers.ts +++ b/src/testHelpers.ts @@ -137,14 +137,14 @@ export function getInformationFromTestnode(): TestnodeInformation { export async function createRollupHelper({ deployer, - batchPoster, + batchPosters, validators, nativeToken = zeroAddress, client, }: { deployer: PrivateKeyAccountWithPrivateKey; - batchPoster: Address; - validators: [Address]; + batchPosters: Address[]; + validators: Address[]; nativeToken: Address; client: PublicClient; }) { @@ -165,7 +165,7 @@ export async function createRollupHelper({ const createRollupInformation = await createRollup({ params: { config: createRollupConfig, - batchPoster, + batchPosters, validators, nativeToken, }, diff --git a/src/types/createRollupTypes.ts b/src/types/createRollupTypes.ts index 5980fe25..f1e43b05 100644 --- a/src/types/createRollupTypes.ts +++ b/src/types/createRollupTypes.ts @@ -7,7 +7,7 @@ export type CreateRollupFunctionInputs = GetFunctionArgs< 'createRollup' >['args']; -type RequiredKeys = 'config' | 'batchPoster' | 'validators'; +type RequiredKeys = 'config' | 'batchPosters' | 'validators'; export type CreateRollupParams = Pick & Partial>; diff --git a/wagmi.config.ts b/wagmi.config.ts index 4db2c02a..3ecd02e4 100644 --- a/wagmi.config.ts +++ b/wagmi.config.ts @@ -139,6 +139,27 @@ const contracts: ContractConfig[] = [ [nitroTestnodeL2.id]: '0x3BaF9f08bAD68869eEdEa90F2Cc546Bd80F1A651', }, }, + { + name: 'RollupCreator', + version: '2.1', + address: { + // mainnet L1 + [mainnet.id]: '0x8c88430658a03497D13cDff7684D37b15aA2F3e1', + // mainnet L2 + [arbitrumOne.id]: '0x79607f00e61E6d7C0E6330bd7E9c4AC320D50FC9', + [arbitrumNova.id]: '0x9B523BF5F77e8d90e0E9eb0924aEA6E40B081aE6', + [base.id]: '0x091b8FC0F48613b191f81009797ce55Cf97Af7C8', + // testnet L1 + [sepolia.id]: '0xfb774ea8a92ae528a596c8d90cbcf1bdbc4cee79', + [holesky.id]: '0x03c70F125Df471E4fd0515ca38504edFE6900F19', + // testnet L2 + [arbitrumSepolia.id]: '0xd2Ec8376B1dF436fAb18120E416d3F2BeC61275b', + [baseSepolia.id]: '0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502', + // local nitro-testnode (on "release" branch with --tokenbridge --l3node --l3-token-bridge flags) + [nitroTestnodeL1.id]: '0x82a3c114b40ecf1fc34745400a1b9b9115c33d31', + [nitroTestnodeL2.id]: '0x4287839696d650a0cf93b98351e85199102335d0', + }, + }, { name: 'TokenBridgeCreator', version: '1.2', @@ -156,8 +177,8 @@ const contracts: ContractConfig[] = [ [arbitrumSepolia.id]: '0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E', [baseSepolia.id]: '0xFC71d21a4FE10Cc0d34745ba9c713836f82f8DE3', // local nitro-testnode (on "release" branch with --tokenbridge --l3node --l3-token-bridge flags) - [nitroTestnodeL1.id]: '0x54B4D4e578E10178a6cA602bdb6df0F213296Af4', - [nitroTestnodeL2.id]: '0x38f35af53bf913c439eab06a367e09d6eb253492', + [nitroTestnodeL1.id]: '0x4Af567288e68caD4aA93A272fe6139Ca53859C70', + [nitroTestnodeL2.id]: '0x38F35Af53bF913c439eaB06A367e09D6eb253492', }, }, { @@ -189,7 +210,7 @@ export async function assertContractAbisMatch(contract: ContractConfig) { return; } - console.log(`- ${contract.name}`); + console.log(`- ${contract.name}${contract.version ? ` v${contract.version}` : ''}`); const abiHashes = await Promise.all( Object.entries(contract.address) @@ -218,7 +239,7 @@ export async function assertContractAbisMatch(contract: ContractConfig) { throw new Error(`- ${contract.name}`); } - console.log(`- ${contract.name} ✔\n`); + console.log(`- ${contract.name}${contract.version ? ` v${contract.version}` : ''} ✔\n`); } async function updateContractWithImplementationIfProxy(contract: ContractConfig) { @@ -265,6 +286,7 @@ export default async function () { etherscan({ chainId: arbitrumSepolia.id, apiKey: arbiscanApiKey, + // todo: fix viem type issue contracts: [contract], cacheDuration: 0, }), From 414d08a36b0b55cb52fe574ee559f8c29083aff7 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 13 Aug 2024 18:07:31 +0200 Subject: [PATCH 17/54] feat: add utils for wasm module root (#155) --- ...upPrepareDeploymentParamsConfigDefaults.ts | 6 +- src/index.ts | 13 +++ src/wasmModuleRoot.ts | 82 +++++++++++++++++++ src/wasmModuleRoot.unit.test.ts | 30 +++++++ 4 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 src/wasmModuleRoot.ts create mode 100644 src/wasmModuleRoot.unit.test.ts diff --git a/src/createRollupPrepareDeploymentParamsConfigDefaults.ts b/src/createRollupPrepareDeploymentParamsConfigDefaults.ts index e1b52eca..2f17aa94 100644 --- a/src/createRollupPrepareDeploymentParamsConfigDefaults.ts +++ b/src/createRollupPrepareDeploymentParamsConfigDefaults.ts @@ -1,14 +1,12 @@ import { parseEther, zeroAddress } from 'viem'; -export const wasmModuleRoot: `0x${string}` = - // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v20 - '0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4'; +import { getWasmModuleRoot } from './wasmModuleRoot'; export const defaults = { extraChallengeTimeBlocks: BigInt(0), stakeToken: zeroAddress, baseStake: parseEther(String(0.1)), - wasmModuleRoot, + wasmModuleRoot: getWasmModuleRoot(20), loserStakeEscrow: zeroAddress, genesisBlockNum: BigInt(0), } as const; diff --git a/src/index.ts b/src/index.ts index e3b532ea..01709be5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -124,6 +124,13 @@ import { setAnyTrustFastConfirmerPrepareTransactionRequest, SetAnyTrustFastConfirmerPrepareTransactionRequestParams, } from './setAnyTrustFastConfirmerPrepareTransactionRequest'; +import { + ConsensusVersion, + WasmModuleRoot, + GetWasmModuleRoot, + getWasmModuleRoot, + isKnownWasmModuleRoot, +} from './wasmModuleRoot'; export { arbOwnerPublicActions, @@ -228,4 +235,10 @@ export { CreateSafeTransactionReceipt, setAnyTrustFastConfirmerPrepareTransactionRequest, SetAnyTrustFastConfirmerPrepareTransactionRequestParams, + // + ConsensusVersion, + WasmModuleRoot, + GetWasmModuleRoot, + getWasmModuleRoot, + isKnownWasmModuleRoot, }; diff --git a/src/wasmModuleRoot.ts b/src/wasmModuleRoot.ts new file mode 100644 index 00000000..e97abb77 --- /dev/null +++ b/src/wasmModuleRoot.ts @@ -0,0 +1,82 @@ +import { Hex } from 'viem'; + +export type ConsensusRelease = { + version: number; + wasmModuleRoot: Hex; +}; + +const consensusReleases = [ + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v10 + version: 10, + wasmModuleRoot: '0x6b94a7fc388fd8ef3def759297828dc311761e88d8179c7ee8d3887dc554f3c3', + }, + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v10.1 + version: 10.1, + wasmModuleRoot: '0xda4e3ad5e7feacb817c21c8d0220da7650fe9051ece68a3f0b1c5d38bbb27b21', + }, + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v10.2 + version: 10.2, + wasmModuleRoot: '0x0754e09320c381566cc0449904c377a52bd34a6b9404432e80afd573b67f7b17', + }, + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v10.3 + version: 10.3, + wasmModuleRoot: '0xf559b6d4fa869472dabce70fe1c15221bdda837533dfd891916836975b434dec', + }, + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v11 + version: 11, + wasmModuleRoot: '0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a', + }, + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v11.1 + version: 11.1, + wasmModuleRoot: '0x68e4fe5023f792d4ef584796c84d710303a5e12ea02d6e37e2b5e9c4332507c4', + }, + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v20 + version: 20, + wasmModuleRoot: '0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4', + }, + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v30 + version: 30, + wasmModuleRoot: '0xb0de9cb89e4d944ae6023a3b62276e54804c242fd8c4c2d8e6cc4450f5fa8b1b', + }, + { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v31 + version: 31, + wasmModuleRoot: '0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69', + }, +] as const satisfies readonly ConsensusRelease[]; + +type ConsensusReleases = typeof consensusReleases; + +export type ConsensusVersion = ConsensusReleases[number]['version']; +export type WasmModuleRoot = ConsensusReleases[number]['wasmModuleRoot']; + +export type GetWasmModuleRoot = Extract< + ConsensusReleases[number], + { version: TConsensusVersion } +>['wasmModuleRoot']; + +export function getWasmModuleRoot( + consensusVersion: TConsensusVersion, +): GetWasmModuleRoot { + const wasmModuleRoot = consensusReleases + // + .find((release) => release.version === consensusVersion)!.wasmModuleRoot; + + return wasmModuleRoot as GetWasmModuleRoot; +} + +export function isKnownWasmModuleRoot(wasmModuleRoot: Hex): wasmModuleRoot is WasmModuleRoot { + return ( + (consensusReleases.map((release) => release.wasmModuleRoot) as Hex[]) + // + .includes(wasmModuleRoot) + ); +} diff --git a/src/wasmModuleRoot.unit.test.ts b/src/wasmModuleRoot.unit.test.ts new file mode 100644 index 00000000..3bd37c67 --- /dev/null +++ b/src/wasmModuleRoot.unit.test.ts @@ -0,0 +1,30 @@ +import { describe, it, expect } from 'vitest'; + +import { isKnownWasmModuleRoot } from './wasmModuleRoot'; + +describe('isKnownWasmModuleRoot', () => { + it('returns true for a known wasm module root', () => { + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v10.1 + expect( + isKnownWasmModuleRoot('0xda4e3ad5e7feacb817c21c8d0220da7650fe9051ece68a3f0b1c5d38bbb27b21'), + ).toEqual(true); + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v11 + expect( + isKnownWasmModuleRoot('0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a'), + ).toEqual(true); + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v20 + expect( + isKnownWasmModuleRoot('0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4'), + ).toEqual(true); + // https://github.com/OffchainLabs/nitro/releases/tag/consensus-v31 + expect( + isKnownWasmModuleRoot('0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69'), + ).toEqual(true); + }); + + it('returns false for an unknown wasm module root', () => { + expect( + isKnownWasmModuleRoot('0x58e4fe5023f792d4ef584796c84d710303a5e12ea02d6e37e2b5e9c4332507c2'), + ).toEqual(false); + }); +}); From b52e6d7d02a92438d5a77b83518b370c995fc045 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 13 Aug 2024 18:32:37 +0200 Subject: [PATCH 18/54] feat: use consensus v31 wasm module root (#164) --- ...eRollupPrepareDeploymentParamsConfig.unit.test.ts.snap | 8 ++++---- src/createRollupPrepareDeploymentParamsConfigDefaults.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap b/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap index 4ad4cbcf..cc2e0d3d 100644 --- a/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap +++ b/src/__snapshots__/createRollupPrepareDeploymentParamsConfig.unit.test.ts.snap @@ -17,7 +17,7 @@ exports[`creates config for a chain on top of arbitrum one with defaults 1`] = ` "futureSeconds": 3600n, }, "stakeToken": "0x0000000000000000000000000000000000000000", - "wasmModuleRoot": "0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4", + "wasmModuleRoot": "0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69", } `; @@ -59,7 +59,7 @@ exports[`creates config for a chain on top of arbitrum sepolia with defaults 1`] "futureSeconds": 3600n, }, "stakeToken": "0x0000000000000000000000000000000000000000", - "wasmModuleRoot": "0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4", + "wasmModuleRoot": "0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69", } `; @@ -101,7 +101,7 @@ exports[`creates config for a chain on top of base sepolia with defaults 1`] = ` "futureSeconds": 3600n, }, "stakeToken": "0x0000000000000000000000000000000000000000", - "wasmModuleRoot": "0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4", + "wasmModuleRoot": "0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69", } `; @@ -122,6 +122,6 @@ exports[`creates config for a chain on top of base with defaults 1`] = ` "futureSeconds": 3600n, }, "stakeToken": "0x0000000000000000000000000000000000000000", - "wasmModuleRoot": "0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4", + "wasmModuleRoot": "0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69", } `; diff --git a/src/createRollupPrepareDeploymentParamsConfigDefaults.ts b/src/createRollupPrepareDeploymentParamsConfigDefaults.ts index 2f17aa94..941383ec 100644 --- a/src/createRollupPrepareDeploymentParamsConfigDefaults.ts +++ b/src/createRollupPrepareDeploymentParamsConfigDefaults.ts @@ -6,7 +6,7 @@ export const defaults = { extraChallengeTimeBlocks: BigInt(0), stakeToken: zeroAddress, baseStake: parseEther(String(0.1)), - wasmModuleRoot: getWasmModuleRoot(20), + wasmModuleRoot: getWasmModuleRoot(31), loserStakeEscrow: zeroAddress, genesisBlockNum: BigInt(0), } as const; From c65c3464e6b957b914131af5177bbe5dd465d703 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 14 Aug 2024 11:10:59 +0200 Subject: [PATCH 19/54] chore: bump version --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 98f07c9d..2b451a50 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.17.2", + "version": "0.18.0-beta.0", "main": "./dist/index.js", "files": [ "./dist" From 45745e86a51eb2590d1b802b6b25b8e8f834e3f0 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 14 Aug 2024 12:12:52 +0200 Subject: [PATCH 20/54] feat: add getConsensusVersion util (#166) --- src/index.ts | 4 ++++ src/wasmModuleRoot.ts | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/index.ts b/src/index.ts index 01709be5..48c3f43d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -130,6 +130,8 @@ import { GetWasmModuleRoot, getWasmModuleRoot, isKnownWasmModuleRoot, + GetConsensusVersion, + getConsensusVersion, } from './wasmModuleRoot'; export { @@ -241,4 +243,6 @@ export { GetWasmModuleRoot, getWasmModuleRoot, isKnownWasmModuleRoot, + GetConsensusVersion, + getConsensusVersion, }; diff --git a/src/wasmModuleRoot.ts b/src/wasmModuleRoot.ts index e97abb77..a4145356 100644 --- a/src/wasmModuleRoot.ts +++ b/src/wasmModuleRoot.ts @@ -80,3 +80,18 @@ export function isKnownWasmModuleRoot(wasmModuleRoot: Hex): wasmModuleRoot is Wa .includes(wasmModuleRoot) ); } + +export type GetConsensusVersion = Extract< + ConsensusReleases[number], + { wasmModuleRoot: TWasmModuleRoot } +>['version']; + +export function getConsensusVersion( + wasmModuleRoot: TWasmModuleRoot, +): GetConsensusVersion { + const consensusVersion = consensusReleases + // + .find((release) => release.wasmModuleRoot === wasmModuleRoot)!.version; + + return consensusVersion as GetConsensusVersion; +} From 011748c530894a06676bfd2ce1fc25ce9b4d9789 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 14 Aug 2024 13:49:04 +0200 Subject: [PATCH 21/54] feat: update wasm utils as consensus release utils (#167) --- ...upPrepareDeploymentParamsConfigDefaults.ts | 4 +- src/index.ts | 16 +++---- src/wasmModuleRoot.ts | 46 +++++++++---------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/createRollupPrepareDeploymentParamsConfigDefaults.ts b/src/createRollupPrepareDeploymentParamsConfigDefaults.ts index 941383ec..081ccc40 100644 --- a/src/createRollupPrepareDeploymentParamsConfigDefaults.ts +++ b/src/createRollupPrepareDeploymentParamsConfigDefaults.ts @@ -1,12 +1,12 @@ import { parseEther, zeroAddress } from 'viem'; -import { getWasmModuleRoot } from './wasmModuleRoot'; +import { getConsensusReleaseByVersion } from './wasmModuleRoot'; export const defaults = { extraChallengeTimeBlocks: BigInt(0), stakeToken: zeroAddress, baseStake: parseEther(String(0.1)), - wasmModuleRoot: getWasmModuleRoot(31), + wasmModuleRoot: getConsensusReleaseByVersion(31).wasmModuleRoot, loserStakeEscrow: zeroAddress, genesisBlockNum: BigInt(0), } as const; diff --git a/src/index.ts b/src/index.ts index 48c3f43d..9803fc7b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -126,12 +126,12 @@ import { } from './setAnyTrustFastConfirmerPrepareTransactionRequest'; import { ConsensusVersion, + getConsensusReleaseByVersion, + GetConsensusReleaseByVersion, WasmModuleRoot, - GetWasmModuleRoot, - getWasmModuleRoot, isKnownWasmModuleRoot, - GetConsensusVersion, - getConsensusVersion, + getConsensusReleaseByWasmModuleRoot, + GetConsensusReleaseByWasmModuleRoot, } from './wasmModuleRoot'; export { @@ -239,10 +239,10 @@ export { SetAnyTrustFastConfirmerPrepareTransactionRequestParams, // ConsensusVersion, + getConsensusReleaseByVersion, + GetConsensusReleaseByVersion, WasmModuleRoot, - GetWasmModuleRoot, - getWasmModuleRoot, isKnownWasmModuleRoot, - GetConsensusVersion, - getConsensusVersion, + getConsensusReleaseByWasmModuleRoot, + GetConsensusReleaseByWasmModuleRoot, }; diff --git a/src/wasmModuleRoot.ts b/src/wasmModuleRoot.ts index a4145356..a496dc0a 100644 --- a/src/wasmModuleRoot.ts +++ b/src/wasmModuleRoot.ts @@ -1,6 +1,6 @@ import { Hex } from 'viem'; -export type ConsensusRelease = { +type ConsensusRelease = { version: number; wasmModuleRoot: Hex; }; @@ -58,40 +58,40 @@ type ConsensusReleases = typeof consensusReleases; export type ConsensusVersion = ConsensusReleases[number]['version']; export type WasmModuleRoot = ConsensusReleases[number]['wasmModuleRoot']; -export type GetWasmModuleRoot = Extract< +export type GetConsensusReleaseByVersion = Extract< ConsensusReleases[number], { version: TConsensusVersion } ->['wasmModuleRoot']; +>; -export function getWasmModuleRoot( +export function getConsensusReleaseByVersion( consensusVersion: TConsensusVersion, -): GetWasmModuleRoot { - const wasmModuleRoot = consensusReleases +): GetConsensusReleaseByVersion { + const consensusRelease = consensusReleases // - .find((release) => release.version === consensusVersion)!.wasmModuleRoot; + .find((release) => release.version === consensusVersion); - return wasmModuleRoot as GetWasmModuleRoot; + return consensusRelease as GetConsensusReleaseByVersion; } -export function isKnownWasmModuleRoot(wasmModuleRoot: Hex): wasmModuleRoot is WasmModuleRoot { - return ( - (consensusReleases.map((release) => release.wasmModuleRoot) as Hex[]) - // - .includes(wasmModuleRoot) - ); -} - -export type GetConsensusVersion = Extract< +export type GetConsensusReleaseByWasmModuleRoot = Extract< ConsensusReleases[number], { wasmModuleRoot: TWasmModuleRoot } ->['version']; +>; -export function getConsensusVersion( +export function getConsensusReleaseByWasmModuleRoot( wasmModuleRoot: TWasmModuleRoot, -): GetConsensusVersion { - const consensusVersion = consensusReleases +): GetConsensusReleaseByWasmModuleRoot { + const consensusRelease = consensusReleases // - .find((release) => release.wasmModuleRoot === wasmModuleRoot)!.version; + .find((release) => release.wasmModuleRoot === wasmModuleRoot); - return consensusVersion as GetConsensusVersion; + return consensusRelease as GetConsensusReleaseByWasmModuleRoot; +} + +export function isKnownWasmModuleRoot(wasmModuleRoot: Hex): wasmModuleRoot is WasmModuleRoot { + return ( + (consensusReleases.map((release) => release.wasmModuleRoot) as Hex[]) + // + .includes(wasmModuleRoot) + ); } From 9dc8568cedac20a3187ed2498076b98752eb2f9e Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 14 Aug 2024 17:36:10 +0200 Subject: [PATCH 22/54] chore: update token bridge contracts (#165) --- src/package.json | 2 +- token-bridge-contracts/Dockerfile | 4 ++-- yarn.lock | 23 ++++++++++++++--------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/package.json b/src/package.json index 2b451a50..82dcbcd7 100644 --- a/src/package.json +++ b/src/package.json @@ -45,7 +45,7 @@ }, "dependencies": { "@arbitrum/sdk": "^4.0.0", - "@arbitrum/token-bridge-contracts": "^1.2.1", + "@arbitrum/token-bridge-contracts": "^1.2.2", "@offchainlabs/fund-distribution-contracts": "^1.0.1", "@safe-global/protocol-kit": "^4.0.2", "ethers": "^5.7.2" diff --git a/token-bridge-contracts/Dockerfile b/token-bridge-contracts/Dockerfile index c27a7a01..b634d726 100644 --- a/token-bridge-contracts/Dockerfile +++ b/token-bridge-contracts/Dockerfile @@ -1,8 +1,8 @@ -FROM node:16-bullseye-slim +FROM node:18-bullseye-slim RUN apt-get update && \ apt-get install -y git docker.io python3 chromium build-essential WORKDIR /workspace -RUN git clone -b v1.2.0 https://github.com/OffchainLabs/token-bridge-contracts.git ./ +RUN git clone -b v1.2.2 https://github.com/OffchainLabs/token-bridge-contracts.git ./ RUN yarn install RUN yarn build ENTRYPOINT ["yarn"] diff --git a/yarn.lock b/yarn.lock index bcb0e722..8de44fa9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33,10 +33,10 @@ async-mutex "^0.4.0" ethers "^5.1.0" -"@arbitrum/token-bridge-contracts@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@arbitrum/token-bridge-contracts/-/token-bridge-contracts-1.2.1.tgz#4838d70182bc0d6b36adfd733d7b4650e596c979" - integrity sha512-ngKeay/0O91QyVLCbcd2pyJIWtzKi2KsPm+O9q3xCfPkjuCZ0+MK5OdhYKCbvGc0jf39R7izRsvmUHE0qA603A== +"@arbitrum/token-bridge-contracts@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@arbitrum/token-bridge-contracts/-/token-bridge-contracts-1.2.2.tgz#abc1cea9e03694b9c5395c95a23bdd4b607c4b75" + integrity sha512-PAAJpnAtql7/xPc2o437m+f47tuGVcwEsbvEuoLinOE1nENVx26luXRON2ONMouwg1D/F05DYpmcuxODJ+rHJg== dependencies: "@arbitrum/nitro-contracts" "1.1.1" "@offchainlabs/upgrade-executor" "1.1.0-beta.0" @@ -3703,12 +3703,17 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@7.4.6, ws@7.5.10: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== -ws@8.13.0, ws@8.17.1: +ws@8.17.1: version "8.17.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== From b4634bae93af452966beaeccd9ff1770c53fd686 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 14 Aug 2024 19:17:54 +0200 Subject: [PATCH 23/54] feat: reduce config options in prepareChainConfig (#169) --- .../prepareChainConfig.unit.test.ts.snap | 36 ++++++------ src/index.ts | 8 ++- src/prepareChainConfig.ts | 24 +++++--- src/prepareChainConfig.unit.test.ts | 30 ++-------- src/types/ChainConfig.ts | 2 +- src/types/utils.ts | 55 +++++++++++++++++++ 6 files changed, 102 insertions(+), 53 deletions(-) diff --git a/src/__snapshots__/prepareChainConfig.unit.test.ts.snap b/src/__snapshots__/prepareChainConfig.unit.test.ts.snap index 62e7949f..887a30dd 100644 --- a/src/__snapshots__/prepareChainConfig.unit.test.ts.snap +++ b/src/__snapshots__/prepareChainConfig.unit.test.ts.snap @@ -3,34 +3,34 @@ exports[`creates chain config with custom params 1`] = ` { "arbitrum": { - "AllowDebugPrecompiles": true, + "AllowDebugPrecompiles": false, "DataAvailabilityCommittee": true, - "EnableArbOS": false, - "GenesisBlockNum": 1, + "EnableArbOS": true, + "GenesisBlockNum": 0, "InitialArbOSVersion": 20, "InitialChainOwner": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "MaxCodeSize": 40960, "MaxInitCodeSize": 81920, }, - "berlinBlock": 1, - "byzantiumBlock": 1, + "berlinBlock": 0, + "byzantiumBlock": 0, "chainId": 69420, "clique": { - "epoch": 1, - "period": 1, + "epoch": 0, + "period": 0, }, - "constantinopleBlock": 1, + "constantinopleBlock": 0, "daoForkBlock": null, - "daoForkSupport": false, - "eip150Block": 1, - "eip150Hash": "0x1100000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 1, - "eip158Block": 1, - "homesteadBlock": 1, - "istanbulBlock": 1, - "londonBlock": 1, - "muirGlacierBlock": 1, - "petersburgBlock": 1, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "homesteadBlock": 0, + "istanbulBlock": 0, + "londonBlock": 0, + "muirGlacierBlock": 0, + "petersburgBlock": 0, } `; diff --git a/src/index.ts b/src/index.ts index 9803fc7b..3f143780 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,11 @@ import { CreateRollupPrepareDeploymentParamsConfigParams, CreateRollupPrepareDeploymentParamsConfigResult, } from './createRollupPrepareDeploymentParamsConfig'; -import { prepareChainConfig, PrepareChainConfigParams } from './prepareChainConfig'; +import { + prepareChainConfig, + PrepareChainConfigParams, + PrepareChainConfigArbitrumParams, +} from './prepareChainConfig'; import { createRollupEnoughCustomFeeTokenAllowance, CreateRollupEnoughCustomFeeTokenAllowanceParams, @@ -151,6 +155,8 @@ export { // prepareChainConfig, PrepareChainConfigParams, + PrepareChainConfigArbitrumParams, + // createRollupEnoughCustomFeeTokenAllowance, CreateRollupEnoughCustomFeeTokenAllowanceParams, createRollupPrepareCustomFeeTokenApprovalTransactionRequest, diff --git a/src/prepareChainConfig.ts b/src/prepareChainConfig.ts index a32f48c8..990a438a 100644 --- a/src/prepareChainConfig.ts +++ b/src/prepareChainConfig.ts @@ -1,3 +1,4 @@ +import { ExcludeSome, Prettify, RequireSome } from './types/utils'; import { ChainConfig, ChainConfigArbitrumParams } from './types/ChainConfig'; export const defaults = { @@ -30,17 +31,26 @@ export const defaults = { }, }; -export type PrepareChainConfigParams = Pick & - Partial> & { - arbitrum: Pick & - Partial>; - }; +export type PrepareChainConfigParams = Prettify< + Pick & { + arbitrum: PrepareChainConfigArbitrumParams; + } +>; + +export type PrepareChainConfigArbitrumParams = RequireSome< + // exclude some fields that shouldn't be changed + ExcludeSome< + ChainConfigArbitrumParams, + 'EnableArbOS' | 'GenesisBlockNum' | 'AllowDebugPrecompiles' + >, + // make InitialChainOwner required + 'InitialChainOwner' +>; export function prepareChainConfig(params: PrepareChainConfigParams): ChainConfig { return { ...defaults, - ...params, - clique: { ...defaults.clique, ...params.clique }, + chainId: params.chainId, arbitrum: { ...defaults.arbitrum, ...params.arbitrum }, }; } diff --git a/src/prepareChainConfig.unit.test.ts b/src/prepareChainConfig.unit.test.ts index e289f203..c3edd71b 100644 --- a/src/prepareChainConfig.unit.test.ts +++ b/src/prepareChainConfig.unit.test.ts @@ -1,7 +1,6 @@ import { it, expect } from 'vitest'; -import { ChainConfig } from './types/ChainConfig'; -import { prepareChainConfig } from './prepareChainConfig'; +import { prepareChainConfig, PrepareChainConfigParams } from './prepareChainConfig'; const chainId = 69_420; const vitalik: `0x${string}` = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'; @@ -18,33 +17,12 @@ it('creates chain config with defaults', () => { }); it('creates chain config with custom params', () => { - const params: ChainConfig = { + const params: PrepareChainConfigParams = { chainId, - homesteadBlock: 1, - daoForkBlock: null, - daoForkSupport: false, - eip150Block: 1, - eip150Hash: '0x1100000000000000000000000000000000000000000000000000000000000000', - eip155Block: 1, - eip158Block: 1, - byzantiumBlock: 1, - constantinopleBlock: 1, - petersburgBlock: 1, - istanbulBlock: 1, - muirGlacierBlock: 1, - berlinBlock: 1, - londonBlock: 1, - clique: { - period: 1, - epoch: 1, - }, arbitrum: { - EnableArbOS: false, - AllowDebugPrecompiles: true, - DataAvailabilityCommittee: true, - InitialArbOSVersion: 20, InitialChainOwner: vitalik, - GenesisBlockNum: 1, + InitialArbOSVersion: 20, + DataAvailabilityCommittee: true, MaxCodeSize: 40 * 1024, MaxInitCodeSize: 80 * 1024, }, diff --git a/src/types/ChainConfig.ts b/src/types/ChainConfig.ts index 26bb0e8a..83061b59 100644 --- a/src/types/ChainConfig.ts +++ b/src/types/ChainConfig.ts @@ -3,9 +3,9 @@ import { Address } from 'viem'; export type ChainConfigArbitrumParams = { EnableArbOS: boolean; AllowDebugPrecompiles: boolean; - DataAvailabilityCommittee: boolean; InitialArbOSVersion: number; InitialChainOwner: Address; + DataAvailabilityCommittee: boolean; GenesisBlockNum: number; MaxCodeSize: number; MaxInitCodeSize: number; diff --git a/src/types/utils.ts b/src/types/utils.ts index d968f1d0..4241ba1e 100644 --- a/src/types/utils.ts +++ b/src/types/utils.ts @@ -6,3 +6,58 @@ export type Prettify = { } & {}; export type GetFunctionName = Extract['name']; + +/** + * Creates a new type by making the specified keys required while keeping the remaining keys optional. + * + * @template T - The original object type. + * @template K - The keys in `T` that should be required in the resulting type. + * + * @example + * type Original = { + * a: number; + * b: string; + * c: boolean; + * }; + * + * type RequiredAandB = RequireSome; + * // Resulting type: + * // { + * // a: number; // Required + * // b: string; // Required + * // c?: boolean; // Optional + * //} + */ +export type RequireSome = Prettify< + { + [P in K]: T[P]; + } & { + [P in Exclude]?: T[P]; + } +>; + +/** + * Creates a new type by excluding the specified keys from the original type. + * + * @template T - The original object type. + * @template K - The keys in `T` that should be excluded from the resulting type. + * + * @example + * type Original = { + * a: number; + * b: string; + * c: boolean; + * d: string; + * }; + * + * type ExcludeD = ExcludeSome; + * // Resulting type: + * // { + * // a: number; + * // b: string; + * // c: boolean; + * //} + */ +export type ExcludeSome = Prettify<{ + [P in Exclude]: T[P]; +}>; From 9b33e2f1c421bb1d7e4c260f908346b96643a1d2 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Thu, 15 Aug 2024 16:00:01 +0200 Subject: [PATCH 24/54] chore: update yarn.lock --- yarn.lock | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8de44fa9..493cf387 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3703,17 +3703,12 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@7.4.6, ws@7.5.10: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -ws@8.13.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - -ws@8.17.1: +ws@8.13.0, ws@8.17.1: version "8.17.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== From 143d415470b96b77cade2b571bfdeffb41e77102 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Thu, 15 Aug 2024 16:13:17 +0200 Subject: [PATCH 25/54] chore: bump version --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 82dcbcd7..88945982 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.18.0-beta.0", + "version": "0.18.0-beta.1", "main": "./dist/index.js", "files": [ "./dist" From 057a7f06dcf0bb2f1a60d76c108c6a20cbcf3029 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Thu, 15 Aug 2024 18:56:19 +0200 Subject: [PATCH 26/54] feat: add nitro contracts v2.1 abis (#168) --- src/contracts/Rollup.ts | 1801 ----------------- src/contracts/Rollup/index.ts | 2 + src/contracts/Rollup/v1.1.ts | 844 ++++++++ src/contracts/Rollup/v2.1.ts | 858 ++++++++ src/contracts/SequencerInbox/index.ts | 2 + .../v1.1.ts} | 0 src/contracts/SequencerInbox/v2.1.ts | 487 +++++ src/getBatchPosters.unit.test.ts | 17 +- src/getValidators.unit.test.ts | 11 +- 9 files changed, 2214 insertions(+), 1808 deletions(-) delete mode 100644 src/contracts/Rollup.ts create mode 100644 src/contracts/Rollup/index.ts create mode 100644 src/contracts/Rollup/v1.1.ts create mode 100644 src/contracts/Rollup/v2.1.ts create mode 100644 src/contracts/SequencerInbox/index.ts rename src/contracts/{SequencerInbox.ts => SequencerInbox/v1.1.ts} (100%) create mode 100644 src/contracts/SequencerInbox/v2.1.ts diff --git a/src/contracts/Rollup.ts b/src/contracts/Rollup.ts deleted file mode 100644 index 0fe25e92..00000000 --- a/src/contracts/Rollup.ts +++ /dev/null @@ -1,1801 +0,0 @@ -// from @arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory -// needs to be copied into this codebase because it is not cast to const in arbitrum sdk -export const rollupABI = [ - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: 'address', - name: 'previousAdmin', - type: 'address', - }, - { - indexed: false, - internalType: 'address', - name: 'newAdmin', - type: 'address', - }, - ], - name: 'AdminChanged', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'address', - name: 'beacon', - type: 'address', - }, - ], - name: 'BeaconUpgraded', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'uint64', - name: 'nodeNum', - type: 'uint64', - }, - { - indexed: false, - internalType: 'bytes32', - name: 'blockHash', - type: 'bytes32', - }, - { - indexed: false, - internalType: 'bytes32', - name: 'sendRoot', - type: 'bytes32', - }, - ], - name: 'NodeConfirmed', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'uint64', - name: 'nodeNum', - type: 'uint64', - }, - { - indexed: true, - internalType: 'bytes32', - name: 'parentNodeHash', - type: 'bytes32', - }, - { - indexed: true, - internalType: 'bytes32', - name: 'nodeHash', - type: 'bytes32', - }, - { - indexed: false, - internalType: 'bytes32', - name: 'executionHash', - type: 'bytes32', - }, - { - components: [ - { - components: [ - { - components: [ - { - internalType: 'bytes32[2]', - name: 'bytes32Vals', - type: 'bytes32[2]', - }, - { - internalType: 'uint64[2]', - name: 'u64Vals', - type: 'uint64[2]', - }, - ], - internalType: 'struct GlobalState', - name: 'globalState', - type: 'tuple', - }, - { - internalType: 'enum MachineStatus', - name: 'machineStatus', - type: 'uint8', - }, - ], - internalType: 'struct ExecutionState', - name: 'beforeState', - type: 'tuple', - }, - { - components: [ - { - components: [ - { - internalType: 'bytes32[2]', - name: 'bytes32Vals', - type: 'bytes32[2]', - }, - { - internalType: 'uint64[2]', - name: 'u64Vals', - type: 'uint64[2]', - }, - ], - internalType: 'struct GlobalState', - name: 'globalState', - type: 'tuple', - }, - { - internalType: 'enum MachineStatus', - name: 'machineStatus', - type: 'uint8', - }, - ], - internalType: 'struct ExecutionState', - name: 'afterState', - type: 'tuple', - }, - { - internalType: 'uint64', - name: 'numBlocks', - type: 'uint64', - }, - ], - indexed: false, - internalType: 'struct Assertion', - name: 'assertion', - type: 'tuple', - }, - { - indexed: false, - internalType: 'bytes32', - name: 'afterInboxBatchAcc', - type: 'bytes32', - }, - { - indexed: false, - internalType: 'bytes32', - name: 'wasmModuleRoot', - type: 'bytes32', - }, - { - indexed: false, - internalType: 'uint256', - name: 'inboxMaxCount', - type: 'uint256', - }, - ], - name: 'NodeCreated', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'uint64', - name: 'nodeNum', - type: 'uint64', - }, - ], - name: 'NodeRejected', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'uint256', - name: 'id', - type: 'uint256', - }, - ], - name: 'OwnerFunctionCalled', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: 'address', - name: 'account', - type: 'address', - }, - ], - name: 'Paused', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'uint64', - name: 'challengeIndex', - type: 'uint64', - }, - { - indexed: false, - internalType: 'address', - name: 'asserter', - type: 'address', - }, - { - indexed: false, - internalType: 'address', - name: 'challenger', - type: 'address', - }, - { - indexed: false, - internalType: 'uint64', - name: 'challengedNode', - type: 'uint64', - }, - ], - name: 'RollupChallengeStarted', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: 'bytes32', - name: 'machineHash', - type: 'bytes32', - }, - { - indexed: false, - internalType: 'uint256', - name: 'chainId', - type: 'uint256', - }, - ], - name: 'RollupInitialized', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: 'address', - name: 'account', - type: 'address', - }, - ], - name: 'Unpaused', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'address', - name: 'implementation', - type: 'address', - }, - ], - name: 'Upgraded', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'address', - name: 'implementation', - type: 'address', - }, - ], - name: 'UpgradedSecondary', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'address', - name: 'user', - type: 'address', - }, - { - indexed: false, - internalType: 'uint256', - name: 'initialBalance', - type: 'uint256', - }, - { - indexed: false, - internalType: 'uint256', - name: 'finalBalance', - type: 'uint256', - }, - ], - name: 'UserStakeUpdated', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'address', - name: 'user', - type: 'address', - }, - { - indexed: false, - internalType: 'uint256', - name: 'initialBalance', - type: 'uint256', - }, - { - indexed: false, - internalType: 'uint256', - name: 'finalBalance', - type: 'uint256', - }, - ], - name: 'UserWithdrawableFundsUpdated', - type: 'event', - }, - { - inputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - name: '_stakerMap', - outputs: [ - { - internalType: 'uint256', - name: 'amountStaked', - type: 'uint256', - }, - { - internalType: 'uint64', - name: 'index', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'latestStakedNode', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'currentChallenge', - type: 'uint64', - }, - { - internalType: 'bool', - name: 'isStaked', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'staker', - type: 'address', - }, - ], - name: 'amountStaked', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'baseStake', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'bridge', - outputs: [ - { - internalType: 'contract IBridge', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'chainId', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'challengeManager', - outputs: [ - { - internalType: 'contract IChallengeManager', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'confirmPeriodBlocks', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - components: [ - { - components: [ - { - components: [ - { - internalType: 'bytes32[2]', - name: 'bytes32Vals', - type: 'bytes32[2]', - }, - { - internalType: 'uint64[2]', - name: 'u64Vals', - type: 'uint64[2]', - }, - ], - internalType: 'struct GlobalState', - name: 'globalState', - type: 'tuple', - }, - { - internalType: 'enum MachineStatus', - name: 'machineStatus', - type: 'uint8', - }, - ], - internalType: 'struct ExecutionState', - name: 'beforeState', - type: 'tuple', - }, - { - components: [ - { - components: [ - { - internalType: 'bytes32[2]', - name: 'bytes32Vals', - type: 'bytes32[2]', - }, - { - internalType: 'uint64[2]', - name: 'u64Vals', - type: 'uint64[2]', - }, - ], - internalType: 'struct GlobalState', - name: 'globalState', - type: 'tuple', - }, - { - internalType: 'enum MachineStatus', - name: 'machineStatus', - type: 'uint8', - }, - ], - internalType: 'struct ExecutionState', - name: 'afterState', - type: 'tuple', - }, - { - internalType: 'uint64', - name: 'numBlocks', - type: 'uint64', - }, - ], - internalType: 'struct Assertion', - name: 'assertion', - type: 'tuple', - }, - ], - name: 'createNitroMigrationGenesis', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'staker', - type: 'address', - }, - ], - name: 'currentChallenge', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'extraChallengeTimeBlocks', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'firstUnresolvedNode', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint64', - name: 'nodeNum', - type: 'uint64', - }, - { - internalType: 'bytes32', - name: 'blockHash', - type: 'bytes32', - }, - { - internalType: 'bytes32', - name: 'sendRoot', - type: 'bytes32', - }, - ], - name: 'forceConfirmNode', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint64', - name: 'prevNode', - type: 'uint64', - }, - { - internalType: 'uint256', - name: 'prevNodeInboxMaxCount', - type: 'uint256', - }, - { - components: [ - { - components: [ - { - components: [ - { - internalType: 'bytes32[2]', - name: 'bytes32Vals', - type: 'bytes32[2]', - }, - { - internalType: 'uint64[2]', - name: 'u64Vals', - type: 'uint64[2]', - }, - ], - internalType: 'struct GlobalState', - name: 'globalState', - type: 'tuple', - }, - { - internalType: 'enum MachineStatus', - name: 'machineStatus', - type: 'uint8', - }, - ], - internalType: 'struct ExecutionState', - name: 'beforeState', - type: 'tuple', - }, - { - components: [ - { - components: [ - { - internalType: 'bytes32[2]', - name: 'bytes32Vals', - type: 'bytes32[2]', - }, - { - internalType: 'uint64[2]', - name: 'u64Vals', - type: 'uint64[2]', - }, - ], - internalType: 'struct GlobalState', - name: 'globalState', - type: 'tuple', - }, - { - internalType: 'enum MachineStatus', - name: 'machineStatus', - type: 'uint8', - }, - ], - internalType: 'struct ExecutionState', - name: 'afterState', - type: 'tuple', - }, - { - internalType: 'uint64', - name: 'numBlocks', - type: 'uint64', - }, - ], - internalType: 'struct Assertion', - name: 'assertion', - type: 'tuple', - }, - { - internalType: 'bytes32', - name: 'expectedNodeHash', - type: 'bytes32', - }, - ], - name: 'forceCreateNode', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address[]', - name: 'staker', - type: 'address[]', - }, - ], - name: 'forceRefundStaker', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address[]', - name: 'stakerA', - type: 'address[]', - }, - { - internalType: 'address[]', - name: 'stakerB', - type: 'address[]', - }, - ], - name: 'forceResolveChallenge', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint64', - name: 'nodeNum', - type: 'uint64', - }, - ], - name: 'getNode', - outputs: [ - { - components: [ - { - internalType: 'bytes32', - name: 'stateHash', - type: 'bytes32', - }, - { - internalType: 'bytes32', - name: 'challengeHash', - type: 'bytes32', - }, - { - internalType: 'bytes32', - name: 'confirmData', - type: 'bytes32', - }, - { - internalType: 'uint64', - name: 'prevNum', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'deadlineBlock', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'noChildConfirmedBeforeBlock', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'stakerCount', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'childStakerCount', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'firstChildBlock', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'latestChildNumber', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'createdAtBlock', - type: 'uint64', - }, - { - internalType: 'bytes32', - name: 'nodeHash', - type: 'bytes32', - }, - ], - internalType: 'struct Node', - name: '', - type: 'tuple', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint64', - name: 'nodeNum', - type: 'uint64', - }, - ], - name: 'getNodeCreationBlockForLogLookup', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'staker', - type: 'address', - }, - ], - name: 'getStaker', - outputs: [ - { - components: [ - { - internalType: 'uint256', - name: 'amountStaked', - type: 'uint256', - }, - { - internalType: 'uint64', - name: 'index', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'latestStakedNode', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'currentChallenge', - type: 'uint64', - }, - { - internalType: 'bool', - name: 'isStaked', - type: 'bool', - }, - ], - internalType: 'struct IRollupCore.Staker', - name: '', - type: 'tuple', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint64', - name: 'stakerNum', - type: 'uint64', - }, - ], - name: 'getStakerAddress', - outputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'inbox', - outputs: [ - { - internalType: 'contract IInboxBase', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - components: [ - { - internalType: 'uint64', - name: 'confirmPeriodBlocks', - type: 'uint64', - }, - { - internalType: 'uint64', - name: 'extraChallengeTimeBlocks', - type: 'uint64', - }, - { - internalType: 'address', - name: 'stakeToken', - type: 'address', - }, - { - internalType: 'uint256', - name: 'baseStake', - type: 'uint256', - }, - { - internalType: 'bytes32', - name: 'wasmModuleRoot', - type: 'bytes32', - }, - { - internalType: 'address', - name: 'owner', - type: 'address', - }, - { - internalType: 'address', - name: 'loserStakeEscrow', - type: 'address', - }, - { - internalType: 'uint256', - name: 'chainId', - type: 'uint256', - }, - { - internalType: 'string', - name: 'chainConfig', - type: 'string', - }, - { - internalType: 'uint64', - name: 'genesisBlockNum', - type: 'uint64', - }, - { - components: [ - { - internalType: 'uint256', - name: 'delayBlocks', - type: 'uint256', - }, - { - internalType: 'uint256', - name: 'futureBlocks', - type: 'uint256', - }, - { - internalType: 'uint256', - name: 'delaySeconds', - type: 'uint256', - }, - { - internalType: 'uint256', - name: 'futureSeconds', - type: 'uint256', - }, - ], - internalType: 'struct ISequencerInbox.MaxTimeVariation', - name: 'sequencerInboxMaxTimeVariation', - type: 'tuple', - }, - ], - internalType: 'struct Config', - name: 'config', - type: 'tuple', - }, - { - components: [ - { - internalType: 'contract IBridge', - name: 'bridge', - type: 'address', - }, - { - internalType: 'contract ISequencerInbox', - name: 'sequencerInbox', - type: 'address', - }, - { - internalType: 'contract IInboxBase', - name: 'inbox', - type: 'address', - }, - { - internalType: 'contract IOutbox', - name: 'outbox', - type: 'address', - }, - { - internalType: 'contract IRollupEventInbox', - name: 'rollupEventInbox', - type: 'address', - }, - { - internalType: 'contract IChallengeManager', - name: 'challengeManager', - type: 'address', - }, - { - internalType: 'address', - name: 'rollupAdminLogic', - type: 'address', - }, - { - internalType: 'contract IRollupUser', - name: 'rollupUserLogic', - type: 'address', - }, - { - internalType: 'address', - name: 'validatorUtils', - type: 'address', - }, - { - internalType: 'address', - name: 'validatorWalletCreator', - type: 'address', - }, - ], - internalType: 'struct ContractDependencies', - name: 'connectedContracts', - type: 'tuple', - }, - ], - name: 'initialize', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'staker', - type: 'address', - }, - ], - name: 'isStaked', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'staker', - type: 'address', - }, - ], - name: 'isStakedOnLatestConfirmed', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - name: 'isValidator', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'staker', - type: 'address', - }, - ], - name: 'isZombie', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'lastStakeBlock', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'latestConfirmed', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'latestNodeCreated', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'staker', - type: 'address', - }, - ], - name: 'latestStakedNode', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'loserStakeEscrow', - outputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'minimumAssertionPeriod', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint64', - name: 'nodeNum', - type: 'uint64', - }, - { - internalType: 'address', - name: 'staker', - type: 'address', - }, - ], - name: 'nodeHasStaker', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'outbox', - outputs: [ - { - internalType: 'contract IOutbox', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'pause', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [], - name: 'paused', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'proxiableUUID', - outputs: [ - { - internalType: 'bytes32', - name: '', - type: 'bytes32', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: '_outbox', - type: 'address', - }, - ], - name: 'removeOldOutbox', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [], - name: 'resume', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [], - name: 'rollupDeploymentBlock', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'rollupEventInbox', - outputs: [ - { - internalType: 'contract IRollupEventInbox', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'sequencerInbox', - outputs: [ - { - internalType: 'contract ISequencerInbox', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint256', - name: 'newBaseStake', - type: 'uint256', - }, - ], - name: 'setBaseStake', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint64', - name: 'newConfirmPeriod', - type: 'uint64', - }, - ], - name: 'setConfirmPeriodBlocks', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: '_inbox', - type: 'address', - }, - { - internalType: 'bool', - name: '_enabled', - type: 'bool', - }, - ], - name: 'setDelayedInbox', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint64', - name: 'newExtraTimeBlocks', - type: 'uint64', - }, - ], - name: 'setExtraChallengeTimeBlocks', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'contract IInboxBase', - name: 'newInbox', - type: 'address', - }, - ], - name: 'setInbox', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'newLoserStakerEscrow', - type: 'address', - }, - ], - name: 'setLoserStakeEscrow', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint256', - name: 'newPeriod', - type: 'uint256', - }, - ], - name: 'setMinimumAssertionPeriod', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'contract IOutbox', - name: '_outbox', - type: 'address', - }, - ], - name: 'setOutbox', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'newOwner', - type: 'address', - }, - ], - name: 'setOwner', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: '_sequencerInbox', - type: 'address', - }, - ], - name: 'setSequencerInbox', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'newStakeToken', - type: 'address', - }, - ], - name: 'setStakeToken', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address[]', - name: '_validator', - type: 'address[]', - }, - { - internalType: 'bool[]', - name: '_val', - type: 'bool[]', - }, - ], - name: 'setValidator', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'bool', - name: '_validatorWhitelistDisabled', - type: 'bool', - }, - ], - name: 'setValidatorWhitelistDisabled', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'bytes32', - name: 'newWasmModuleRoot', - type: 'bytes32', - }, - ], - name: 'setWasmModuleRoot', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [], - name: 'stakeToken', - outputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'stakerCount', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'totalWithdrawableFunds', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'beacon', - type: 'address', - }, - { - internalType: 'address', - name: 'newImplementation', - type: 'address', - }, - ], - name: 'upgradeBeacon', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'newImplementation', - type: 'address', - }, - ], - name: 'upgradeSecondaryTo', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'newImplementation', - type: 'address', - }, - { - internalType: 'bytes', - name: 'data', - type: 'bytes', - }, - ], - name: 'upgradeSecondaryToAndCall', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'newImplementation', - type: 'address', - }, - ], - name: 'upgradeTo', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'newImplementation', - type: 'address', - }, - { - internalType: 'bytes', - name: 'data', - type: 'bytes', - }, - ], - name: 'upgradeToAndCall', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [], - name: 'validatorUtils', - outputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'validatorWalletCreator', - outputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'validatorWhitelistDisabled', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'wasmModuleRoot', - outputs: [ - { - internalType: 'bytes32', - name: '', - type: 'bytes32', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'user', - type: 'address', - }, - ], - name: 'withdrawableFunds', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint256', - name: 'zombieNum', - type: 'uint256', - }, - ], - name: 'zombieAddress', - outputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'zombieCount', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'uint256', - name: 'zombieNum', - type: 'uint256', - }, - ], - name: 'zombieLatestStakedNode', - outputs: [ - { - internalType: 'uint64', - name: '', - type: 'uint64', - }, - ], - stateMutability: 'view', - type: 'function', - }, -] as const; diff --git a/src/contracts/Rollup/index.ts b/src/contracts/Rollup/index.ts new file mode 100644 index 00000000..65e52bda --- /dev/null +++ b/src/contracts/Rollup/index.ts @@ -0,0 +1,2 @@ +// export the latest version +export * from './v2.1'; diff --git a/src/contracts/Rollup/v1.1.ts b/src/contracts/Rollup/v1.1.ts new file mode 100644 index 00000000..347362be --- /dev/null +++ b/src/contracts/Rollup/v1.1.ts @@ -0,0 +1,844 @@ +export const rollupABI = [ + { + anonymous: false, + inputs: [ + { indexed: false, internalType: 'address', name: 'previousAdmin', type: 'address' }, + { indexed: false, internalType: 'address', name: 'newAdmin', type: 'address' }, + ], + name: 'AdminChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'beacon', type: 'address' }], + name: 'BeaconUpgraded', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint64', name: 'nodeNum', type: 'uint64' }, + { indexed: false, internalType: 'bytes32', name: 'blockHash', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'sendRoot', type: 'bytes32' }, + ], + name: 'NodeConfirmed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint64', name: 'nodeNum', type: 'uint64' }, + { indexed: true, internalType: 'bytes32', name: 'parentNodeHash', type: 'bytes32' }, + { indexed: true, internalType: 'bytes32', name: 'nodeHash', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'executionHash', type: 'bytes32' }, + { + components: [ + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'beforeState', + type: 'tuple', + }, + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'afterState', + type: 'tuple', + }, + { internalType: 'uint64', name: 'numBlocks', type: 'uint64' }, + ], + indexed: false, + internalType: 'struct Assertion', + name: 'assertion', + type: 'tuple', + }, + { indexed: false, internalType: 'bytes32', name: 'afterInboxBatchAcc', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'wasmModuleRoot', type: 'bytes32' }, + { indexed: false, internalType: 'uint256', name: 'inboxMaxCount', type: 'uint256' }, + ], + name: 'NodeCreated', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'uint64', name: 'nodeNum', type: 'uint64' }], + name: 'NodeRejected', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'uint256', name: 'id', type: 'uint256' }], + name: 'OwnerFunctionCalled', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: 'address', name: 'account', type: 'address' }], + name: 'Paused', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint64', name: 'challengeIndex', type: 'uint64' }, + { indexed: false, internalType: 'address', name: 'asserter', type: 'address' }, + { indexed: false, internalType: 'address', name: 'challenger', type: 'address' }, + { indexed: false, internalType: 'uint64', name: 'challengedNode', type: 'uint64' }, + ], + name: 'RollupChallengeStarted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: 'bytes32', name: 'machineHash', type: 'bytes32' }, + { indexed: false, internalType: 'uint256', name: 'chainId', type: 'uint256' }, + ], + name: 'RollupInitialized', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: 'address', name: 'account', type: 'address' }], + name: 'Unpaused', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'implementation', type: 'address' }], + name: 'Upgraded', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'implementation', type: 'address' }], + name: 'UpgradedSecondary', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'initialBalance', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'finalBalance', type: 'uint256' }, + ], + name: 'UserStakeUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'initialBalance', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'finalBalance', type: 'uint256' }, + ], + name: 'UserWithdrawableFundsUpdated', + type: 'event', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: '_stakerMap', + outputs: [ + { internalType: 'uint256', name: 'amountStaked', type: 'uint256' }, + { internalType: 'uint64', name: 'index', type: 'uint64' }, + { internalType: 'uint64', name: 'latestStakedNode', type: 'uint64' }, + { internalType: 'uint64', name: 'currentChallenge', type: 'uint64' }, + { internalType: 'bool', name: 'isStaked', type: 'bool' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'amountStaked', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseStake', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'bridge', + outputs: [{ internalType: 'contract IBridge', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'chainId', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'challengeManager', + outputs: [{ internalType: 'contract IChallengeManager', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'confirmPeriodBlocks', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'beforeState', + type: 'tuple', + }, + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'afterState', + type: 'tuple', + }, + { internalType: 'uint64', name: 'numBlocks', type: 'uint64' }, + ], + internalType: 'struct Assertion', + name: 'assertion', + type: 'tuple', + }, + ], + name: 'createNitroMigrationGenesis', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'currentChallenge', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'extraChallengeTimeBlocks', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'firstUnresolvedNode', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint64', name: 'nodeNum', type: 'uint64' }, + { internalType: 'bytes32', name: 'blockHash', type: 'bytes32' }, + { internalType: 'bytes32', name: 'sendRoot', type: 'bytes32' }, + ], + name: 'forceConfirmNode', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint64', name: 'prevNode', type: 'uint64' }, + { internalType: 'uint256', name: 'prevNodeInboxMaxCount', type: 'uint256' }, + { + components: [ + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'beforeState', + type: 'tuple', + }, + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'afterState', + type: 'tuple', + }, + { internalType: 'uint64', name: 'numBlocks', type: 'uint64' }, + ], + internalType: 'struct Assertion', + name: 'assertion', + type: 'tuple', + }, + { internalType: 'bytes32', name: 'expectedNodeHash', type: 'bytes32' }, + ], + name: 'forceCreateNode', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address[]', name: 'staker', type: 'address[]' }], + name: 'forceRefundStaker', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'stakerA', type: 'address[]' }, + { internalType: 'address[]', name: 'stakerB', type: 'address[]' }, + ], + name: 'forceResolveChallenge', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'nodeNum', type: 'uint64' }], + name: 'getNode', + outputs: [ + { + components: [ + { internalType: 'bytes32', name: 'stateHash', type: 'bytes32' }, + { internalType: 'bytes32', name: 'challengeHash', type: 'bytes32' }, + { internalType: 'bytes32', name: 'confirmData', type: 'bytes32' }, + { internalType: 'uint64', name: 'prevNum', type: 'uint64' }, + { internalType: 'uint64', name: 'deadlineBlock', type: 'uint64' }, + { internalType: 'uint64', name: 'noChildConfirmedBeforeBlock', type: 'uint64' }, + { internalType: 'uint64', name: 'stakerCount', type: 'uint64' }, + { internalType: 'uint64', name: 'childStakerCount', type: 'uint64' }, + { internalType: 'uint64', name: 'firstChildBlock', type: 'uint64' }, + { internalType: 'uint64', name: 'latestChildNumber', type: 'uint64' }, + { internalType: 'uint64', name: 'createdAtBlock', type: 'uint64' }, + { internalType: 'bytes32', name: 'nodeHash', type: 'bytes32' }, + ], + internalType: 'struct Node', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'nodeNum', type: 'uint64' }], + name: 'getNodeCreationBlockForLogLookup', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'getStaker', + outputs: [ + { + components: [ + { internalType: 'uint256', name: 'amountStaked', type: 'uint256' }, + { internalType: 'uint64', name: 'index', type: 'uint64' }, + { internalType: 'uint64', name: 'latestStakedNode', type: 'uint64' }, + { internalType: 'uint64', name: 'currentChallenge', type: 'uint64' }, + { internalType: 'bool', name: 'isStaked', type: 'bool' }, + ], + internalType: 'struct IRollupCore.Staker', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'stakerNum', type: 'uint64' }], + name: 'getStakerAddress', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'inbox', + outputs: [{ internalType: 'contract IInboxBase', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + components: [ + { internalType: 'uint64', name: 'confirmPeriodBlocks', type: 'uint64' }, + { internalType: 'uint64', name: 'extraChallengeTimeBlocks', type: 'uint64' }, + { internalType: 'address', name: 'stakeToken', type: 'address' }, + { internalType: 'uint256', name: 'baseStake', type: 'uint256' }, + { internalType: 'bytes32', name: 'wasmModuleRoot', type: 'bytes32' }, + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'loserStakeEscrow', type: 'address' }, + { internalType: 'uint256', name: 'chainId', type: 'uint256' }, + { internalType: 'string', name: 'chainConfig', type: 'string' }, + { internalType: 'uint64', name: 'genesisBlockNum', type: 'uint64' }, + { + components: [ + { internalType: 'uint256', name: 'delayBlocks', type: 'uint256' }, + { internalType: 'uint256', name: 'futureBlocks', type: 'uint256' }, + { internalType: 'uint256', name: 'delaySeconds', type: 'uint256' }, + { internalType: 'uint256', name: 'futureSeconds', type: 'uint256' }, + ], + internalType: 'struct ISequencerInbox.MaxTimeVariation', + name: 'sequencerInboxMaxTimeVariation', + type: 'tuple', + }, + ], + internalType: 'struct Config', + name: 'config', + type: 'tuple', + }, + { + components: [ + { internalType: 'contract IBridge', name: 'bridge', type: 'address' }, + { internalType: 'contract ISequencerInbox', name: 'sequencerInbox', type: 'address' }, + { internalType: 'contract IInboxBase', name: 'inbox', type: 'address' }, + { internalType: 'contract IOutbox', name: 'outbox', type: 'address' }, + { internalType: 'contract IRollupEventInbox', name: 'rollupEventInbox', type: 'address' }, + { internalType: 'contract IChallengeManager', name: 'challengeManager', type: 'address' }, + { internalType: 'address', name: 'rollupAdminLogic', type: 'address' }, + { internalType: 'contract IRollupUser', name: 'rollupUserLogic', type: 'address' }, + { internalType: 'address', name: 'validatorUtils', type: 'address' }, + { internalType: 'address', name: 'validatorWalletCreator', type: 'address' }, + ], + internalType: 'struct ContractDependencies', + name: 'connectedContracts', + type: 'tuple', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'isStaked', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'isStakedOnLatestConfirmed', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'isValidator', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'isZombie', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'lastStakeBlock', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'latestConfirmed', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'latestNodeCreated', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'latestStakedNode', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'loserStakeEscrow', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'minimumAssertionPeriod', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint64', name: 'nodeNum', type: 'uint64' }, + { internalType: 'address', name: 'staker', type: 'address' }, + ], + name: 'nodeHasStaker', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'outbox', + outputs: [{ internalType: 'contract IOutbox', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { inputs: [], name: 'pause', outputs: [], stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [], + name: 'paused', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'proxiableUUID', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_outbox', type: 'address' }], + name: 'removeOldOutbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { inputs: [], name: 'resume', outputs: [], stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [], + name: 'rollupDeploymentBlock', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'rollupEventInbox', + outputs: [{ internalType: 'contract IRollupEventInbox', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'sequencerInbox', + outputs: [{ internalType: 'contract ISequencerInbox', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'newBaseStake', type: 'uint256' }], + name: 'setBaseStake', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'newConfirmPeriod', type: 'uint64' }], + name: 'setConfirmPeriodBlocks', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_inbox', type: 'address' }, + { internalType: 'bool', name: '_enabled', type: 'bool' }, + ], + name: 'setDelayedInbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'newExtraTimeBlocks', type: 'uint64' }], + name: 'setExtraChallengeTimeBlocks', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'contract IInboxBase', name: 'newInbox', type: 'address' }], + name: 'setInbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newLoserStakerEscrow', type: 'address' }], + name: 'setLoserStakeEscrow', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'newPeriod', type: 'uint256' }], + name: 'setMinimumAssertionPeriod', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'contract IOutbox', name: '_outbox', type: 'address' }], + name: 'setOutbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newOwner', type: 'address' }], + name: 'setOwner', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_sequencerInbox', type: 'address' }], + name: 'setSequencerInbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newStakeToken', type: 'address' }], + name: 'setStakeToken', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: '_validator', type: 'address[]' }, + { internalType: 'bool[]', name: '_val', type: 'bool[]' }, + ], + name: 'setValidator', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bool', name: '_validatorWhitelistDisabled', type: 'bool' }], + name: 'setValidatorWhitelistDisabled', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'newWasmModuleRoot', type: 'bytes32' }], + name: 'setWasmModuleRoot', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'stakeToken', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'stakerCount', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalWithdrawableFunds', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'beacon', type: 'address' }, + { internalType: 'address', name: 'newImplementation', type: 'address' }, + ], + name: 'upgradeBeacon', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newImplementation', type: 'address' }], + name: 'upgradeSecondaryTo', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'newImplementation', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'upgradeSecondaryToAndCall', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newImplementation', type: 'address' }], + name: 'upgradeTo', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'newImplementation', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'upgradeToAndCall', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'validatorUtils', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'validatorWalletCreator', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'validatorWhitelistDisabled', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'wasmModuleRoot', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'user', type: 'address' }], + name: 'withdrawableFunds', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'zombieNum', type: 'uint256' }], + name: 'zombieAddress', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'zombieCount', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'zombieNum', type: 'uint256' }], + name: 'zombieLatestStakedNode', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, +] as const; diff --git a/src/contracts/Rollup/v2.1.ts b/src/contracts/Rollup/v2.1.ts new file mode 100644 index 00000000..4c5f4b2a --- /dev/null +++ b/src/contracts/Rollup/v2.1.ts @@ -0,0 +1,858 @@ +export const rollupABI = [ + { + anonymous: false, + inputs: [ + { indexed: false, internalType: 'address', name: 'previousAdmin', type: 'address' }, + { indexed: false, internalType: 'address', name: 'newAdmin', type: 'address' }, + ], + name: 'AdminChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'beacon', type: 'address' }], + name: 'BeaconUpgraded', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint64', name: 'nodeNum', type: 'uint64' }, + { indexed: false, internalType: 'bytes32', name: 'blockHash', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'sendRoot', type: 'bytes32' }, + ], + name: 'NodeConfirmed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint64', name: 'nodeNum', type: 'uint64' }, + { indexed: true, internalType: 'bytes32', name: 'parentNodeHash', type: 'bytes32' }, + { indexed: true, internalType: 'bytes32', name: 'nodeHash', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'executionHash', type: 'bytes32' }, + { + components: [ + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'beforeState', + type: 'tuple', + }, + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'afterState', + type: 'tuple', + }, + { internalType: 'uint64', name: 'numBlocks', type: 'uint64' }, + ], + indexed: false, + internalType: 'struct Assertion', + name: 'assertion', + type: 'tuple', + }, + { indexed: false, internalType: 'bytes32', name: 'afterInboxBatchAcc', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'wasmModuleRoot', type: 'bytes32' }, + { indexed: false, internalType: 'uint256', name: 'inboxMaxCount', type: 'uint256' }, + ], + name: 'NodeCreated', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'uint64', name: 'nodeNum', type: 'uint64' }], + name: 'NodeRejected', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'uint256', name: 'id', type: 'uint256' }], + name: 'OwnerFunctionCalled', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: 'address', name: 'account', type: 'address' }], + name: 'Paused', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint64', name: 'challengeIndex', type: 'uint64' }, + { indexed: false, internalType: 'address', name: 'asserter', type: 'address' }, + { indexed: false, internalType: 'address', name: 'challenger', type: 'address' }, + { indexed: false, internalType: 'uint64', name: 'challengedNode', type: 'uint64' }, + ], + name: 'RollupChallengeStarted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: 'bytes32', name: 'machineHash', type: 'bytes32' }, + { indexed: false, internalType: 'uint256', name: 'chainId', type: 'uint256' }, + ], + name: 'RollupInitialized', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: 'address', name: 'account', type: 'address' }], + name: 'Unpaused', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'implementation', type: 'address' }], + name: 'Upgraded', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'implementation', type: 'address' }], + name: 'UpgradedSecondary', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'initialBalance', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'finalBalance', type: 'uint256' }, + ], + name: 'UserStakeUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'initialBalance', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'finalBalance', type: 'uint256' }, + ], + name: 'UserWithdrawableFundsUpdated', + type: 'event', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: '_stakerMap', + outputs: [ + { internalType: 'uint256', name: 'amountStaked', type: 'uint256' }, + { internalType: 'uint64', name: 'index', type: 'uint64' }, + { internalType: 'uint64', name: 'latestStakedNode', type: 'uint64' }, + { internalType: 'uint64', name: 'currentChallenge', type: 'uint64' }, + { internalType: 'bool', name: 'isStaked', type: 'bool' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'amountStaked', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'anyTrustFastConfirmer', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'baseStake', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'bridge', + outputs: [{ internalType: 'contract IBridge', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'chainId', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'challengeManager', + outputs: [{ internalType: 'contract IChallengeManager', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'confirmPeriodBlocks', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'beforeState', + type: 'tuple', + }, + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'afterState', + type: 'tuple', + }, + { internalType: 'uint64', name: 'numBlocks', type: 'uint64' }, + ], + internalType: 'struct Assertion', + name: 'assertion', + type: 'tuple', + }, + ], + name: 'createNitroMigrationGenesis', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'currentChallenge', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'extraChallengeTimeBlocks', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'firstUnresolvedNode', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint64', name: 'nodeNum', type: 'uint64' }, + { internalType: 'bytes32', name: 'blockHash', type: 'bytes32' }, + { internalType: 'bytes32', name: 'sendRoot', type: 'bytes32' }, + ], + name: 'forceConfirmNode', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint64', name: 'prevNode', type: 'uint64' }, + { internalType: 'uint256', name: 'prevNodeInboxMaxCount', type: 'uint256' }, + { + components: [ + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'beforeState', + type: 'tuple', + }, + { + components: [ + { + components: [ + { internalType: 'bytes32[2]', name: 'bytes32Vals', type: 'bytes32[2]' }, + { internalType: 'uint64[2]', name: 'u64Vals', type: 'uint64[2]' }, + ], + internalType: 'struct GlobalState', + name: 'globalState', + type: 'tuple', + }, + { internalType: 'enum MachineStatus', name: 'machineStatus', type: 'uint8' }, + ], + internalType: 'struct ExecutionState', + name: 'afterState', + type: 'tuple', + }, + { internalType: 'uint64', name: 'numBlocks', type: 'uint64' }, + ], + internalType: 'struct Assertion', + name: 'assertion', + type: 'tuple', + }, + { internalType: 'bytes32', name: 'expectedNodeHash', type: 'bytes32' }, + ], + name: 'forceCreateNode', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address[]', name: 'staker', type: 'address[]' }], + name: 'forceRefundStaker', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'stakerA', type: 'address[]' }, + { internalType: 'address[]', name: 'stakerB', type: 'address[]' }, + ], + name: 'forceResolveChallenge', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'nodeNum', type: 'uint64' }], + name: 'getNode', + outputs: [ + { + components: [ + { internalType: 'bytes32', name: 'stateHash', type: 'bytes32' }, + { internalType: 'bytes32', name: 'challengeHash', type: 'bytes32' }, + { internalType: 'bytes32', name: 'confirmData', type: 'bytes32' }, + { internalType: 'uint64', name: 'prevNum', type: 'uint64' }, + { internalType: 'uint64', name: 'deadlineBlock', type: 'uint64' }, + { internalType: 'uint64', name: 'noChildConfirmedBeforeBlock', type: 'uint64' }, + { internalType: 'uint64', name: 'stakerCount', type: 'uint64' }, + { internalType: 'uint64', name: 'childStakerCount', type: 'uint64' }, + { internalType: 'uint64', name: 'firstChildBlock', type: 'uint64' }, + { internalType: 'uint64', name: 'latestChildNumber', type: 'uint64' }, + { internalType: 'uint64', name: 'createdAtBlock', type: 'uint64' }, + { internalType: 'bytes32', name: 'nodeHash', type: 'bytes32' }, + ], + internalType: 'struct Node', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'nodeNum', type: 'uint64' }], + name: 'getNodeCreationBlockForLogLookup', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'getStaker', + outputs: [ + { + components: [ + { internalType: 'uint256', name: 'amountStaked', type: 'uint256' }, + { internalType: 'uint64', name: 'index', type: 'uint64' }, + { internalType: 'uint64', name: 'latestStakedNode', type: 'uint64' }, + { internalType: 'uint64', name: 'currentChallenge', type: 'uint64' }, + { internalType: 'bool', name: 'isStaked', type: 'bool' }, + ], + internalType: 'struct IRollupCore.Staker', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'stakerNum', type: 'uint64' }], + name: 'getStakerAddress', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'inbox', + outputs: [{ internalType: 'contract IInboxBase', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + components: [ + { internalType: 'uint64', name: 'confirmPeriodBlocks', type: 'uint64' }, + { internalType: 'uint64', name: 'extraChallengeTimeBlocks', type: 'uint64' }, + { internalType: 'address', name: 'stakeToken', type: 'address' }, + { internalType: 'uint256', name: 'baseStake', type: 'uint256' }, + { internalType: 'bytes32', name: 'wasmModuleRoot', type: 'bytes32' }, + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'loserStakeEscrow', type: 'address' }, + { internalType: 'uint256', name: 'chainId', type: 'uint256' }, + { internalType: 'string', name: 'chainConfig', type: 'string' }, + { internalType: 'uint64', name: 'genesisBlockNum', type: 'uint64' }, + { + components: [ + { internalType: 'uint256', name: 'delayBlocks', type: 'uint256' }, + { internalType: 'uint256', name: 'futureBlocks', type: 'uint256' }, + { internalType: 'uint256', name: 'delaySeconds', type: 'uint256' }, + { internalType: 'uint256', name: 'futureSeconds', type: 'uint256' }, + ], + internalType: 'struct ISequencerInbox.MaxTimeVariation', + name: 'sequencerInboxMaxTimeVariation', + type: 'tuple', + }, + ], + internalType: 'struct Config', + name: 'config', + type: 'tuple', + }, + { + components: [ + { internalType: 'contract IBridge', name: 'bridge', type: 'address' }, + { internalType: 'contract ISequencerInbox', name: 'sequencerInbox', type: 'address' }, + { internalType: 'contract IInboxBase', name: 'inbox', type: 'address' }, + { internalType: 'contract IOutbox', name: 'outbox', type: 'address' }, + { internalType: 'contract IRollupEventInbox', name: 'rollupEventInbox', type: 'address' }, + { internalType: 'contract IChallengeManager', name: 'challengeManager', type: 'address' }, + { internalType: 'address', name: 'rollupAdminLogic', type: 'address' }, + { internalType: 'contract IRollupUser', name: 'rollupUserLogic', type: 'address' }, + { internalType: 'address', name: 'validatorUtils', type: 'address' }, + { internalType: 'address', name: 'validatorWalletCreator', type: 'address' }, + ], + internalType: 'struct ContractDependencies', + name: 'connectedContracts', + type: 'tuple', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'isStaked', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'isStakedOnLatestConfirmed', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'isValidator', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'isZombie', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'lastStakeBlock', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'latestConfirmed', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'latestNodeCreated', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'staker', type: 'address' }], + name: 'latestStakedNode', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'loserStakeEscrow', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'minimumAssertionPeriod', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint64', name: 'nodeNum', type: 'uint64' }, + { internalType: 'address', name: 'staker', type: 'address' }, + ], + name: 'nodeHasStaker', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'outbox', + outputs: [{ internalType: 'contract IOutbox', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { inputs: [], name: 'pause', outputs: [], stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [], + name: 'paused', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'proxiableUUID', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_outbox', type: 'address' }], + name: 'removeOldOutbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { inputs: [], name: 'resume', outputs: [], stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [], + name: 'rollupDeploymentBlock', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'rollupEventInbox', + outputs: [{ internalType: 'contract IRollupEventInbox', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'sequencerInbox', + outputs: [{ internalType: 'contract ISequencerInbox', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_anyTrustFastConfirmer', type: 'address' }], + name: 'setAnyTrustFastConfirmer', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'newBaseStake', type: 'uint256' }], + name: 'setBaseStake', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'newConfirmPeriod', type: 'uint64' }], + name: 'setConfirmPeriodBlocks', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_inbox', type: 'address' }, + { internalType: 'bool', name: '_enabled', type: 'bool' }, + ], + name: 'setDelayedInbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint64', name: 'newExtraTimeBlocks', type: 'uint64' }], + name: 'setExtraChallengeTimeBlocks', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'contract IInboxBase', name: 'newInbox', type: 'address' }], + name: 'setInbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newLoserStakerEscrow', type: 'address' }], + name: 'setLoserStakeEscrow', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'newPeriod', type: 'uint256' }], + name: 'setMinimumAssertionPeriod', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'contract IOutbox', name: '_outbox', type: 'address' }], + name: 'setOutbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newOwner', type: 'address' }], + name: 'setOwner', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '_sequencerInbox', type: 'address' }], + name: 'setSequencerInbox', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newStakeToken', type: 'address' }], + name: 'setStakeToken', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: '_validator', type: 'address[]' }, + { internalType: 'bool[]', name: '_val', type: 'bool[]' }, + ], + name: 'setValidator', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bool', name: '_validatorWhitelistDisabled', type: 'bool' }], + name: 'setValidatorWhitelistDisabled', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'newWasmModuleRoot', type: 'bytes32' }], + name: 'setWasmModuleRoot', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'stakeToken', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'stakerCount', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalWithdrawableFunds', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'beacon', type: 'address' }, + { internalType: 'address', name: 'newImplementation', type: 'address' }, + ], + name: 'upgradeBeacon', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newImplementation', type: 'address' }], + name: 'upgradeSecondaryTo', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'newImplementation', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'upgradeSecondaryToAndCall', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newImplementation', type: 'address' }], + name: 'upgradeTo', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'newImplementation', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'upgradeToAndCall', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'validatorUtils', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'validatorWalletCreator', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'validatorWhitelistDisabled', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'wasmModuleRoot', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'user', type: 'address' }], + name: 'withdrawableFunds', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'zombieNum', type: 'uint256' }], + name: 'zombieAddress', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'zombieCount', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'zombieNum', type: 'uint256' }], + name: 'zombieLatestStakedNode', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function', + }, +] as const; diff --git a/src/contracts/SequencerInbox/index.ts b/src/contracts/SequencerInbox/index.ts new file mode 100644 index 00000000..65e52bda --- /dev/null +++ b/src/contracts/SequencerInbox/index.ts @@ -0,0 +1,2 @@ +// export the latest version +export * from './v2.1'; diff --git a/src/contracts/SequencerInbox.ts b/src/contracts/SequencerInbox/v1.1.ts similarity index 100% rename from src/contracts/SequencerInbox.ts rename to src/contracts/SequencerInbox/v1.1.ts diff --git a/src/contracts/SequencerInbox/v2.1.ts b/src/contracts/SequencerInbox/v2.1.ts new file mode 100644 index 00000000..3d0c2086 --- /dev/null +++ b/src/contracts/SequencerInbox/v2.1.ts @@ -0,0 +1,487 @@ +export const sequencerInboxABI = [ + { + inputs: [ + { internalType: 'uint256', name: '_maxDataSize', type: 'uint256' }, + { internalType: 'contract IReader4844', name: 'reader4844_', type: 'address' }, + { internalType: 'bool', name: '_isUsingFeeToken', type: 'bool' }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { inputs: [], name: 'AlreadyInit', type: 'error' }, + { + inputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + name: 'AlreadyValidDASKeyset', + type: 'error', + }, + { inputs: [], name: 'BadMaxTimeVariation', type: 'error' }, + { inputs: [], name: 'BadPostUpgradeInit', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'stored', type: 'uint256' }, + { internalType: 'uint256', name: 'received', type: 'uint256' }, + ], + name: 'BadSequencerNumber', + type: 'error', + }, + { inputs: [], name: 'DataBlobsNotSupported', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'dataLength', type: 'uint256' }, + { internalType: 'uint256', name: 'maxDataLength', type: 'uint256' }, + ], + name: 'DataTooLarge', + type: 'error', + }, + { inputs: [], name: 'DelayedBackwards', type: 'error' }, + { inputs: [], name: 'DelayedTooFar', type: 'error' }, + { inputs: [], name: 'Deprecated', type: 'error' }, + { inputs: [], name: 'ForceIncludeBlockTooSoon', type: 'error' }, + { inputs: [], name: 'ForceIncludeTimeTooSoon', type: 'error' }, + { inputs: [], name: 'HadZeroInit', type: 'error' }, + { inputs: [], name: 'IncorrectMessagePreimage', type: 'error' }, + { + inputs: [{ internalType: 'string', name: 'name', type: 'string' }], + name: 'InitParamZero', + type: 'error', + }, + { + inputs: [{ internalType: 'bytes1', name: '', type: 'bytes1' }], + name: 'InvalidHeaderFlag', + type: 'error', + }, + { inputs: [], name: 'MissingDataHashes', type: 'error' }, + { inputs: [], name: 'NativeTokenMismatch', type: 'error' }, + { + inputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + name: 'NoSuchKeyset', + type: 'error', + }, + { inputs: [], name: 'NotBatchPoster', type: 'error' }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'NotBatchPosterManager', + type: 'error', + }, + { inputs: [], name: 'NotForked', type: 'error' }, + { inputs: [], name: 'NotOrigin', type: 'error' }, + { + inputs: [ + { internalType: 'address', name: 'sender', type: 'address' }, + { internalType: 'address', name: 'owner', type: 'address' }, + ], + name: 'NotOwner', + type: 'error', + }, + { inputs: [], name: 'RollupNotChanged', type: 'error' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'messageNum', type: 'uint256' }, + { indexed: false, internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'InboxMessageDelivered', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'uint256', name: 'messageNum', type: 'uint256' }], + name: 'InboxMessageDeliveredFromOrigin', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'bytes32', name: 'keysetHash', type: 'bytes32' }], + name: 'InvalidateKeyset', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'uint256', name: 'id', type: 'uint256' }], + name: 'OwnerFunctionCalled', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'batchSequenceNumber', type: 'uint256' }, + { indexed: false, internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'SequencerBatchData', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'batchSequenceNumber', type: 'uint256' }, + { indexed: true, internalType: 'bytes32', name: 'beforeAcc', type: 'bytes32' }, + { indexed: true, internalType: 'bytes32', name: 'afterAcc', type: 'bytes32' }, + { indexed: false, internalType: 'bytes32', name: 'delayedAcc', type: 'bytes32' }, + { + indexed: false, + internalType: 'uint256', + name: 'afterDelayedMessagesRead', + type: 'uint256', + }, + { + components: [ + { internalType: 'uint64', name: 'minTimestamp', type: 'uint64' }, + { internalType: 'uint64', name: 'maxTimestamp', type: 'uint64' }, + { internalType: 'uint64', name: 'minBlockNumber', type: 'uint64' }, + { internalType: 'uint64', name: 'maxBlockNumber', type: 'uint64' }, + ], + indexed: false, + internalType: 'struct IBridge.TimeBounds', + name: 'timeBounds', + type: 'tuple', + }, + { + indexed: false, + internalType: 'enum IBridge.BatchDataLocation', + name: 'dataLocation', + type: 'uint8', + }, + ], + name: 'SequencerBatchDelivered', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'bytes32', name: 'keysetHash', type: 'bytes32' }, + { indexed: false, internalType: 'bytes', name: 'keysetBytes', type: 'bytes' }, + ], + name: 'SetValidKeyset', + type: 'event', + }, + { + inputs: [], + name: 'BROTLI_MESSAGE_HEADER_FLAG', + outputs: [{ internalType: 'bytes1', name: '', type: 'bytes1' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'DAS_MESSAGE_HEADER_FLAG', + outputs: [{ internalType: 'bytes1', name: '', type: 'bytes1' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'DATA_AUTHENTICATED_FLAG', + outputs: [{ internalType: 'bytes1', name: '', type: 'bytes1' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'DATA_BLOB_HEADER_FLAG', + outputs: [{ internalType: 'bytes1', name: '', type: 'bytes1' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'HEADER_LENGTH', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TREE_DAS_MESSAGE_HEADER_FLAG', + outputs: [{ internalType: 'bytes1', name: '', type: 'bytes1' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ZERO_HEAVY_MESSAGE_HEADER_FLAG', + outputs: [{ internalType: 'bytes1', name: '', type: 'bytes1' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'sequenceNumber', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + { internalType: 'uint256', name: 'afterDelayedMessagesRead', type: 'uint256' }, + { internalType: 'contract IGasRefunder', name: 'gasRefunder', type: 'address' }, + { internalType: 'uint256', name: 'prevMessageCount', type: 'uint256' }, + { internalType: 'uint256', name: 'newMessageCount', type: 'uint256' }, + ], + name: 'addSequencerL2Batch', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'sequenceNumber', type: 'uint256' }, + { internalType: 'uint256', name: 'afterDelayedMessagesRead', type: 'uint256' }, + { internalType: 'contract IGasRefunder', name: 'gasRefunder', type: 'address' }, + { internalType: 'uint256', name: 'prevMessageCount', type: 'uint256' }, + { internalType: 'uint256', name: 'newMessageCount', type: 'uint256' }, + ], + name: 'addSequencerL2BatchFromBlobs', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'bytes', name: '', type: 'bytes' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'contract IGasRefunder', name: '', type: 'address' }, + ], + name: 'addSequencerL2BatchFromOrigin', + outputs: [], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'sequenceNumber', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + { internalType: 'uint256', name: 'afterDelayedMessagesRead', type: 'uint256' }, + { internalType: 'contract IGasRefunder', name: 'gasRefunder', type: 'address' }, + { internalType: 'uint256', name: 'prevMessageCount', type: 'uint256' }, + { internalType: 'uint256', name: 'newMessageCount', type: 'uint256' }, + ], + name: 'addSequencerL2BatchFromOrigin', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'batchCount', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'batchPosterManager', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'bridge', + outputs: [{ internalType: 'contract IBridge', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + name: 'dasKeySetInfo', + outputs: [ + { internalType: 'bool', name: 'isValidKeyset', type: 'bool' }, + { internalType: 'uint64', name: 'creationBlock', type: 'uint64' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: '_totalDelayedMessagesRead', type: 'uint256' }, + { internalType: 'uint8', name: 'kind', type: 'uint8' }, + { internalType: 'uint64[2]', name: 'l1BlockAndTime', type: 'uint64[2]' }, + { internalType: 'uint256', name: 'baseFeeL1', type: 'uint256' }, + { internalType: 'address', name: 'sender', type: 'address' }, + { internalType: 'bytes32', name: 'messageDataHash', type: 'bytes32' }, + ], + name: 'forceInclusion', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'ksHash', type: 'bytes32' }], + name: 'getKeysetCreationBlock', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'index', type: 'uint256' }], + name: 'inboxAccs', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'contract IBridge', name: 'bridge_', type: 'address' }, + { + components: [ + { internalType: 'uint256', name: 'delayBlocks', type: 'uint256' }, + { internalType: 'uint256', name: 'futureBlocks', type: 'uint256' }, + { internalType: 'uint256', name: 'delaySeconds', type: 'uint256' }, + { internalType: 'uint256', name: 'futureSeconds', type: 'uint256' }, + ], + internalType: 'struct ISequencerInbox.MaxTimeVariation', + name: 'maxTimeVariation_', + type: 'tuple', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'ksHash', type: 'bytes32' }], + name: 'invalidateKeysetHash', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'isBatchPoster', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'isSequencer', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'isUsingFeeToken', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'ksHash', type: 'bytes32' }], + name: 'isValidKeysetHash', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'maxDataSize', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'maxTimeVariation', + outputs: [ + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'postUpgradeInit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'reader4844', + outputs: [{ internalType: 'contract IReader4844', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'removeDelayAfterFork', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'rollup', + outputs: [{ internalType: 'contract IOwnable', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newBatchPosterManager', type: 'address' }], + name: 'setBatchPosterManager', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'addr', type: 'address' }, + { internalType: 'bool', name: 'isBatchPoster_', type: 'bool' }, + ], + name: 'setIsBatchPoster', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'addr', type: 'address' }, + { internalType: 'bool', name: 'isSequencer_', type: 'bool' }, + ], + name: 'setIsSequencer', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + components: [ + { internalType: 'uint256', name: 'delayBlocks', type: 'uint256' }, + { internalType: 'uint256', name: 'futureBlocks', type: 'uint256' }, + { internalType: 'uint256', name: 'delaySeconds', type: 'uint256' }, + { internalType: 'uint256', name: 'futureSeconds', type: 'uint256' }, + ], + internalType: 'struct ISequencerInbox.MaxTimeVariation', + name: 'maxTimeVariation_', + type: 'tuple', + }, + ], + name: 'setMaxTimeVariation', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes', name: 'keysetBytes', type: 'bytes' }], + name: 'setValidKeyset', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'totalDelayedMessagesRead', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'updateRollupAddress', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; diff --git a/src/getBatchPosters.unit.test.ts b/src/getBatchPosters.unit.test.ts index 16f0f45e..186c6255 100644 --- a/src/getBatchPosters.unit.test.ts +++ b/src/getBatchPosters.unit.test.ts @@ -167,13 +167,22 @@ it('getBatchPosters returns batch posters for a chain created with RollupCreator expect(isAccurate).toBeTruthy(); }); -// https://sepolia.arbiscan.io/tx/0xfd638529dec24963075ee8fcd9df0d319c21190a9e3f3cb5e91d7da353666b06 +// https://sepolia.arbiscan.io/tx/0x77db43157182a69ce0e6d2a0564d2dabb43b306d48ea7b4d877160d6a1c9b66d it('getBatchPosters returns batch posters for a chain created with RollupCreator v2.1', async () => { const { isAccurate, batchPosters } = await getBatchPosters(arbitrumSepoliaClient, { - rollup: '0x16A95119425638cAaD6d302D75B270ecDBf37649', - sequencerInbox: '0xbE20C632d1DaD19285575580Aaa60C9B1207d531', + rollup: '0x66d0e72952f4f69aF9D33C1B7C31Fa9aCDbCAF63', + sequencerInbox: '0x43528b8Be52e8D084F147d167487f361553463b5', }); - expect(batchPosters).toEqual(['0x551B0B7DA75530544aF467183E626778412491Da']); + expect(batchPosters).toEqual([ + '0x9464aD09CE0d157Efc6c7EefE577C5AA6dEc804D', + '0xC02386B2D10a37e71145B6A7f5569e1db4604213', + '0x6C4483f6DCEDb5a758b28D28E11F805bdACFE245', + '0xf89836dc33f58394fB34B3e690D3829A65C74286', + '0xd1d25Aeb44E99B35E2d5E7Db961c73ec94f92a24', + '0xDc4ECA04032b9178020Ff0c6154A7e87309a429f', + '0xe122F9838A4C8e6834F24D1b9dCa92eb52a8E17e', + '0xB280Fd59090f3D95588d94BACD22b336dE2278e0', + ]); expect(isAccurate).toBeTruthy(); }); diff --git a/src/getValidators.unit.test.ts b/src/getValidators.unit.test.ts index 0f7b9d47..f909dcbd 100644 --- a/src/getValidators.unit.test.ts +++ b/src/getValidators.unit.test.ts @@ -163,12 +163,17 @@ it('getValidators returns validators for a chain created with RollupCreator v1.1 expect(isAccurate).toBeTruthy(); }); -// https://sepolia.arbiscan.io/tx/0xfd638529dec24963075ee8fcd9df0d319c21190a9e3f3cb5e91d7da353666b06 +// https://sepolia.arbiscan.io/tx/0x77db43157182a69ce0e6d2a0564d2dabb43b306d48ea7b4d877160d6a1c9b66d it('getValidators returns validators for a chain created with RollupCreator v2.1', async () => { const { isAccurate, validators } = await getValidators(arbitrumSepoliaClient, { - rollup: '0x16A95119425638cAaD6d302D75B270ecDBf37649', + rollup: '0x66d0e72952f4f69aF9D33C1B7C31Fa9aCDbCAF63', }); - expect(validators).toEqual(['0xbD7621A2bB0e4B768F1e1756dC500e2c44f02649']); + expect(validators).toEqual([ + '0xDBb2c9923b5DE18B151bC55Ed571EDcd1fC7EeB9', + '0x84B2EFFDd54aA5dce861440Ae9B9D320b043a64c', + '0x39B4Ce32E557225a401917a701ac4d267648635a', + '0xe2D0cC872647B1A129B942BbFC980B31E8e94Df2', + ]); expect(isAccurate).toBeTruthy(); }); From 5f2b6ff9c5bce2793f930cceed605ee0794144c6 Mon Sep 17 00:00:00 2001 From: spsjvc Date: Fri, 16 Aug 2024 10:51:55 +0200 Subject: [PATCH 27/54] fix: properly export contracts (#170) --- src/package.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/package.json b/src/package.json index 88945982..102f82c3 100644 --- a/src/package.json +++ b/src/package.json @@ -22,6 +22,10 @@ "./constants": { "types": "./dist/constants.d.ts", "default": "./dist/constants.js" + }, + "./contracts/*": { + "types": "./dist/contracts/*", + "default": "./dist/contracts/*" } }, "typesVersions": { @@ -34,6 +38,9 @@ ], "constants": [ "./dist/constants.d.ts" + ], + "contracts/*": [ + "./dist/contracts/*" ] } }, From f82d01e0751859d2c5bfeb347fccc2354f0d4256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dragi=C5=A1a=20Spasojevi=C4=87?= Date: Fri, 16 Aug 2024 10:52:57 +0200 Subject: [PATCH 28/54] chore: bump version --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 102f82c3..110fc384 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.18.0-beta.1", + "version": "0.18.0", "main": "./dist/index.js", "files": [ "./dist" From 36fd6fe0d025729d1722ab7e83421ee144e2b5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20FP?= <105675159+TucksonDev@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:03:31 +0100 Subject: [PATCH 29/54] fix: add fast confirmer as validator (#171) --- examples/setup-fast-withdrawal/index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/setup-fast-withdrawal/index.ts b/examples/setup-fast-withdrawal/index.ts index 6ad4f0d6..f8ad21e3 100644 --- a/examples/setup-fast-withdrawal/index.ts +++ b/examples/setup-fast-withdrawal/index.ts @@ -143,6 +143,10 @@ async function main() { ); console.log(''); + // add the new Safe address as a validator + // (needed to call removeOldZombies() as part of the fastConfirmNextNode() flow) + fcValidators.push(safeAddress); + // // Step 2. Add validators to the Orbit chain rollup validator whitelist // @@ -297,13 +301,13 @@ async function main() { // Batch poster configuration const timeDelay = getTimeDelayFromNumberOfBlocks(parentChain.id, minimumAssertionPeriod); - console.log('Your batch poster has to run at least nitro v3.x'); + console.log('Your batch poster has to run at least nitro v3.1.1'); console.log('Add the following parameter:'); console.log(`--node.batch-poster.max-delay=${timeDelay}`); console.log(''); // Validator configuration - console.log('Your validators have to run at least nitro v3.x'); + console.log('Your validators have to run at least nitro v3.1.1'); console.log('Add the following parameters:'); console.log(`--node.staker.enable-fast-confirmation=true`); console.log(`--node.staker.fast-confirm-safe-address=${safeAddress}`); From ced5193237a6b17d6e43cdc1d77430dfe3fa9d8a Mon Sep 17 00:00:00 2001 From: Christophe Deveaux Date: Mon, 19 Aug 2024 13:20:43 +0200 Subject: [PATCH 30/54] feat: add SequencerInbox getters (#114) --- src/actions/getMaxTimeVariation.ts | 33 ++++++++++++++++++++++++++++++ src/actions/index.ts | 3 +++ src/actions/isBatchPoster.ts | 29 ++++++++++++++++++++++++++ src/actions/isValidKeysetHash.ts | 30 +++++++++++++++++++++++++++ src/index.ts | 1 + src/types/Actions.ts | 22 ++++++++++++++++++++ 6 files changed, 118 insertions(+) create mode 100644 src/actions/getMaxTimeVariation.ts create mode 100644 src/actions/index.ts create mode 100644 src/actions/isBatchPoster.ts create mode 100644 src/actions/isValidKeysetHash.ts create mode 100644 src/types/Actions.ts diff --git a/src/actions/getMaxTimeVariation.ts b/src/actions/getMaxTimeVariation.ts new file mode 100644 index 00000000..b0bfe82c --- /dev/null +++ b/src/actions/getMaxTimeVariation.ts @@ -0,0 +1,33 @@ +import { Chain, PublicClient, Transport } from 'viem'; +import { sequencerInboxABI } from '../contracts/SequencerInbox'; +import { ActionParameters } from '../types/Actions'; + +export type GetMaxTimeVariationParameters = ActionParameters< + {}, + 'sequencerInbox', + Curried +>; + +export type GetMaxTimeVariationReturnType = { + delayBlocks: bigint; + futureBlocks: bigint; + delaySeconds: bigint; + futureSeconds: bigint; +}; + +export async function getMaxTimeVariation( + client: PublicClient, + args: GetMaxTimeVariationParameters, +): Promise { + const [delayBlocks, futureBlocks, delaySeconds, futureSeconds] = await client.readContract({ + abi: sequencerInboxABI, + functionName: 'maxTimeVariation', + address: args.sequencerInbox, + }); + return { + delayBlocks, + futureBlocks, + delaySeconds, + futureSeconds, + }; +} diff --git a/src/actions/index.ts b/src/actions/index.ts new file mode 100644 index 00000000..63164981 --- /dev/null +++ b/src/actions/index.ts @@ -0,0 +1,3 @@ +export * from './getMaxTimeVariation'; +export * from './isBatchPoster'; +export * from './isValidKeysetHash'; diff --git a/src/actions/isBatchPoster.ts b/src/actions/isBatchPoster.ts new file mode 100644 index 00000000..f71b773f --- /dev/null +++ b/src/actions/isBatchPoster.ts @@ -0,0 +1,29 @@ +import { Address, Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { sequencerInboxABI } from '../contracts/SequencerInbox'; +import { ActionParameters } from '../types/Actions'; + +type Args = { + batchPoster: Address; +}; +export type IsBatchPosterParameters = ActionParameters< + Args, + 'sequencerInbox', + Curried +>; + +export type IsBatchPosterReturnType = ReadContractReturnType< + typeof sequencerInboxABI, + 'isBatchPoster' +>; + +export async function isBatchPoster( + client: PublicClient, + args: IsBatchPosterParameters, +): Promise { + return client.readContract({ + abi: sequencerInboxABI, + functionName: 'isBatchPoster', + address: args.sequencerInbox, + args: [args.batchPoster], + }); +} diff --git a/src/actions/isValidKeysetHash.ts b/src/actions/isValidKeysetHash.ts new file mode 100644 index 00000000..1a5e7007 --- /dev/null +++ b/src/actions/isValidKeysetHash.ts @@ -0,0 +1,30 @@ +import { Chain, Hex, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { sequencerInboxABI } from '../contracts/SequencerInbox'; +import { ActionParameters } from '../types/Actions'; + +type Args = { + keysetHash: Hex; +}; + +export type IsValidKeysetHashParameters = ActionParameters< + Args, + 'sequencerInbox', + Curried +>; + +export type IsValidKeysetHashReturnType = ReadContractReturnType< + typeof sequencerInboxABI, + 'isValidKeysetHash' +>; + +export async function isValidKeysetHash( + client: PublicClient, + args: IsValidKeysetHashParameters, +): Promise { + return client.readContract({ + abi: sequencerInboxABI, + functionName: 'isValidKeysetHash', + address: args.sequencerInbox, + args: [args.keysetHash], + }); +} diff --git a/src/index.ts b/src/index.ts index 3f143780..db767cbe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -137,6 +137,7 @@ import { getConsensusReleaseByWasmModuleRoot, GetConsensusReleaseByWasmModuleRoot, } from './wasmModuleRoot'; +export * from './actions'; export { arbOwnerPublicActions, diff --git a/src/types/Actions.ts b/src/types/Actions.ts new file mode 100644 index 00000000..0327ffba --- /dev/null +++ b/src/types/Actions.ts @@ -0,0 +1,22 @@ +import { Address } from 'viem'; +import { Prettify } from './utils'; + +/** + * Actions require contract address, but as part of decorators, the address might have been passed already to the decorator. + * + * If the address was passed to the decorator, it's now optional (we still allow overrides of the address per action). + * If the action doesn't have any other parameters beside the contract address, then parameters can either be { contract: address } or void + */ +export type ActionParameters = Prettify< + Curried extends false + ? Args & { [key in ContractName]: Address } + : Args extends Record + ? + | { + [key in ContractName]: Address; + } + | void + : Args & { + [key in ContractName]?: Address; + } +>; From e14d272f0cbdd26e9c6b410040c2a82c96aa8c7f Mon Sep 17 00:00:00 2001 From: spsjvc Date: Tue, 20 Aug 2024 18:00:16 +0200 Subject: [PATCH 31/54] ci: pin nitro testnode to release (#172) --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 578586b6..d6e08261 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -71,7 +71,7 @@ jobs: - name: Set up the local node uses: OffchainLabs/actions/run-nitro-test-node@feat-simplify with: - nitro-testnode-ref: executor-owner + nitro-testnode-ref: release args: --tokenbridge --l3node --l3-token-bridge --l3-fee-token - name: Copy .env From 3586145c5f52cbc0ae6377dcb4aedf8cb44d3b6e Mon Sep 17 00:00:00 2001 From: spsjvc Date: Mon, 26 Aug 2024 15:15:37 +0200 Subject: [PATCH 32/54] chore: ignore GHSA-952p-6rrq-rcjv advisory (#174) --- audit-ci.jsonc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/audit-ci.jsonc b/audit-ci.jsonc index c7e6fbd7..8cd89c03 100644 --- a/audit-ci.jsonc +++ b/audit-ci.jsonc @@ -79,6 +79,16 @@ // https://github.com/advisories/GHSA-977x-g7h5-7qgw "GHSA-977x-g7h5-7qgw", // https://github.com/advisories/GHSA-f7q4-pwc6-w24p - "GHSA-f7q4-pwc6-w24p" + "GHSA-f7q4-pwc6-w24p", + // https://github.com/advisories/GHSA-952p-6rrq-rcjv + // + // micromatch is vulnerable to Regular Expression Denial of Service + // + // from: @arbitrum/orbit-sdk>@arbitrum/token-bridge-contracts>@arbitrum/nitro-contracts>patch-package>find-yarn-workspace-root>micromatch + // from: @wagmi/cli>globby>fast-glob>micromatch + // from: patch-package>find-yarn-workspace-root>micromatc + // + // all the packages listed above are used only during development + "GHSA-952p-6rrq-rcjv" ] } From 4b6abaf0e02d7d809712af783aeb45659d9da29c Mon Sep 17 00:00:00 2001 From: spsjvc Date: Mon, 26 Aug 2024 15:55:28 +0200 Subject: [PATCH 33/54] fix: make createRollupPrepareTransaction work with v1.1 (#173) --- ...RollupPrepareTransaction.unit.test.ts.snap | 80 +++++++++++++++++++ src/createRollupPrepareTransaction.ts | 41 ++++++++-- ...reateRollupPrepareTransaction.unit.test.ts | 24 ++++++ src/index.ts | 12 ++- src/types/createRollupTypes.ts | 40 ++++++++-- 5 files changed, 183 insertions(+), 14 deletions(-) create mode 100644 src/__snapshots__/createRollupPrepareTransaction.unit.test.ts.snap create mode 100644 src/createRollupPrepareTransaction.unit.test.ts diff --git a/src/__snapshots__/createRollupPrepareTransaction.unit.test.ts.snap b/src/__snapshots__/createRollupPrepareTransaction.unit.test.ts.snap new file mode 100644 index 00000000..b4362ae8 --- /dev/null +++ b/src/__snapshots__/createRollupPrepareTransaction.unit.test.ts.snap @@ -0,0 +1,80 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`successfully parses input calldata for a chain created with RollupCreator v1.1 1`] = ` +[ + { + "batchPoster": "0x3C3A5b44FAB0e2025160a765348c21C08e41d1Af", + "config": { + "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\\":true,\\"InitialArbOSVersion\\":20,\\"GenesisBlockNum\\":0,\\"MaxCodeSize\\":24576,\\"MaxInitCodeSize\\":49152,\\"InitialChainOwner\\":\\"0x41C966f99De0cA6F6531fbcAc9Db7eaBDF119744\\"},\\"chainId\\":30046249195}", + "chainId": 30046249195n, + "confirmPeriodBlocks": 150n, + "extraChallengeTimeBlocks": 0n, + "genesisBlockNum": 0n, + "loserStakeEscrow": "0x0000000000000000000000000000000000000000", + "owner": "0x41C966f99De0cA6F6531fbcAc9Db7eaBDF119744", + "sequencerInboxMaxTimeVariation": { + "delayBlocks": 28800n, + "delaySeconds": 345600n, + "futureBlocks": 300n, + "futureSeconds": 3600n, + }, + "stakeToken": "0x0000000000000000000000000000000000000000", + "wasmModuleRoot": "0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4", + }, + "deployFactoriesToL2": true, + "maxDataSize": 104857n, + "maxFeePerGasForRetryables": 100000000n, + "nativeToken": "0x0000000000000000000000000000000000000000", + "validators": [ + "0x8E842599F71ABD661737bb3108a53E5b1787c791", + ], + }, +] +`; + +exports[`successfully parses input calldata for a chain created with RollupCreator v2.1 1`] = ` +[ + { + "batchPosterManager": "0x0000000000000000000000000000000000000000", + "batchPosters": [ + "0x9464aD09CE0d157Efc6c7EefE577C5AA6dEc804D", + "0xC02386B2D10a37e71145B6A7f5569e1db4604213", + "0x6C4483f6DCEDb5a758b28D28E11F805bdACFE245", + "0xf89836dc33f58394fB34B3e690D3829A65C74286", + "0xd1d25Aeb44E99B35E2d5E7Db961c73ec94f92a24", + "0xDc4ECA04032b9178020Ff0c6154A7e87309a429f", + "0xe122F9838A4C8e6834F24D1b9dCa92eb52a8E17e", + "0xB280Fd59090f3D95588d94BACD22b336dE2278e0", + ], + "config": { + "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\\":true,\\"InitialArbOSVersion\\":20,\\"GenesisBlockNum\\":0,\\"MaxCodeSize\\":24576,\\"MaxInitCodeSize\\":49152,\\"InitialChainOwner\\":\\"0x31bAC660fBB4eF1B91409dB42CB4C6e75527d004\\"},\\"chainId\\":32902132974}", + "chainId": 32902132974n, + "confirmPeriodBlocks": 150n, + "extraChallengeTimeBlocks": 0n, + "genesisBlockNum": 0n, + "loserStakeEscrow": "0x0000000000000000000000000000000000000000", + "owner": "0x31bAC660fBB4eF1B91409dB42CB4C6e75527d004", + "sequencerInboxMaxTimeVariation": { + "delayBlocks": 28800n, + "delaySeconds": 345600n, + "futureBlocks": 300n, + "futureSeconds": 3600n, + }, + "stakeToken": "0x0000000000000000000000000000000000000000", + "wasmModuleRoot": "0x260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc69", + }, + "deployFactoriesToL2": false, + "maxDataSize": 104857n, + "maxFeePerGasForRetryables": 100000000n, + "nativeToken": "0x0000000000000000000000000000000000000000", + "validators": [ + "0xDBb2c9923b5DE18B151bC55Ed571EDcd1fC7EeB9", + "0x84B2EFFDd54aA5dce861440Ae9B9D320b043a64c", + "0x39B4Ce32E557225a401917a701ac4d267648635a", + "0xe2D0cC872647B1A129B942BbFC980B31E8e94Df2", + ], + }, +] +`; diff --git a/src/createRollupPrepareTransaction.ts b/src/createRollupPrepareTransaction.ts index 4528107b..011a8656 100644 --- a/src/createRollupPrepareTransaction.ts +++ b/src/createRollupPrepareTransaction.ts @@ -1,17 +1,46 @@ import { Transaction, decodeFunctionData } from 'viem'; +import { DecodeFunctionDataReturnType } from 'viem/_types/utils/abi/decodeFunctionData'; import { rollupCreatorABI } from './contracts/RollupCreator'; -import { CreateRollupFunctionInputs } from './types/createRollupTypes'; +import { rollupCreatorABI as rollupCreatorV1Dot1ABI } from './contracts/RollupCreator/v1.1'; -function createRollupDecodeFunctionData(data: `0x${string}`) { - return decodeFunctionData({ - abi: rollupCreatorABI, - data, +import { + CreateRollupFunctionInputs, + RollupCreatorABI, + RollupCreatorVersion, + RollupCreatorLatestVersion, +} from './types/createRollupTypes'; + +function createRollupDecodeFunctionData>( + data: `0x${string}`, +): DecodeFunctionDataReturnType { + let result: DecodeFunctionDataReturnType | null = null; + + // try parsing from multiple RollupCreator versions + [ + // v2.1 + rollupCreatorABI, + // v1.1 + rollupCreatorV1Dot1ABI, + ].forEach((abi) => { + try { + result = decodeFunctionData({ abi, data }) as DecodeFunctionDataReturnType; + } catch (error) { + // do nothing + } }); + + if (result === null) { + throw new Error(`[createRollupPrepareTransaction] failed to decode function data`); + } + + return result; } export type CreateRollupTransaction = Transaction & { - getInputs(): CreateRollupFunctionInputs; + getInputs< + TVersion extends RollupCreatorVersion = RollupCreatorLatestVersion, + >(): CreateRollupFunctionInputs; }; export function createRollupPrepareTransaction(tx: Transaction): CreateRollupTransaction { diff --git a/src/createRollupPrepareTransaction.unit.test.ts b/src/createRollupPrepareTransaction.unit.test.ts new file mode 100644 index 00000000..a45775ef --- /dev/null +++ b/src/createRollupPrepareTransaction.unit.test.ts @@ -0,0 +1,24 @@ +import { it, expect } from 'vitest'; +import { Transaction } from 'viem'; + +import { createRollupPrepareTransaction } from './createRollupPrepareTransaction'; + +// https://sepolia.arbiscan.io/tx/0x5b0b49e0259289fc89949a55a5ad35a8939440a55065d29b14e5e7ef7494efff +it('successfully parses input calldata for a chain created with RollupCreator v1.1', () => { + const { getInputs } = createRollupPrepareTransaction({ + input: + '0xcb73d6e2000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000003c3a5b44fab0e2025160a765348c21c08e41d1af00000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000019999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a00008b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a400000000000000000000000041c966f99de0ca6f6531fbcac9db7eabdf119744000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006fee560eb00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007080000000000000000000000000000000000000000000000000000000000000012c00000000000000000000000000000000000000000000000000000000000546000000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000002757b22686f6d657374656164426c6f636b223a302c2264616f466f726b426c6f636b223a6e756c6c2c2264616f466f726b537570706f7274223a747275652c22656970313530426c6f636b223a302c2265697031353048617368223a22307830303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c22656970313535426c6f636b223a302c22656970313538426c6f636b223a302c2262797a616e7469756d426c6f636b223a302c22636f6e7374616e74696e6f706c65426c6f636b223a302c2270657465727362757267426c6f636b223a302c22697374616e62756c426c6f636b223a302c226d756972476c6163696572426c6f636b223a302c226265726c696e426c6f636b223a302c226c6f6e646f6e426c6f636b223a302c22636c69717565223a7b22706572696f64223a302c2265706f6368223a307d2c22617262697472756d223a7b22456e61626c654172624f53223a747275652c22416c6c6f774465627567507265636f6d70696c6573223a66616c73652c2244617461417661696c6162696c697479436f6d6d6974746565223a747275652c22496e697469616c4172624f5356657273696f6e223a32302c2247656e65736973426c6f636b4e756d223a302c224d6178436f646553697a65223a32343537362c224d6178496e6974436f646553697a65223a34393135322c22496e697469616c436861696e4f776e6572223a22307834314339363666393944653063413646363533316662634163394462376561424446313139373434227d2c22636861696e4964223a33303034363234393139357d000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008e842599f71abd661737bb3108a53e5b1787c791', + } as unknown as Transaction); + + expect(getInputs()).toMatchSnapshot(); +}); + +// https://sepolia.arbiscan.io/tx/0x77db43157182a69ce0e6d2a0564d2dabb43b306d48ea7b4d877160d6a1c9b66d +it('successfully parses input calldata for a chain created with RollupCreator v2.1', () => { + const { getInputs } = createRollupPrepareTransaction({ + input: + '0x331f9b0b0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000019999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000260f5fa5c3176a856893642e149cf128b5a8de9f828afec8d11184415dd8dc6900000000000000000000000031bac660fbb4ef1b91409db42cb4c6e75527d004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a91eb4ee00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007080000000000000000000000000000000000000000000000000000000000000012c00000000000000000000000000000000000000000000000000000000000546000000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000002757b22686f6d657374656164426c6f636b223a302c2264616f466f726b426c6f636b223a6e756c6c2c2264616f466f726b537570706f7274223a747275652c22656970313530426c6f636b223a302c2265697031353048617368223a22307830303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c22656970313535426c6f636b223a302c22656970313538426c6f636b223a302c2262797a616e7469756d426c6f636b223a302c22636f6e7374616e74696e6f706c65426c6f636b223a302c2270657465727362757267426c6f636b223a302c22697374616e62756c426c6f636b223a302c226d756972476c6163696572426c6f636b223a302c226265726c696e426c6f636b223a302c226c6f6e646f6e426c6f636b223a302c22636c69717565223a7b22706572696f64223a302c2265706f6368223a307d2c22617262697472756d223a7b22456e61626c654172624f53223a747275652c22416c6c6f774465627567507265636f6d70696c6573223a66616c73652c2244617461417661696c6162696c697479436f6d6d6974746565223a747275652c22496e697469616c4172624f5356657273696f6e223a32302c2247656e65736973426c6f636b4e756d223a302c224d6178436f646553697a65223a32343537362c224d6178496e6974436f646553697a65223a34393135322c22496e697469616c436861696e4f776e6572223a22307833316241433636306642423465463142393134303964423432434234433665373535323764303034227d2c22636861696e4964223a33323930323133323937347d00000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000dbb2c9923b5de18b151bc55ed571edcd1fc7eeb900000000000000000000000084b2effdd54aa5dce861440ae9b9d320b043a64c00000000000000000000000039b4ce32e557225a401917a701ac4d267648635a000000000000000000000000e2d0cc872647b1a129b942bbfc980b31e8e94df200000000000000000000000000000000000000000000000000000000000000080000000000000000000000009464ad09ce0d157efc6c7eefe577c5aa6dec804d000000000000000000000000c02386b2d10a37e71145b6a7f5569e1db46042130000000000000000000000006c4483f6dcedb5a758b28d28e11f805bdacfe245000000000000000000000000f89836dc33f58394fb34b3e690d3829a65c74286000000000000000000000000d1d25aeb44e99b35e2d5e7db961c73ec94f92a24000000000000000000000000dc4eca04032b9178020ff0c6154a7e87309a429f000000000000000000000000e122f9838a4c8e6834f24d1b9dca92eb52a8e17e000000000000000000000000b280fd59090f3d95588d94bacd22b336de2278e0', + } as unknown as Transaction); + + expect(getInputs()).toMatchSnapshot(); +}); diff --git a/src/index.ts b/src/index.ts index db767cbe..5cbd3c94 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,7 +16,13 @@ import { createRollupPrepareCustomFeeTokenApprovalTransactionRequest, CreateRollupPrepareCustomFeeTokenApprovalTransactionRequestParams, } from './createRollupPrepareCustomFeeTokenApprovalTransactionRequest'; -import { CreateRollupFunctionInputs, CreateRollupParams } from './types/createRollupTypes'; +import { + RollupCreatorVersion, + RollupCreatorLatestVersion, + RollupCreatorABI, + CreateRollupFunctionInputs, + CreateRollupParams, +} from './types/createRollupTypes'; import { createRollupPrepareTransactionRequest, CreateRollupPrepareTransactionRequestParams, @@ -150,6 +156,10 @@ export { CreateRollupFunctionInputs, CreateRollupParams, // + RollupCreatorVersion, + RollupCreatorLatestVersion, + RollupCreatorABI, + // createRollupPrepareDeploymentParamsConfig, CreateRollupPrepareDeploymentParamsConfigParams, CreateRollupPrepareDeploymentParamsConfigResult, diff --git a/src/types/createRollupTypes.ts b/src/types/createRollupTypes.ts index f1e43b05..b71d8c8a 100644 --- a/src/types/createRollupTypes.ts +++ b/src/types/createRollupTypes.ts @@ -1,16 +1,42 @@ import { Address, GetFunctionArgs } from 'viem'; import { rollupCreatorABI } from '../contracts/RollupCreator'; +import { rollupCreatorABI as rollupCreatorV1Dot1ABI } from '../contracts/RollupCreator/v1.1'; -export type CreateRollupFunctionInputs = GetFunctionArgs< - typeof rollupCreatorABI, - 'createRollup' ->['args']; +import { Prettify } from './utils'; -type RequiredKeys = 'config' | 'batchPosters' | 'validators'; +export type RollupCreatorVersion = 'v2.1' | 'v1.1'; +export type RollupCreatorLatestVersion = Extract; -export type CreateRollupParams = Pick & - Partial>; +export type RollupCreatorABI = + // + TVersion extends 'v2.1' + ? typeof rollupCreatorABI + : TVersion extends 'v1.1' + ? typeof rollupCreatorV1Dot1ABI + : never; + +export type CreateRollupFunctionInputs< + TVersion extends RollupCreatorVersion = RollupCreatorLatestVersion, +> = GetFunctionArgs, 'createRollup'>['args']; + +type GetCreateRollupRequiredKeys< + TVersion extends RollupCreatorVersion = RollupCreatorLatestVersion, +> = + // + TVersion extends 'v2.1' + ? 'config' | 'batchPosters' | 'validators' + : TVersion extends 'v1.1' + ? 'config' | 'batchPoster' | 'validators' + : never; + +export type CreateRollupParams = + Prettify< + // @ts-ignore this works perfectly fine, not sure why typescript is complaining + Pick[0], GetCreateRollupRequiredKeys> & + // @ts-ignore this works perfectly fine, not sure why typescript is complaining + Partial[0], GetCreateRollupRequiredKeys>> + >; export type WithRollupCreatorAddressOverride = T & { /** From 3170519cc2ca1a1864233fb583f2f47688d39116 Mon Sep 17 00:00:00 2001 From: Christophe Deveaux Date: Tue, 27 Aug 2024 17:58:39 +0200 Subject: [PATCH 34/54] feat: add SequencerInbox setters (#117) --- src/actions/buildInvalidateKeysetHash.ts | 49 +++++++++++++ src/actions/buildSetIsBatchPoster.ts | 63 +++++++++++++++++ src/actions/buildSetMaxTimeVariation.ts | 45 ++++++++++++ src/actions/buildSetValidKeyset.ts | 49 +++++++++++++ src/actions/index.ts | 4 ++ src/prepareUpgradeExecutorCallParameters.ts | 76 +++++++++++++++++++++ src/types/Actions.ts | 14 +++- 7 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 src/actions/buildInvalidateKeysetHash.ts create mode 100644 src/actions/buildSetIsBatchPoster.ts create mode 100644 src/actions/buildSetMaxTimeVariation.ts create mode 100644 src/actions/buildSetValidKeyset.ts create mode 100644 src/prepareUpgradeExecutorCallParameters.ts diff --git a/src/actions/buildInvalidateKeysetHash.ts b/src/actions/buildInvalidateKeysetHash.ts new file mode 100644 index 00000000..30b55039 --- /dev/null +++ b/src/actions/buildInvalidateKeysetHash.ts @@ -0,0 +1,49 @@ +import { Chain, Hex, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { sequencerInboxABI } from '../contracts/SequencerInbox'; +import { + ActionParameters, + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { validateParentChainPublicClient } from '../types/ParentChain'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; + +export type BuildInvalidateKeysetHashParameters = Prettify< + WithUpgradeExecutor< + WithAccount< + ActionParameters< + { + keysetHash: Hex; + }, + 'sequencerInbox', + Curried + > + > + > +>; + +export type BuildInvalidateKeysetHashReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildInvalidateKeysetHash( + client: PublicClient, + params: BuildInvalidateKeysetHashParameters, +): Promise { + const validatedPublicClient = validateParentChainPublicClient(client); + const { account, upgradeExecutor, sequencerInbox: sequencerInboxAddress, ...args } = params; + + const request = await client.prepareTransactionRequest({ + chain: client.chain, + account, + ...prepareUpgradeExecutorCallParameters({ + to: sequencerInboxAddress, + upgradeExecutor, + args: [args.keysetHash], + abi: sequencerInboxABI, + functionName: 'setValidKeyset', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/buildSetIsBatchPoster.ts b/src/actions/buildSetIsBatchPoster.ts new file mode 100644 index 00000000..209eef67 --- /dev/null +++ b/src/actions/buildSetIsBatchPoster.ts @@ -0,0 +1,63 @@ +import { Address, Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { sequencerInboxABI } from '../contracts/SequencerInbox'; +import { + ActionParameters, + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; +import { validateParentChainPublicClient } from '../types/ParentChain'; + +type Args = { + batchPoster: Address; +}; + +export type BuildSetIsBatchPosterParameters = Prettify< + WithUpgradeExecutor>> +>; + +export type BuildSetIsBatchPosterReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +async function buildSetIsBatchPoster( + client: PublicClient, + params: BuildSetIsBatchPosterParameters & { enable: boolean }, +): Promise { + const validatedPublicClient = validateParentChainPublicClient(client); + const { account, upgradeExecutor, sequencerInbox: sequencerInboxAddress, ...args } = params; + + const request = await client.prepareTransactionRequest({ + chain: client.chain, + account, + ...prepareUpgradeExecutorCallParameters({ + to: sequencerInboxAddress, + upgradeExecutor, + args: [args.batchPoster, args.enable], + abi: sequencerInboxABI, + functionName: 'setIsBatchPoster', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} + +export async function buildEnableBatchPoster( + client: PublicClient, + args: BuildSetIsBatchPosterParameters, +): Promise { + return buildSetIsBatchPoster(client, { + ...args, + enable: true, + }); +} + +export async function buildDisableBatchPoster( + client: PublicClient, + args: BuildSetIsBatchPosterParameters, +): Promise { + return buildSetIsBatchPoster(client, { + ...args, + enable: false, + }); +} diff --git a/src/actions/buildSetMaxTimeVariation.ts b/src/actions/buildSetMaxTimeVariation.ts new file mode 100644 index 00000000..aef110fa --- /dev/null +++ b/src/actions/buildSetMaxTimeVariation.ts @@ -0,0 +1,45 @@ +import { Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { sequencerInboxABI } from '../contracts/SequencerInbox'; +import { + ActionParameters, + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; +import { validateParentChainPublicClient } from '../types/ParentChain'; + +type Args = { + delayBlocks: bigint; + futureBlocks: bigint; + delaySeconds: bigint; + futureSeconds: bigint; +}; +export type BuildSetMaxTimeVariationParameters = Prettify< + WithUpgradeExecutor>> +>; + +export type BuildSetMaxTimeVariationReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildSetMaxTimeVariation( + client: PublicClient, + params: BuildSetMaxTimeVariationParameters, +): Promise { + const validatedPublicClient = validateParentChainPublicClient(client); + const { account, upgradeExecutor, sequencerInbox: sequencerInboxAddress, ...args } = params; + + const request = await client.prepareTransactionRequest({ + chain: client.chain, + account, + ...prepareUpgradeExecutorCallParameters({ + to: sequencerInboxAddress, + upgradeExecutor, + args: [args], + abi: sequencerInboxABI, + functionName: 'setMaxTimeVariation', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/buildSetValidKeyset.ts b/src/actions/buildSetValidKeyset.ts new file mode 100644 index 00000000..c690a41c --- /dev/null +++ b/src/actions/buildSetValidKeyset.ts @@ -0,0 +1,49 @@ +import { Chain, Hex, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { sequencerInboxABI } from '../contracts/SequencerInbox'; +import { + ActionParameters, + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { validateParentChainPublicClient } from '../types/ParentChain'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; + +export type BuildSetValidKeysetParameters = Prettify< + WithUpgradeExecutor< + WithAccount< + ActionParameters< + { + keyset: Hex; + }, + 'sequencerInbox', + Curried + > + > + > +>; + +export type BuildSetValidKeysetReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildSetValidKeyset( + client: PublicClient, + params: BuildSetValidKeysetParameters, +): Promise { + const validatedPublicClient = validateParentChainPublicClient(client); + const { account, upgradeExecutor, sequencerInbox: sequencerInboxAddress, ...args } = params; + + const request = await client.prepareTransactionRequest({ + chain: client.chain, + account, + ...prepareUpgradeExecutorCallParameters({ + to: sequencerInboxAddress, + upgradeExecutor, + args: [args.keyset], + abi: sequencerInboxABI, + functionName: 'setValidKeyset', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/index.ts b/src/actions/index.ts index 63164981..28c51440 100644 --- a/src/actions/index.ts +++ b/src/actions/index.ts @@ -1,3 +1,7 @@ export * from './getMaxTimeVariation'; export * from './isBatchPoster'; export * from './isValidKeysetHash'; +export * from './buildInvalidateKeysetHash'; +export * from './buildSetIsBatchPoster'; +export * from './buildSetValidKeyset'; +export * from './buildSetMaxTimeVariation'; diff --git a/src/prepareUpgradeExecutorCallParameters.ts b/src/prepareUpgradeExecutorCallParameters.ts new file mode 100644 index 00000000..dcde21c0 --- /dev/null +++ b/src/prepareUpgradeExecutorCallParameters.ts @@ -0,0 +1,76 @@ +import { + Address, + encodeFunctionData as viemEncodeFunctionData, + EncodeFunctionDataParameters as ViemEncodeFunctionDataParameters, +} from 'viem'; +import { GetFunctionName } from './types/utils'; +import { sequencerInboxABI } from './contracts/SequencerInbox'; +import { arbOwnerABI } from './contracts/ArbOwner'; +import { + upgradeExecutorEncodeFunctionData, + UpgradeExecutorFunctionName, +} from './upgradeExecutorEncodeFunctionData'; + +type ABIs = typeof sequencerInboxABI | typeof arbOwnerABI; +type FunctionName = GetFunctionName; + +type EncodeFunctionDataParameters< + TAbi extends ABIs, + TFunctionName extends FunctionName, +> = ViemEncodeFunctionDataParameters; + +function encodeFunctionData>({ + abi, + functionName, + args, +}: EncodeFunctionDataParameters) { + return viemEncodeFunctionData({ + abi, + functionName, + args, + } as unknown as ViemEncodeFunctionDataParameters); +} + +export function prepareUpgradeExecutorCallParameters< + TAbi extends ABIs, + TFunctionName extends FunctionName, +>( + params: EncodeFunctionDataParameters & + ( + | { + to: Address; + upgradeExecutor: false; + value?: bigint; + } + | { + to: Address; + upgradeExecutor: Address; + value?: bigint; + upgradeExecutorFunctionName?: Extract< + UpgradeExecutorFunctionName, + 'execute' | 'executeCall' + >; + } + ), +) { + const { upgradeExecutor, value = BigInt(0) } = params; + if (!upgradeExecutor) { + return { + to: params.to, + data: encodeFunctionData(params), + value, + }; + } + + return { + to: upgradeExecutor, + data: upgradeExecutorEncodeFunctionData({ + functionName: params.upgradeExecutorFunctionName ?? 'executeCall', + args: [ + params.to, // target + encodeFunctionData(params), // targetCallData + ], + }), + value, + }; +} diff --git a/src/types/Actions.ts b/src/types/Actions.ts index 0327ffba..ba515953 100644 --- a/src/types/Actions.ts +++ b/src/types/Actions.ts @@ -1,4 +1,4 @@ -import { Address } from 'viem'; +import { Address, PrepareTransactionRequestReturnType } from 'viem'; import { Prettify } from './utils'; /** @@ -20,3 +20,15 @@ export type ActionParameters; + +export type WithAccount = Args & { + account: Address; +}; + +export type WithUpgradeExecutor = Args & { + upgradeExecutor: Address | false; +}; + +export type PrepareTransactionRequestReturnTypeWithChainId = PrepareTransactionRequestReturnType & { + chainId: number; +}; From e937f3c4aa772aabd204c9fbc764598addb1cf22 Mon Sep 17 00:00:00 2001 From: Fionna Chan <13184582+fionnachan@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:15:40 +0100 Subject: [PATCH 35/54] build: bump packages and remove advisories (#175) --- audit-ci.jsonc | 26 +------------------------- package.json | 3 ++- yarn.lock | 34 +++++++++++++++++----------------- 3 files changed, 20 insertions(+), 43 deletions(-) diff --git a/audit-ci.jsonc b/audit-ci.jsonc index 8cd89c03..6925ec78 100644 --- a/audit-ci.jsonc +++ b/audit-ci.jsonc @@ -65,30 +65,6 @@ // from: @arbitrum/token-bridge-contracts>@openzeppelin/contracts-upgradeable // from: @arbitrum/nitro-contracts>@openzeppelin/contracts // from: @arbitrum/token-bridge-contracts>@openzeppelin/contracts - "GHSA-9vx6-7xxf-x967", - // https://github.com/advisories/GHSA-grv7-fg5c-xmjg - // Uncontrolled resource consumption in braces - // eslint and hardhat dependency, only used in dev - // from: hardhat>braces & eslint>braces - "GHSA-grv7-fg5c-xmjg", - // elliptic - // waiting for it to release a fix but low severity so we can ignore it - // from: @ethersproject/signing-key>elliptic - // https://github.com/advisories/GHSA-49q7-c7j4-3p7m - "GHSA-49q7-c7j4-3p7m", - // https://github.com/advisories/GHSA-977x-g7h5-7qgw - "GHSA-977x-g7h5-7qgw", - // https://github.com/advisories/GHSA-f7q4-pwc6-w24p - "GHSA-f7q4-pwc6-w24p", - // https://github.com/advisories/GHSA-952p-6rrq-rcjv - // - // micromatch is vulnerable to Regular Expression Denial of Service - // - // from: @arbitrum/orbit-sdk>@arbitrum/token-bridge-contracts>@arbitrum/nitro-contracts>patch-package>find-yarn-workspace-root>micromatch - // from: @wagmi/cli>globby>fast-glob>micromatch - // from: patch-package>find-yarn-workspace-root>micromatc - // - // all the packages listed above are used only during development - "GHSA-952p-6rrq-rcjv" + "GHSA-9vx6-7xxf-x967" ] } diff --git a/package.json b/package.json index fa300036..c93d3b55 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ }, "resolutions": { "**/@wagmi/cli/viem/ws": "8.17.1", - "**/@ethersproject/providers/ws": "7.5.10" + "**/@ethersproject/providers/ws": "7.5.10", + "**/elliptic": "6.5.7" } } diff --git a/yarn.lock b/yarn.lock index 493cf387..20c775ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1213,12 +1213,12 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" brorand@^1.1.0: version "1.1.0" @@ -1596,10 +1596,10 @@ duplexer@^0.1.1, duplexer@~0.1.1: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== -elliptic@6.5.4, elliptic@^6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== +elliptic@6.5.4, elliptic@6.5.7, elliptic@^6.5.4: + version "6.5.7" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" + integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -1936,10 +1936,10 @@ fetch-blob@^3.1.2, fetch-blob@^3.1.4: node-domexception "^1.0.0" web-streams-polyfill "^3.0.3" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -2563,11 +2563,11 @@ merge2@^1.3.0, merge2@^1.4.1: integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" mimic-fn@^2.1.0: From e100388b1f8966498d5d5c5c2b90195b067d68ca Mon Sep 17 00:00:00 2001 From: Christophe Deveaux Date: Tue, 27 Aug 2024 18:25:34 +0200 Subject: [PATCH 36/54] feat: export buildSetIsBatchPoster (#176) --- src/actions/buildSetIsBatchPoster.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/buildSetIsBatchPoster.ts b/src/actions/buildSetIsBatchPoster.ts index 209eef67..a4bbe4c3 100644 --- a/src/actions/buildSetIsBatchPoster.ts +++ b/src/actions/buildSetIsBatchPoster.ts @@ -20,7 +20,7 @@ export type BuildSetIsBatchPosterParameters = P export type BuildSetIsBatchPosterReturnType = PrepareTransactionRequestReturnTypeWithChainId; -async function buildSetIsBatchPoster( +export async function buildSetIsBatchPoster( client: PublicClient, params: BuildSetIsBatchPosterParameters & { enable: boolean }, ): Promise { From 4e61b48fa94287a269bbd1cc96d834fbe784dd2b Mon Sep 17 00:00:00 2001 From: spsjvc Date: Wed, 28 Aug 2024 11:18:03 +0200 Subject: [PATCH 37/54] chore: bump version --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 110fc384..316eca52 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.18.0", + "version": "0.19.0-beta.0", "main": "./dist/index.js", "files": [ "./dist" From 95d0a78cfca04ff298347376a14ceec6e993b07b Mon Sep 17 00:00:00 2001 From: Christophe Date: Thu, 27 Jun 2024 20:12:43 +0000 Subject: [PATCH 38/54] Feat: Add v1 RollupAdminLogic getters Closes FS-620 --- src/actions/getConfirmPeriodBlocks.ts | 25 ++++++++++++++++++++++ src/actions/getExtraChallengeTimeBlocks.ts | 22 +++++++++++++++++++ src/actions/getMinimumAssertionPeriod.ts | 25 ++++++++++++++++++++++ src/actions/getWasmModuleRoot.ts | 25 ++++++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 src/actions/getConfirmPeriodBlocks.ts create mode 100644 src/actions/getExtraChallengeTimeBlocks.ts create mode 100644 src/actions/getMinimumAssertionPeriod.ts create mode 100644 src/actions/getWasmModuleRoot.ts diff --git a/src/actions/getConfirmPeriodBlocks.ts b/src/actions/getConfirmPeriodBlocks.ts new file mode 100644 index 00000000..327aa571 --- /dev/null +++ b/src/actions/getConfirmPeriodBlocks.ts @@ -0,0 +1,25 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters } from '../types/Actions'; + +export type GetConfirmPeriodBlocksParameters = ActionParameters< + {}, + 'rollupAdminLogic', + Curried +>; + +export type GetConfirmPeriodBlocksReturnType = ReadContractReturnType< + typeof rollupAdminLogic.abi, + 'confirmPeriodBlocks' +>; + +export async function getConfirmPeriodBlocks( + client: PublicClient, + args: GetConfirmPeriodBlocksParameters, +): Promise { + return client.readContract({ + abi: rollupAdminLogic.abi, + functionName: 'confirmPeriodBlocks', + address: args.rollupAdminLogic, + }); +} diff --git a/src/actions/getExtraChallengeTimeBlocks.ts b/src/actions/getExtraChallengeTimeBlocks.ts new file mode 100644 index 00000000..ede8f8b2 --- /dev/null +++ b/src/actions/getExtraChallengeTimeBlocks.ts @@ -0,0 +1,22 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters } from '../types/Actions'; + +export type GetExtraChallengeTimeBlocksParameters = + ActionParameters<{}, 'rollupAdminLogic', Curried>; + +export type GetExtraChallengeTimeBlocksReturnType = ReadContractReturnType< + typeof rollupAdminLogic.abi, + 'extraChallengeTimeBlocks' +>; + +export async function getExtraChallengeTimeBlocks( + client: PublicClient, + args: GetExtraChallengeTimeBlocksParameters, +): Promise { + return client.readContract({ + abi: rollupAdminLogic.abi, + functionName: 'extraChallengeTimeBlocks', + address: args.rollupAdminLogic, + }); +} diff --git a/src/actions/getMinimumAssertionPeriod.ts b/src/actions/getMinimumAssertionPeriod.ts new file mode 100644 index 00000000..c250b2ce --- /dev/null +++ b/src/actions/getMinimumAssertionPeriod.ts @@ -0,0 +1,25 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters } from '../types/Actions'; + +export type GetMinimumAssertionPeriodParameters = ActionParameters< + {}, + 'rollupAdminLogic', + Curried +>; + +export type GetMinimumAssertionPeriodReturnType = ReadContractReturnType< + typeof rollupAdminLogic.abi, + 'minimumAssertionPeriod' +>; + +export async function getMinimumAssertionPeriod( + client: PublicClient, + args: GetMinimumAssertionPeriodParameters, +): Promise { + return client.readContract({ + abi: rollupAdminLogic.abi, + functionName: 'minimumAssertionPeriod', + address: args.rollupAdminLogic, + }); +} diff --git a/src/actions/getWasmModuleRoot.ts b/src/actions/getWasmModuleRoot.ts new file mode 100644 index 00000000..ba6b23cd --- /dev/null +++ b/src/actions/getWasmModuleRoot.ts @@ -0,0 +1,25 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters } from '../types/Actions'; + +export type GetWasmModuleRootParameters = ActionParameters< + {}, + 'rollupAdminLogic', + Curried +>; + +export type GetWasmModuleRootReturnType = ReadContractReturnType< + typeof rollupAdminLogic.abi, + 'wasmModuleRoot' +>; + +export async function getWasmModuleRoot( + client: PublicClient, + args: GetWasmModuleRootParameters, +): Promise { + return client.readContract({ + abi: rollupAdminLogic.abi, + functionName: 'wasmModuleRoot', + address: args.rollupAdminLogic, + }); +} From be0739904f2c30d80f2c2fbdf893d5f0be07c91c Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 2 Jul 2024 10:22:32 +0000 Subject: [PATCH 39/54] Fetch rollupAddress from sequencerInbox in getters --- src/actions/getConfirmPeriodBlocks.ts | 8 ++++--- src/actions/getExtraChallengeTimeBlocks.ts | 8 ++++--- src/actions/getMinimumAssertionPeriod.ts | 13 +++++------ src/actions/getWasmModuleRoot.ts | 8 ++++--- src/getRollupAddress.ts | 27 ++++++++++++++++++++++ 5 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 src/getRollupAddress.ts diff --git a/src/actions/getConfirmPeriodBlocks.ts b/src/actions/getConfirmPeriodBlocks.ts index 327aa571..120db86a 100644 --- a/src/actions/getConfirmPeriodBlocks.ts +++ b/src/actions/getConfirmPeriodBlocks.ts @@ -1,8 +1,9 @@ import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters } from '../types/Actions'; +import { WithContractAddress } from '../types/Actions'; +import { getRollupAddress } from '../getRollupAddress'; -export type GetConfirmPeriodBlocksParameters = ActionParameters< +export type GetConfirmPeriodBlocksParameters = WithContractAddress< {}, 'rollupAdminLogic', Curried @@ -17,9 +18,10 @@ export async function getConfirmPeriodBlocks( client: PublicClient, args: GetConfirmPeriodBlocksParameters, ): Promise { + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.readContract({ abi: rollupAdminLogic.abi, functionName: 'confirmPeriodBlocks', - address: args.rollupAdminLogic, + address: rollupAdminLogicAddresss, }); } diff --git a/src/actions/getExtraChallengeTimeBlocks.ts b/src/actions/getExtraChallengeTimeBlocks.ts index ede8f8b2..0bce1c4f 100644 --- a/src/actions/getExtraChallengeTimeBlocks.ts +++ b/src/actions/getExtraChallengeTimeBlocks.ts @@ -1,9 +1,10 @@ import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters } from '../types/Actions'; +import { WithContractAddress } from '../types/Actions'; +import { getRollupAddress } from '../getRollupAddress'; export type GetExtraChallengeTimeBlocksParameters = - ActionParameters<{}, 'rollupAdminLogic', Curried>; + WithContractAddress<{}, 'rollupAdminLogic', Curried>; export type GetExtraChallengeTimeBlocksReturnType = ReadContractReturnType< typeof rollupAdminLogic.abi, @@ -14,9 +15,10 @@ export async function getExtraChallengeTimeBlocks, args: GetExtraChallengeTimeBlocksParameters, ): Promise { + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.readContract({ abi: rollupAdminLogic.abi, functionName: 'extraChallengeTimeBlocks', - address: args.rollupAdminLogic, + address: rollupAdminLogicAddresss, }); } diff --git a/src/actions/getMinimumAssertionPeriod.ts b/src/actions/getMinimumAssertionPeriod.ts index c250b2ce..0ff81960 100644 --- a/src/actions/getMinimumAssertionPeriod.ts +++ b/src/actions/getMinimumAssertionPeriod.ts @@ -1,12 +1,10 @@ import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters } from '../types/Actions'; +import { WithContractAddress } from '../types/Actions'; +import { getRollupAddress } from '../getRollupAddress'; -export type GetMinimumAssertionPeriodParameters = ActionParameters< - {}, - 'rollupAdminLogic', - Curried ->; +export type GetMinimumAssertionPeriodParameters = + WithContractAddress<{}, 'rollupAdminLogic', Curried>; export type GetMinimumAssertionPeriodReturnType = ReadContractReturnType< typeof rollupAdminLogic.abi, @@ -17,9 +15,10 @@ export async function getMinimumAssertionPeriod, args: GetMinimumAssertionPeriodParameters, ): Promise { + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.readContract({ abi: rollupAdminLogic.abi, functionName: 'minimumAssertionPeriod', - address: args.rollupAdminLogic, + address: rollupAdminLogicAddresss, }); } diff --git a/src/actions/getWasmModuleRoot.ts b/src/actions/getWasmModuleRoot.ts index ba6b23cd..8798b32d 100644 --- a/src/actions/getWasmModuleRoot.ts +++ b/src/actions/getWasmModuleRoot.ts @@ -1,8 +1,9 @@ import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters } from '../types/Actions'; +import { WithContractAddress } from '../types/Actions'; +import { getRollupAddress } from '../getRollupAddress'; -export type GetWasmModuleRootParameters = ActionParameters< +export type GetWasmModuleRootParameters = WithContractAddress< {}, 'rollupAdminLogic', Curried @@ -17,9 +18,10 @@ export async function getWasmModuleRoot( client: PublicClient, args: GetWasmModuleRootParameters, ): Promise { + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.readContract({ abi: rollupAdminLogic.abi, functionName: 'wasmModuleRoot', - address: args.rollupAdminLogic, + address: rollupAdminLogicAddresss, }); } diff --git a/src/getRollupAddress.ts b/src/getRollupAddress.ts new file mode 100644 index 00000000..532d0e8a --- /dev/null +++ b/src/getRollupAddress.ts @@ -0,0 +1,27 @@ +import { Address, Chain, PublicClient, Transport } from 'viem'; +import { sequencerInboxABI } from './abi'; + +const cache: Record = {}; +export async function getRollupAddress( + publicClient: PublicClient, + params: { sequencerInbox: Address } | { rollupAdminLogic: Address }, +): Promise
{ + // rollupAdminLogic was passed as an override, return directly + if ('rollupAdminLogic' in params) { + return params.rollupAdminLogic; + } + + const addressFromCache = cache[params.sequencerInbox]; + if (addressFromCache) { + return addressFromCache; + } + + // Otherwise, fetch the rollup address from sequencerInbox contract + const rollupAddress = await publicClient.readContract({ + functionName: 'rollup', + address: params.sequencerInbox, + abi: sequencerInboxABI, + }); + cache[params.sequencerInbox] = rollupAddress; + return rollupAddress; +} From ab36d2dfd570610402ea2f391ecd40c2ec8b16a7 Mon Sep 17 00:00:00 2001 From: Christophe Date: Wed, 10 Jul 2024 15:51:27 +0000 Subject: [PATCH 40/54] Update cache key --- src/getRollupAddress.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/getRollupAddress.ts b/src/getRollupAddress.ts index 532d0e8a..8adf7a7e 100644 --- a/src/getRollupAddress.ts +++ b/src/getRollupAddress.ts @@ -1,7 +1,7 @@ import { Address, Chain, PublicClient, Transport } from 'viem'; import { sequencerInboxABI } from './abi'; -const cache: Record = {}; +const cache: Record = {}; export async function getRollupAddress( publicClient: PublicClient, params: { sequencerInbox: Address } | { rollupAdminLogic: Address }, @@ -11,7 +11,7 @@ export async function getRollupAddress( return params.rollupAdminLogic; } - const addressFromCache = cache[params.sequencerInbox]; + const addressFromCache = cache[`${publicClient.chain?.id}_${params.sequencerInbox}`]; if (addressFromCache) { return addressFromCache; } @@ -22,6 +22,6 @@ export async function getRollupAddress( address: params.sequencerInbox, abi: sequencerInboxABI, }); - cache[params.sequencerInbox] = rollupAddress; + cache[`${publicClient.chain?.id}_${params.sequencerInbox}`] = rollupAddress; return rollupAddress; } From c2e8a55ed7ba913457f98ab49d7d1772533c854c Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 28 Jun 2024 12:54:27 +0000 Subject: [PATCH 41/54] Feat: Add v1 ArbOwnerPublic getters --- src/actions/getAllChainOwners.ts | 20 ++++++++++++++++++++ src/actions/getInfraFeeAccount.ts | 20 ++++++++++++++++++++ src/actions/getNetworkFeeAccount.ts | 20 ++++++++++++++++++++ src/actions/getScheduledUpgrade.ts | 28 ++++++++++++++++++++++++++++ src/actions/isChainOwner.ts | 21 +++++++++++++++++++++ 5 files changed, 109 insertions(+) create mode 100644 src/actions/getAllChainOwners.ts create mode 100644 src/actions/getInfraFeeAccount.ts create mode 100644 src/actions/getNetworkFeeAccount.ts create mode 100644 src/actions/getScheduledUpgrade.ts create mode 100644 src/actions/isChainOwner.ts diff --git a/src/actions/getAllChainOwners.ts b/src/actions/getAllChainOwners.ts new file mode 100644 index 00000000..41c69dd0 --- /dev/null +++ b/src/actions/getAllChainOwners.ts @@ -0,0 +1,20 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublic } from '../contracts'; + +type ArbOwnerPublicABI = typeof arbOwnerPublic.abi; +export type GetAllChainOwnersParameters = void; + +export type GetAllChainOwnersReturnType = ReadContractReturnType< + ArbOwnerPublicABI, + 'getAllChainOwners' +>; + +export async function getAllChainOwners( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbOwnerPublic.abi, + functionName: 'getAllChainOwners', + address: arbOwnerPublic.address, + }); +} diff --git a/src/actions/getInfraFeeAccount.ts b/src/actions/getInfraFeeAccount.ts new file mode 100644 index 00000000..bdd7bd13 --- /dev/null +++ b/src/actions/getInfraFeeAccount.ts @@ -0,0 +1,20 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublic } from '../contracts'; + +type ArbOwnerPublicABI = typeof arbOwnerPublic.abi; +export type GetInfraFeeAccountParameters = void; + +export type GetInfraFeeAccountReturnType = ReadContractReturnType< + ArbOwnerPublicABI, + 'getInfraFeeAccount' +>; + +export async function getInfraFeeAccount( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbOwnerPublic.abi, + functionName: 'getInfraFeeAccount', + address: arbOwnerPublic.address, + }); +} diff --git a/src/actions/getNetworkFeeAccount.ts b/src/actions/getNetworkFeeAccount.ts new file mode 100644 index 00000000..334e93ff --- /dev/null +++ b/src/actions/getNetworkFeeAccount.ts @@ -0,0 +1,20 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublic } from '../contracts'; + +type ArbOwnerPublicABI = typeof arbOwnerPublic.abi; +export type GetNetworkFeeAccountParameters = void; + +export type GetNetworkFeeAccountReturnType = ReadContractReturnType< + ArbOwnerPublicABI, + 'getNetworkFeeAccount' +>; + +export async function getNetworkFeeAccount( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbOwnerPublic.abi, + functionName: 'getNetworkFeeAccount', + address: arbOwnerPublic.address, + }); +} diff --git a/src/actions/getScheduledUpgrade.ts b/src/actions/getScheduledUpgrade.ts new file mode 100644 index 00000000..6d634fc4 --- /dev/null +++ b/src/actions/getScheduledUpgrade.ts @@ -0,0 +1,28 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublic } from '../contracts'; + +type ArbOwnerPublicABI = typeof arbOwnerPublic.abi; +export type GetScheduledUpgradeParameters = void; + +type GetScheduledUpgradeRawReturnType = ReadContractReturnType< + ArbOwnerPublicABI, + 'getScheduledUpgrade' +>; +export type GetScheduledUpgradeReturnType = { + arbosVersion: GetScheduledUpgradeRawReturnType[0]; + scheduledForTimestamp: GetScheduledUpgradeRawReturnType[1]; +}; + +export async function getScheduledUpgrade( + client: PublicClient, +): Promise { + const [arbosVersion, scheduledForTimestamp] = await client.readContract({ + abi: arbOwnerPublic.abi, + functionName: 'getScheduledUpgrade', + address: arbOwnerPublic.address, + }); + return { + arbosVersion, + scheduledForTimestamp, + }; +} diff --git a/src/actions/isChainOwner.ts b/src/actions/isChainOwner.ts new file mode 100644 index 00000000..aebaeadc --- /dev/null +++ b/src/actions/isChainOwner.ts @@ -0,0 +1,21 @@ +import { Address, Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublic } from '../contracts'; + +type ArbOwnerPublicABI = typeof arbOwnerPublic.abi; +export type IsChainOwnerParameters = { + address: Address; +}; + +export type IsChainOwnerReturnType = ReadContractReturnType; + +export async function isChainOwner( + client: PublicClient, + args: IsChainOwnerParameters, +): Promise { + return client.readContract({ + abi: arbOwnerPublic.abi, + functionName: 'isChainOwner', + address: arbOwnerPublic.address, + args: [args.address], + }); +} From 02e6fdf5dc3ca59418f6e4c0ed699eaf8a93462a Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 28 Jun 2024 15:05:11 +0000 Subject: [PATCH 42/54] Feat: Add v1 ArbGasInfo getters --- src/actions/getGasAccountingParams.ts | 20 ++++++++++++++++++++ src/actions/getMinimumGasPrice.ts | 20 ++++++++++++++++++++ src/actions/getParentBaseFeeEstimate.ts | 20 ++++++++++++++++++++ src/actions/getParentRewardRate.ts | 20 ++++++++++++++++++++ src/actions/getParentRewardRecipient.ts | 20 ++++++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 src/actions/getGasAccountingParams.ts create mode 100644 src/actions/getMinimumGasPrice.ts create mode 100644 src/actions/getParentBaseFeeEstimate.ts create mode 100644 src/actions/getParentRewardRate.ts create mode 100644 src/actions/getParentRewardRecipient.ts diff --git a/src/actions/getGasAccountingParams.ts b/src/actions/getGasAccountingParams.ts new file mode 100644 index 00000000..fd8dfbff --- /dev/null +++ b/src/actions/getGasAccountingParams.ts @@ -0,0 +1,20 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfo } from '../contracts'; + +type ArbGasInfoABI = typeof arbGasInfo.abi; +export type GetGasAccountingParamsParameters = void; + +export type GetGasAccountingParamsReturnType = ReadContractReturnType< + ArbGasInfoABI, + 'getGasAccountingParams' +>; + +export async function getGasAccountingParams( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfo.abi, + functionName: 'getGasAccountingParams', + address: arbGasInfo.address, + }); +} diff --git a/src/actions/getMinimumGasPrice.ts b/src/actions/getMinimumGasPrice.ts new file mode 100644 index 00000000..5d285b72 --- /dev/null +++ b/src/actions/getMinimumGasPrice.ts @@ -0,0 +1,20 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfo } from '../contracts'; + +type ArbGasInfoABI = typeof arbGasInfo.abi; +export type GetMinimumGasPriceParameters = void; + +export type GetMinimumGasPriceReturnType = ReadContractReturnType< + ArbGasInfoABI, + 'getMinimumGasPrice' +>; + +export async function getMinimumGasPrice( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfo.abi, + functionName: 'getMinimumGasPrice', + address: arbGasInfo.address, + }); +} diff --git a/src/actions/getParentBaseFeeEstimate.ts b/src/actions/getParentBaseFeeEstimate.ts new file mode 100644 index 00000000..a83b8e50 --- /dev/null +++ b/src/actions/getParentBaseFeeEstimate.ts @@ -0,0 +1,20 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfo } from '../contracts'; + +type ArbGasInfoABI = typeof arbGasInfo.abi; +export type GetParentbaseFeeEstimateParameters = void; + +export type GetParentbaseFeeEstimateReturnType = ReadContractReturnType< + ArbGasInfoABI, + 'getL1BaseFeeEstimate' +>; + +export async function getParentbaseFeeEstimate( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfo.abi, + functionName: 'getL1BaseFeeEstimate', + address: arbGasInfo.address, + }); +} diff --git a/src/actions/getParentRewardRate.ts b/src/actions/getParentRewardRate.ts new file mode 100644 index 00000000..7be94c03 --- /dev/null +++ b/src/actions/getParentRewardRate.ts @@ -0,0 +1,20 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfo } from '../contracts'; + +type ArbGasInfoABI = typeof arbGasInfo.abi; +export type GetParentRewardRateParameters = void; + +export type GetParentRewardRateReturnType = ReadContractReturnType< + ArbGasInfoABI, + 'getL1RewardRate' +>; + +export async function getParentRewardRate( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfo.abi, + functionName: 'getL1RewardRate', + address: arbGasInfo.address, + }); +} diff --git a/src/actions/getParentRewardRecipient.ts b/src/actions/getParentRewardRecipient.ts new file mode 100644 index 00000000..433d0ebd --- /dev/null +++ b/src/actions/getParentRewardRecipient.ts @@ -0,0 +1,20 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfo } from '../contracts'; + +type ArbGasInfoABI = typeof arbGasInfo.abi; +export type GetParentRewardRecipientParameters = void; + +export type GetParentRewardRecipientReturnType = ReadContractReturnType< + ArbGasInfoABI, + 'getL1RewardRecipient' +>; + +export async function getParentRewardRecipient( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfo.abi, + functionName: 'getL1RewardRecipient', + address: arbGasInfo.address, + }); +} From d0925ab230de71445fc27d9a2f967ebe46f49224 Mon Sep 17 00:00:00 2001 From: Christophe Date: Mon, 1 Jul 2024 11:39:21 +0000 Subject: [PATCH 43/54] Use proper case for getParentBaseFeeEstimate --- src/actions/getParentBaseFeeEstimate.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/actions/getParentBaseFeeEstimate.ts b/src/actions/getParentBaseFeeEstimate.ts index a83b8e50..704e6b9e 100644 --- a/src/actions/getParentBaseFeeEstimate.ts +++ b/src/actions/getParentBaseFeeEstimate.ts @@ -2,16 +2,16 @@ import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; import { arbGasInfo } from '../contracts'; type ArbGasInfoABI = typeof arbGasInfo.abi; -export type GetParentbaseFeeEstimateParameters = void; +export type GetParentBaseFeeEstimateParameters = void; -export type GetParentbaseFeeEstimateReturnType = ReadContractReturnType< +export type GetParentBaseFeeEstimateReturnType = ReadContractReturnType< ArbGasInfoABI, 'getL1BaseFeeEstimate' >; -export async function getParentbaseFeeEstimate( +export async function getParentBaseFeeEstimate( client: PublicClient, -): Promise { +): Promise { return client.readContract({ abi: arbGasInfo.abi, functionName: 'getL1BaseFeeEstimate', From fdc75013da6f8fada3234e9585ad45ead0f6c897 Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 28 Jun 2024 15:30:19 +0000 Subject: [PATCH 44/54] Feat: Add v1 upgradeExecutor getters --- src/actions/hasRole.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/actions/hasRole.ts diff --git a/src/actions/hasRole.ts b/src/actions/hasRole.ts new file mode 100644 index 00000000..45f754c6 --- /dev/null +++ b/src/actions/hasRole.ts @@ -0,0 +1,29 @@ +import { Address, Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { upgradeExecutor } from '../contracts'; +import { ActionParameters } from '../types/Actions'; +import { UpgradeExecutorRole } from '../upgradeExecutorEncodeFunctionData'; + +type Args = { + role: UpgradeExecutorRole; + address: Address; +}; +type UpgradeExecutorABI = typeof upgradeExecutor.abi; +export type hasRoleParameters = ActionParameters< + Args, + 'upgradeExecutor', + Curried +>; + +export type hasRoleReturnType = ReadContractReturnType; + +export async function hasRole( + client: PublicClient, + args: hasRoleParameters, +): Promise { + return client.readContract({ + abi: upgradeExecutor.abi, + functionName: 'hasRole', + address: args.upgradeExecutor, + args: [args.role, args.address], + }); +} From 81a09e57ca7e2513d4acac88abf9a8cd775b23c8 Mon Sep 17 00:00:00 2001 From: Christophe Date: Thu, 27 Jun 2024 19:08:07 +0000 Subject: [PATCH 45/54] Feat: Add v1 SequencerInbox setters Closes FS-535 --- src/actions/invalidateKeysetHash.ts | 49 +++++++++++++++++++++ src/actions/setIsbatchPoster.ts | 67 +++++++++++++++++++++++++++++ src/actions/setKeyset.ts | 49 +++++++++++++++++++++ src/actions/setMaxTimeVariation.ts | 46 ++++++++++++++++++++ 4 files changed, 211 insertions(+) create mode 100644 src/actions/invalidateKeysetHash.ts create mode 100644 src/actions/setIsbatchPoster.ts create mode 100644 src/actions/setKeyset.ts create mode 100644 src/actions/setMaxTimeVariation.ts diff --git a/src/actions/invalidateKeysetHash.ts b/src/actions/invalidateKeysetHash.ts new file mode 100644 index 00000000..1d0bd681 --- /dev/null +++ b/src/actions/invalidateKeysetHash.ts @@ -0,0 +1,49 @@ +import { + Chain, + Hex, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { sequencerInbox } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type InvalidateKeysetHashParameters = Prettify< + WithAccount< + ActionParameters< + { + keysetHash: Hex; + }, + 'sequencerInbox', + Curried + > + > +>; + +export type InvalidateKeysetHashReturnType = PrepareTransactionRequestReturnType; + +function sequencerInboxFunctionData({ keysetHash }: InvalidateKeysetHashParameters) { + return encodeFunctionData({ + abi: sequencerInbox.abi, + functionName: 'invalidateKeysetHash', + args: [keysetHash], + }); +} + +export async function invalidateKeysetHash( + client: PublicClient, + args: InvalidateKeysetHashParameters, +): Promise { + const data = sequencerInboxFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.sequencerInbox, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setIsbatchPoster.ts b/src/actions/setIsbatchPoster.ts new file mode 100644 index 00000000..eef471d3 --- /dev/null +++ b/src/actions/setIsbatchPoster.ts @@ -0,0 +1,67 @@ +import { + Address, + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { sequencerInbox } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +type Args = { + batchPoster: Address; +}; + +export type SetIsBatchPosterParameters = Prettify< + WithAccount> +>; + +export type SetIsBatchPosterReturnType = PrepareTransactionRequestReturnType; + +function sequencerInboxFunctionData({ + batchPoster, + enable, +}: SetIsBatchPosterParameters & { enable: boolean }) { + return encodeFunctionData({ + abi: sequencerInbox.abi, + functionName: 'setIsBatchPoster', + args: [batchPoster, enable], + }); +} + +async function setIsBatchPoster( + client: PublicClient, + args: SetIsBatchPosterParameters & { enable: boolean }, +): Promise { + const data = sequencerInboxFunctionData(args); + return client.prepareTransactionRequest({ + to: args.sequencerInbox, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} + +export async function enableBatchPoster( + client: PublicClient, + args: SetIsBatchPosterParameters, +): Promise { + return setIsBatchPoster(client, { + ...args, + enable: true, + }); +} + +export async function disableBatchPoster( + client: PublicClient, + args: SetIsBatchPosterParameters, +): Promise { + return setIsBatchPoster(client, { + ...args, + enable: false, + }); +} diff --git a/src/actions/setKeyset.ts b/src/actions/setKeyset.ts new file mode 100644 index 00000000..d71c1212 --- /dev/null +++ b/src/actions/setKeyset.ts @@ -0,0 +1,49 @@ +import { + Chain, + Hex, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { sequencerInbox } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetKeysetParameters = Prettify< + WithAccount< + ActionParameters< + { + keyset: Hex; + }, + 'sequencerInbox', + Curried + > + > +>; + +export type SetKeysetReturnType = PrepareTransactionRequestReturnType; + +function sequencerInboxFunctionData({ keyset }: SetKeysetParameters) { + return encodeFunctionData({ + abi: sequencerInbox.abi, + functionName: 'setValidKeyset', + args: [keyset], + }); +} + +export async function setKeyset( + client: PublicClient, + args: SetKeysetParameters, +): Promise { + const data = sequencerInboxFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.sequencerInbox, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setMaxTimeVariation.ts b/src/actions/setMaxTimeVariation.ts new file mode 100644 index 00000000..7f763d84 --- /dev/null +++ b/src/actions/setMaxTimeVariation.ts @@ -0,0 +1,46 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { sequencerInbox } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +type Args = { + delayBlocks: bigint; + futureBlocks: bigint; + delaySeconds: bigint; + futureSeconds: bigint; +}; +export type SetMaxTimeVariationParameters = Prettify< + WithAccount> +>; + +export type SetMaxTimeVariationReturnType = PrepareTransactionRequestReturnType; + +function sequencerInboxFunctionData(args: SetMaxTimeVariationParameters) { + return encodeFunctionData({ + abi: sequencerInbox.abi, + functionName: 'setMaxTimeVariation', + args: [args], + }); +} + +export async function setMaxTimeVariation( + client: PublicClient, + args: SetMaxTimeVariationParameters, +): Promise { + const data = sequencerInboxFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.sequencerInbox, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} From 795894a6b7631dc467068fa1e4a45412b9bfb4c7 Mon Sep 17 00:00:00 2001 From: Christophe Date: Thu, 27 Jun 2024 21:12:15 +0000 Subject: [PATCH 46/54] Feat: Add v1 RollupAdminLogic setters Closes FS-621 --- src/actions/setConfirmPeriodBlocks.ts | 48 +++++++++++++++ src/actions/setExtraChallengeTimeBlocks.ts | 50 ++++++++++++++++ src/actions/setMinimumAssertionPeriod.ts | 48 +++++++++++++++ src/actions/setValidator.ts | 47 +++++++++++++++ src/actions/setValidatorWhitelistDisabled.ts | 61 ++++++++++++++++++++ src/actions/setWasmModuleRoot.ts | 49 ++++++++++++++++ 6 files changed, 303 insertions(+) create mode 100644 src/actions/setConfirmPeriodBlocks.ts create mode 100644 src/actions/setExtraChallengeTimeBlocks.ts create mode 100644 src/actions/setMinimumAssertionPeriod.ts create mode 100644 src/actions/setValidator.ts create mode 100644 src/actions/setValidatorWhitelistDisabled.ts create mode 100644 src/actions/setWasmModuleRoot.ts diff --git a/src/actions/setConfirmPeriodBlocks.ts b/src/actions/setConfirmPeriodBlocks.ts new file mode 100644 index 00000000..89a4be54 --- /dev/null +++ b/src/actions/setConfirmPeriodBlocks.ts @@ -0,0 +1,48 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetConfirmPeriodBlocksParameters = Prettify< + WithAccount< + ActionParameters< + { + newPeriod: bigint; + }, + 'rollupAdminLogic', + Curried + > + > +>; + +export type SetConfirmPeriodBlocksReturnType = PrepareTransactionRequestReturnType; + +function rollupAdminLogicFunctionData({ newPeriod }: SetConfirmPeriodBlocksParameters) { + return encodeFunctionData({ + abi: rollupAdminLogic.abi, + functionName: 'setConfirmPeriodBlocks', + args: [newPeriod], + }); +} + +export async function setConfirmPeriodBlocks( + client: PublicClient, + args: SetConfirmPeriodBlocksParameters, +): Promise { + const data = rollupAdminLogicFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.rollupAdminLogic, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setExtraChallengeTimeBlocks.ts b/src/actions/setExtraChallengeTimeBlocks.ts new file mode 100644 index 00000000..265b8d84 --- /dev/null +++ b/src/actions/setExtraChallengeTimeBlocks.ts @@ -0,0 +1,50 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetExtraChallengeTimeBlocksParameters = Prettify< + WithAccount< + ActionParameters< + { + newExtraTimeBlocks: bigint; + }, + 'rollupAdminLogic', + Curried + > + > +>; + +export type SetExtraChallengeTimeBlocksReturnType = PrepareTransactionRequestReturnType; + +function rollupAdminLogicFunctionData({ + newExtraTimeBlocks, +}: SetExtraChallengeTimeBlocksParameters) { + return encodeFunctionData({ + abi: rollupAdminLogic.abi, + functionName: 'setExtraChallengeTimeBlocks', + args: [newExtraTimeBlocks], + }); +} + +export async function setExtraChallengeTimeBlocks( + client: PublicClient, + args: SetExtraChallengeTimeBlocksParameters, +): Promise { + const data = rollupAdminLogicFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.rollupAdminLogic, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setMinimumAssertionPeriod.ts b/src/actions/setMinimumAssertionPeriod.ts new file mode 100644 index 00000000..1eed2739 --- /dev/null +++ b/src/actions/setMinimumAssertionPeriod.ts @@ -0,0 +1,48 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetMinimumAssertionPeriodParameters = Prettify< + WithAccount< + ActionParameters< + { + newPeriod: bigint; + }, + 'rollupAdminLogic', + Curried + > + > +>; + +export type SetMinimumAssertionPeriodReturnType = PrepareTransactionRequestReturnType; + +function rollupAdminLogicFunctionData({ newPeriod }: SetMinimumAssertionPeriodParameters) { + return encodeFunctionData({ + abi: rollupAdminLogic.abi, + functionName: 'setMinimumAssertionPeriod', + args: [newPeriod], + }); +} + +export async function setMinimumAssertionPeriod( + client: PublicClient, + args: SetMinimumAssertionPeriodParameters, +): Promise { + const data = rollupAdminLogicFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.rollupAdminLogic, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setValidator.ts b/src/actions/setValidator.ts new file mode 100644 index 00000000..f49a8ba0 --- /dev/null +++ b/src/actions/setValidator.ts @@ -0,0 +1,47 @@ +import { + Address, + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +type Args = { + add: Address[]; + remove: Address[]; +}; + +export type SetIsValidatorParameters = Prettify< + WithAccount> +>; + +export type SetIsValidatorReturnType = PrepareTransactionRequestReturnType; + +function rollupAdminLogicFunctionData({ add, remove }: SetIsValidatorParameters) { + const addState: boolean[] = new Array(add.length).fill(true); + const removeState: boolean[] = new Array(remove.length).fill(false); + return encodeFunctionData({ + abi: rollupAdminLogic.abi, + functionName: 'setValidator', + args: [add.concat(remove), addState.concat(removeState)], + }); +} + +export async function setValidators( + client: PublicClient, + args: SetIsValidatorParameters, +): Promise { + const data = rollupAdminLogicFunctionData(args); + return client.prepareTransactionRequest({ + to: args.rollupAdminLogic, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setValidatorWhitelistDisabled.ts b/src/actions/setValidatorWhitelistDisabled.ts new file mode 100644 index 00000000..38f36abd --- /dev/null +++ b/src/actions/setValidatorWhitelistDisabled.ts @@ -0,0 +1,61 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetValidatorWhitelistDisabledParameters = Prettify< + WithAccount> +>; + +export type SetValidatorWhitelistDisabledReturnType = PrepareTransactionRequestReturnType; + +function rollupAdminLogicFunctionData({ + enable, +}: SetValidatorWhitelistDisabledParameters & { enable: boolean }) { + return encodeFunctionData({ + abi: rollupAdminLogic.abi, + functionName: 'setValidatorWhitelistDisabled', + args: [enable], + }); +} + +async function setValidatorWhitelistDisabled( + client: PublicClient, + args: SetValidatorWhitelistDisabledParameters & { enable: boolean }, +): Promise { + const data = rollupAdminLogicFunctionData(args); + return client.prepareTransactionRequest({ + to: args.rollupAdminLogic, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} + +export async function enableValidatorWhitelist( + client: PublicClient, + args: SetValidatorWhitelistDisabledParameters, +): Promise { + return setValidatorWhitelistDisabled(client, { + ...args, + enable: true, + }); +} + +export async function disableValidatorWhitelist( + client: PublicClient, + args: SetValidatorWhitelistDisabledParameters, +): Promise { + return setValidatorWhitelistDisabled(client, { + ...args, + enable: false, + }); +} diff --git a/src/actions/setWasmModuleRoot.ts b/src/actions/setWasmModuleRoot.ts new file mode 100644 index 00000000..7c856d7d --- /dev/null +++ b/src/actions/setWasmModuleRoot.ts @@ -0,0 +1,49 @@ +import { + Chain, + Hex, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetWasmModuleRootParameters = Prettify< + WithAccount< + ActionParameters< + { + newWasmModuleRoot: Hex; + }, + 'rollupAdminLogic', + Curried + > + > +>; + +export type SetWasmModuleRootReturnType = PrepareTransactionRequestReturnType; + +function rollupAdminLogicFunctionData({ newWasmModuleRoot }: SetWasmModuleRootParameters) { + return encodeFunctionData({ + abi: rollupAdminLogic.abi, + functionName: 'setWasmModuleRoot', + args: [newWasmModuleRoot], + }); +} + +export async function setWasmModuleRoot( + client: PublicClient, + args: SetWasmModuleRootParameters, +): Promise { + const data = rollupAdminLogicFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.rollupAdminLogic, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} From 2dfedf93a180f239ead04a168d0fa8cbabea1645 Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 2 Jul 2024 10:23:26 +0000 Subject: [PATCH 47/54] Fetch rollupAddress from sequencerInbox in setters --- src/actions/setConfirmPeriodBlocks.ts | 17 +++++---------- src/actions/setExtraChallengeTimeBlocks.ts | 17 +++++---------- src/actions/setMinimumAssertionPeriod.ts | 17 +++++---------- src/actions/setValidator.ts | 22 +++++++++++++------- src/actions/setValidatorWhitelistDisabled.ts | 8 ++++--- src/actions/setWasmModuleRoot.ts | 9 ++++---- 6 files changed, 39 insertions(+), 51 deletions(-) diff --git a/src/actions/setConfirmPeriodBlocks.ts b/src/actions/setConfirmPeriodBlocks.ts index 89a4be54..47b951a5 100644 --- a/src/actions/setConfirmPeriodBlocks.ts +++ b/src/actions/setConfirmPeriodBlocks.ts @@ -7,19 +7,12 @@ import { encodeFunctionData, } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters, WithAccount } from '../types/Actions'; +import { WithAccount, WithContractAddress } from '../types/Actions'; import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; export type SetConfirmPeriodBlocksParameters = Prettify< - WithAccount< - ActionParameters< - { - newPeriod: bigint; - }, - 'rollupAdminLogic', - Curried - > - > + WithAccount> >; export type SetConfirmPeriodBlocksReturnType = PrepareTransactionRequestReturnType; @@ -37,9 +30,9 @@ export async function setConfirmPeriodBlocks( args: SetConfirmPeriodBlocksParameters, ): Promise { const data = rollupAdminLogicFunctionData(args); - + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.prepareTransactionRequest({ - to: args.rollupAdminLogic, + to: rollupAdminLogicAddresss, value: BigInt(0), chain: client.chain, data, diff --git a/src/actions/setExtraChallengeTimeBlocks.ts b/src/actions/setExtraChallengeTimeBlocks.ts index 265b8d84..4f35ce27 100644 --- a/src/actions/setExtraChallengeTimeBlocks.ts +++ b/src/actions/setExtraChallengeTimeBlocks.ts @@ -7,19 +7,12 @@ import { encodeFunctionData, } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters, WithAccount } from '../types/Actions'; +import { WithAccount, WithContractAddress } from '../types/Actions'; import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; export type SetExtraChallengeTimeBlocksParameters = Prettify< - WithAccount< - ActionParameters< - { - newExtraTimeBlocks: bigint; - }, - 'rollupAdminLogic', - Curried - > - > + WithAccount> >; export type SetExtraChallengeTimeBlocksReturnType = PrepareTransactionRequestReturnType; @@ -39,9 +32,9 @@ export async function setExtraChallengeTimeBlocks { const data = rollupAdminLogicFunctionData(args); - + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.prepareTransactionRequest({ - to: args.rollupAdminLogic, + to: rollupAdminLogicAddresss, value: BigInt(0), chain: client.chain, data, diff --git a/src/actions/setMinimumAssertionPeriod.ts b/src/actions/setMinimumAssertionPeriod.ts index 1eed2739..051b7bc4 100644 --- a/src/actions/setMinimumAssertionPeriod.ts +++ b/src/actions/setMinimumAssertionPeriod.ts @@ -7,19 +7,12 @@ import { encodeFunctionData, } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters, WithAccount } from '../types/Actions'; +import { WithAccount, WithContractAddress } from '../types/Actions'; import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; export type SetMinimumAssertionPeriodParameters = Prettify< - WithAccount< - ActionParameters< - { - newPeriod: bigint; - }, - 'rollupAdminLogic', - Curried - > - > + WithAccount> >; export type SetMinimumAssertionPeriodReturnType = PrepareTransactionRequestReturnType; @@ -37,9 +30,9 @@ export async function setMinimumAssertionPeriod { const data = rollupAdminLogicFunctionData(args); - + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.prepareTransactionRequest({ - to: args.rollupAdminLogic, + to: rollupAdminLogicAddresss, value: BigInt(0), chain: client.chain, data, diff --git a/src/actions/setValidator.ts b/src/actions/setValidator.ts index f49a8ba0..1163e68b 100644 --- a/src/actions/setValidator.ts +++ b/src/actions/setValidator.ts @@ -8,16 +8,21 @@ import { encodeFunctionData, } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters, WithAccount } from '../types/Actions'; +import { WithAccount, WithContractAddress } from '../types/Actions'; import { Prettify } from '../types/utils'; - -type Args = { - add: Address[]; - remove: Address[]; -}; +import { getRollupAddress } from '../getRollupAddress'; export type SetIsValidatorParameters = Prettify< - WithAccount> + WithAccount< + WithContractAddress< + { + add: Address[]; + remove: Address[]; + }, + 'rollupAdminLogic', + Curried + > + > >; export type SetIsValidatorReturnType = PrepareTransactionRequestReturnType; @@ -37,8 +42,9 @@ export async function setValidators( args: SetIsValidatorParameters, ): Promise { const data = rollupAdminLogicFunctionData(args); + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.prepareTransactionRequest({ - to: args.rollupAdminLogic, + to: rollupAdminLogicAddresss, value: BigInt(0), chain: client.chain, data, diff --git a/src/actions/setValidatorWhitelistDisabled.ts b/src/actions/setValidatorWhitelistDisabled.ts index 38f36abd..a6ecd8eb 100644 --- a/src/actions/setValidatorWhitelistDisabled.ts +++ b/src/actions/setValidatorWhitelistDisabled.ts @@ -7,11 +7,12 @@ import { encodeFunctionData, } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters, WithAccount } from '../types/Actions'; +import { WithAccount, WithContractAddress } from '../types/Actions'; import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; export type SetValidatorWhitelistDisabledParameters = Prettify< - WithAccount> + WithAccount> >; export type SetValidatorWhitelistDisabledReturnType = PrepareTransactionRequestReturnType; @@ -31,8 +32,9 @@ async function setValidatorWhitelistDisabled( args: SetValidatorWhitelistDisabledParameters & { enable: boolean }, ): Promise { const data = rollupAdminLogicFunctionData(args); + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.prepareTransactionRequest({ - to: args.rollupAdminLogic, + to: rollupAdminLogicAddresss, value: BigInt(0), chain: client.chain, data, diff --git a/src/actions/setWasmModuleRoot.ts b/src/actions/setWasmModuleRoot.ts index 7c856d7d..d9be7561 100644 --- a/src/actions/setWasmModuleRoot.ts +++ b/src/actions/setWasmModuleRoot.ts @@ -8,12 +8,13 @@ import { encodeFunctionData, } from 'viem'; import { rollupAdminLogic } from '../contracts'; -import { ActionParameters, WithAccount } from '../types/Actions'; +import { WithAccount, WithContractAddress } from '../types/Actions'; import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; export type SetWasmModuleRootParameters = Prettify< WithAccount< - ActionParameters< + WithContractAddress< { newWasmModuleRoot: Hex; }, @@ -38,9 +39,9 @@ export async function setWasmModuleRoot( args: SetWasmModuleRootParameters, ): Promise { const data = rollupAdminLogicFunctionData(args); - + const rollupAdminLogicAddresss = await getRollupAddress(client, args); return client.prepareTransactionRequest({ - to: args.rollupAdminLogic, + to: rollupAdminLogicAddresss, value: BigInt(0), chain: client.chain, data, From e5d1cb9ef48b846507cf522e0f8d7d1e1a012ba6 Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 28 Jun 2024 13:50:05 +0000 Subject: [PATCH 48/54] Feat: Add v1 ArbOwnerPublic setters --- src/actions/addChainOwner.ts | 43 +++++++++++++++++++ src/actions/removeChainOwner.ts | 43 +++++++++++++++++++ src/actions/setMaxTxGasLimit.ts | 42 ++++++++++++++++++ src/actions/setParentPricePerUnit.ts | 42 ++++++++++++++++++ src/actions/setParentPricingRewardRate.ts | 42 ++++++++++++++++++ .../setParentPricingRewardRecipient.ts | 43 +++++++++++++++++++ src/actions/setSpeedLimit.ts | 42 ++++++++++++++++++ 7 files changed, 297 insertions(+) create mode 100644 src/actions/addChainOwner.ts create mode 100644 src/actions/removeChainOwner.ts create mode 100644 src/actions/setMaxTxGasLimit.ts create mode 100644 src/actions/setParentPricePerUnit.ts create mode 100644 src/actions/setParentPricingRewardRate.ts create mode 100644 src/actions/setParentPricingRewardRecipient.ts create mode 100644 src/actions/setSpeedLimit.ts diff --git a/src/actions/addChainOwner.ts b/src/actions/addChainOwner.ts new file mode 100644 index 00000000..27c2e581 --- /dev/null +++ b/src/actions/addChainOwner.ts @@ -0,0 +1,43 @@ +import { + Address, + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { arbOwner } from '../contracts'; +import { WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type AddChainOwnerParameters = Prettify< + WithAccount<{ + newOwner: Address; + }> +>; + +export type AddChainOwnerReturnType = PrepareTransactionRequestReturnType; + +function arbOwnerFunctionData({ newOwner }: AddChainOwnerParameters) { + return encodeFunctionData({ + abi: arbOwner.abi, + functionName: 'addChainOwner', + args: [newOwner], + }); +} + +export async function addChainOwner( + client: PublicClient, + args: AddChainOwnerParameters, +): Promise { + const data = arbOwnerFunctionData(args); + + return client.prepareTransactionRequest({ + to: arbOwner.address, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/removeChainOwner.ts b/src/actions/removeChainOwner.ts new file mode 100644 index 00000000..04e6d9d5 --- /dev/null +++ b/src/actions/removeChainOwner.ts @@ -0,0 +1,43 @@ +import { + Address, + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { arbOwner } from '../contracts'; +import { WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type RemoveChainOwnerParameters = Prettify< + WithAccount<{ + owner: Address; + }> +>; + +export type RemoveChainOwnerReturnType = PrepareTransactionRequestReturnType; + +function arbOwnerFunctionData({ owner }: RemoveChainOwnerParameters) { + return encodeFunctionData({ + abi: arbOwner.abi, + functionName: 'removeChainOwner', + args: [owner], + }); +} + +export async function removeChainOwner( + client: PublicClient, + args: RemoveChainOwnerParameters, +): Promise { + const data = arbOwnerFunctionData(args); + + return client.prepareTransactionRequest({ + to: arbOwner.address, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setMaxTxGasLimit.ts b/src/actions/setMaxTxGasLimit.ts new file mode 100644 index 00000000..c414f8df --- /dev/null +++ b/src/actions/setMaxTxGasLimit.ts @@ -0,0 +1,42 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { arbOwner } from '../contracts'; +import { WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetMaxTxGasLimitParameters = Prettify< + WithAccount<{ + limit: bigint; + }> +>; + +export type SetMaxTxGasLimitReturnType = PrepareTransactionRequestReturnType; + +function arbOwnerFunctionData({ limit }: SetMaxTxGasLimitParameters) { + return encodeFunctionData({ + abi: arbOwner.abi, + functionName: 'setMaxTxGasLimit', + args: [limit], + }); +} + +export async function setL1PricingRewardRecipient( + client: PublicClient, + args: SetMaxTxGasLimitParameters, +): Promise { + const data = arbOwnerFunctionData(args); + + return client.prepareTransactionRequest({ + to: arbOwner.address, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setParentPricePerUnit.ts b/src/actions/setParentPricePerUnit.ts new file mode 100644 index 00000000..ef726318 --- /dev/null +++ b/src/actions/setParentPricePerUnit.ts @@ -0,0 +1,42 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { arbOwner } from '../contracts'; +import { WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetParentPricePerUnitParameters = Prettify< + WithAccount<{ + pricePerUnit: bigint; + }> +>; + +export type SetParentPricePerUnitReturnType = PrepareTransactionRequestReturnType; + +function arbOwnerFunctionData({ pricePerUnit }: SetParentPricePerUnitParameters) { + return encodeFunctionData({ + abi: arbOwner.abi, + functionName: 'setL1PricePerUnit', + args: [pricePerUnit], + }); +} + +export async function setParentPricePerUnit( + client: PublicClient, + args: SetParentPricePerUnitParameters, +): Promise { + const data = arbOwnerFunctionData(args); + + return client.prepareTransactionRequest({ + to: arbOwner.address, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setParentPricingRewardRate.ts b/src/actions/setParentPricingRewardRate.ts new file mode 100644 index 00000000..c101b087 --- /dev/null +++ b/src/actions/setParentPricingRewardRate.ts @@ -0,0 +1,42 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { arbOwner } from '../contracts'; +import { WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetParentPricingRewardRateParameters = Prettify< + WithAccount<{ + weiPerUnit: bigint; + }> +>; + +export type SetParentPricingRewardRateReturnType = PrepareTransactionRequestReturnType; + +function arbOwnerFunctionData({ weiPerUnit }: SetParentPricingRewardRateParameters) { + return encodeFunctionData({ + abi: arbOwner.abi, + functionName: 'setL1PricingRewardRate', + args: [weiPerUnit], + }); +} + +export async function setParentPricingRewardRate( + client: PublicClient, + args: SetParentPricingRewardRateParameters, +): Promise { + const data = arbOwnerFunctionData(args); + + return client.prepareTransactionRequest({ + to: arbOwner.address, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setParentPricingRewardRecipient.ts b/src/actions/setParentPricingRewardRecipient.ts new file mode 100644 index 00000000..99568ba2 --- /dev/null +++ b/src/actions/setParentPricingRewardRecipient.ts @@ -0,0 +1,43 @@ +import { + Address, + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { arbOwner } from '../contracts'; +import { WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetParentPricingRewardRecipientParameters = Prettify< + WithAccount<{ + recipient: Address; + }> +>; + +export type SetParentPricingRewardRecipientReturnType = PrepareTransactionRequestReturnType; + +function arbOwnerFunctionData({ recipient }: SetParentPricingRewardRecipientParameters) { + return encodeFunctionData({ + abi: arbOwner.abi, + functionName: 'setL1PricingRewardRecipient', + args: [recipient], + }); +} + +export async function setParentPricingRewardRecipient( + client: PublicClient, + args: SetParentPricingRewardRecipientParameters, +): Promise { + const data = arbOwnerFunctionData(args); + + return client.prepareTransactionRequest({ + to: arbOwner.address, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/setSpeedLimit.ts b/src/actions/setSpeedLimit.ts new file mode 100644 index 00000000..9495fa86 --- /dev/null +++ b/src/actions/setSpeedLimit.ts @@ -0,0 +1,42 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { arbOwner } from '../contracts'; +import { WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; + +export type SetSpeedLimitParameters = Prettify< + WithAccount<{ + limit: bigint; + }> +>; + +export type SetSpeedLimitReturnType = PrepareTransactionRequestReturnType; + +function arbOwnerFunctionData({ limit }: SetSpeedLimitParameters) { + return encodeFunctionData({ + abi: arbOwner.abi, + functionName: 'setSpeedLimit', + args: [limit], + }); +} + +export async function setSpeedLimit( + client: PublicClient, + args: SetSpeedLimitParameters, +): Promise { + const data = arbOwnerFunctionData(args); + + return client.prepareTransactionRequest({ + to: arbOwner.address, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} From 8a219dd553f6c4318929cd160b1ed16ca889a6e1 Mon Sep 17 00:00:00 2001 From: Christophe Date: Mon, 1 Jul 2024 11:57:59 +0000 Subject: [PATCH 49/54] Rename setMaxTxGasLimit --- src/actions/setMaxTxGasLimit.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/setMaxTxGasLimit.ts b/src/actions/setMaxTxGasLimit.ts index c414f8df..d388c9d4 100644 --- a/src/actions/setMaxTxGasLimit.ts +++ b/src/actions/setMaxTxGasLimit.ts @@ -26,7 +26,7 @@ function arbOwnerFunctionData({ limit }: SetMaxTxGasLimitParameters) { }); } -export async function setL1PricingRewardRecipient( +export async function setMaxTxGasLimit( client: PublicClient, args: SetMaxTxGasLimitParameters, ): Promise { From 3e8811c596fb92bd8a646e9b0d694ac7e2ed2d23 Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 28 Jun 2024 15:38:50 +0000 Subject: [PATCH 50/54] Feat: Add v1 upgradeExecutor setters --- src/actions/addExecutor.ts | 50 +++++++++++++++++++++++++++++++++++ src/actions/removeExecutor.ts | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 src/actions/addExecutor.ts create mode 100644 src/actions/removeExecutor.ts diff --git a/src/actions/addExecutor.ts b/src/actions/addExecutor.ts new file mode 100644 index 00000000..f4f5ca37 --- /dev/null +++ b/src/actions/addExecutor.ts @@ -0,0 +1,50 @@ +import { + Address, + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { upgradeExecutor } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { UPGRADE_EXECUTOR_ROLE_EXECUTOR } from '../upgradeExecutorEncodeFunctionData'; + +export type AddExecutorParameters = Prettify< + WithAccount< + ActionParameters< + { + address: Address; + }, + 'upgradeExecutor', + Curried + > + > +>; + +export type AddExecutorReturnType = PrepareTransactionRequestReturnType; + +function upgradeExecutorFunctionData({ address }: AddExecutorParameters) { + return encodeFunctionData({ + abi: upgradeExecutor.abi, + functionName: 'grantRole', + args: [UPGRADE_EXECUTOR_ROLE_EXECUTOR, address], + }); +} + +export async function addExecutor( + client: PublicClient, + args: AddExecutorParameters, +): Promise { + const data = upgradeExecutorFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.upgradeExecutor, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} diff --git a/src/actions/removeExecutor.ts b/src/actions/removeExecutor.ts new file mode 100644 index 00000000..71249d26 --- /dev/null +++ b/src/actions/removeExecutor.ts @@ -0,0 +1,50 @@ +import { + Address, + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { upgradeExecutor } from '../contracts'; +import { ActionParameters, WithAccount } from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { UPGRADE_EXECUTOR_ROLE_EXECUTOR } from '../upgradeExecutorEncodeFunctionData'; + +export type RemoveExecutorParameters = Prettify< + WithAccount< + ActionParameters< + { + address: Address; + }, + 'upgradeExecutor', + Curried + > + > +>; + +export type RemoveExecutorReturnType = PrepareTransactionRequestReturnType; + +function upgradeExecutorFunctionData({ address }: RemoveExecutorParameters) { + return encodeFunctionData({ + abi: upgradeExecutor.abi, + functionName: 'revokeRole', + args: [UPGRADE_EXECUTOR_ROLE_EXECUTOR, address], + }); +} + +export async function removeExecutor( + client: PublicClient, + args: RemoveExecutorParameters, +): Promise { + const data = upgradeExecutorFunctionData(args); + + return client.prepareTransactionRequest({ + to: args.upgradeExecutor, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} From 5beddc030d04cbd1069a425993f528bca7118bbe Mon Sep 17 00:00:00 2001 From: Christophe Date: Mon, 1 Jul 2024 12:41:51 +0000 Subject: [PATCH 51/54] Feat: Add v1 publicActionsChildChain --- src/chains.ts | 28 +++ .../publicActionsChildChain.unit.test.ts.snap | 30 +++ src/decorators/publicActionsChildChain.ts | 178 ++++++++++++++++++ .../publicActionsChildChain.unit.test.ts | 72 +++++++ 4 files changed, 308 insertions(+) create mode 100644 src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap create mode 100644 src/decorators/publicActionsChildChain.ts create mode 100644 src/decorators/publicActionsChildChain.unit.test.ts diff --git a/src/chains.ts b/src/chains.ts index b2525fe4..0f5f9d91 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -96,3 +96,31 @@ export { nitroTestnodeL2, nitroTestnodeL3, }; + +export const xai = defineChain({ + id: 660279, + network: 'Xai Mainnet', + name: 'Xai Mainnet', + nativeCurrency: { name: 'Xai', symbol: 'XAI', decimals: 18 }, + rpcUrls: { + public: { + http: ['https://xai-chain.net/rpc'], + }, + default: { + http: ['https://xai-chain.net/rpc'], + }, + }, + blockExplorers: { + default: { + name: 'Blockscout', + url: 'https://explorer.xai-chain.net', + }, + }, + contracts: { + multicall3: { + address: '0xca11bde05977b3631167028862be2a173976ca11', + blockCreated: 222549, + }, + }, + testnet: false, +}); diff --git a/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap b/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap new file mode 100644 index 00000000..7dc5520d --- /dev/null +++ b/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap @@ -0,0 +1,30 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Getters > [getAllChainOwners] Should return all chain owners 1`] = `[]`; + +exports[`Getters > [getGasAccountingParams] Should return gas accounting params 1`] = ` +[ + 7000000n, + 32000000n, + 32000000n, +] +`; + +exports[`Getters > [getInfraFeeAccount] Should return infra fee account 1`] = `"0xbF5041Fc07E1c866D15c749156657B8eEd0fb649"`; + +exports[`Getters > [getMinimumGasPrice] Should return minimum gas price 1`] = `10000000n`; + +exports[`Getters > [getNetworkFeeAccount] Should return network fee account 1`] = `"0x32e7AF5A8151934F3787d0cD59EB6EDd0a736b1d"`; + +exports[`Getters > [getParentBaseFeeEstimate] Should return parent base fee estimate 1`] = `106354669n`; + +exports[`Getters > [getParentRewardRate] Should return parent reward rate 1`] = `0n`; + +exports[`Getters > [getParentRewardRecipient] Should return parent reward recipient 1`] = `"0x2E041280627800801E90E9Ac83532fadb6cAd99A"`; + +exports[`Getters > [getScheduledUpgrade] Should return scheduled upgrade 1`] = ` +{ + "arbosVersion": 0n, + "scheduledForTimestamp": 0n, +} +`; diff --git a/src/decorators/publicActionsChildChain.ts b/src/decorators/publicActionsChildChain.ts new file mode 100644 index 00000000..9f234b9c --- /dev/null +++ b/src/decorators/publicActionsChildChain.ts @@ -0,0 +1,178 @@ +import { Chain, PublicClient, Transport } from 'viem'; + +// Getters +import { + getAllChainOwners, + GetAllChainOwnersParameters, + GetAllChainOwnersReturnType, +} from '../actions/getAllChainOwners'; +import { + getInfraFeeAccount, + GetInfraFeeAccountParameters, + GetInfraFeeAccountReturnType, +} from '../actions/getInfraFeeAccount'; +import { + getNetworkFeeAccount, + GetNetworkFeeAccountParameters, + GetNetworkFeeAccountReturnType, +} from '../actions/getNetworkFeeAccount'; +import { + getScheduledUpgrade, + GetScheduledUpgradeParameters, + GetScheduledUpgradeReturnType, +} from '../actions/getScheduledUpgrade'; +import { + isChainOwner, + IsChainOwnerParameters, + IsChainOwnerReturnType, +} from '../actions/isChainOwner'; +import { + getGasAccountingParams, + GetGasAccountingParamsParameters, + GetGasAccountingParamsReturnType, +} from '../actions/getGasAccountingParams'; +import { + getMinimumGasPrice, + GetMinimumGasPriceParameters, + GetMinimumGasPriceReturnType, +} from '../actions/getMinimumGasPrice'; +import { + getParentBaseFeeEstimate, + GetParentBaseFeeEstimateParameters, + GetParentBaseFeeEstimateReturnType, +} from '../actions/getParentBaseFeeEstimate'; +import { + getParentRewardRate, + GetParentRewardRateParameters, + GetParentRewardRateReturnType, +} from '../actions/getParentRewardRate'; +import { + getParentRewardRecipient, + GetParentRewardRecipientParameters, + GetParentRewardRecipientReturnType, +} from '../actions/getParentRewardRecipient'; +// Setters +import { + addChainOwner, + AddChainOwnerParameters, + AddChainOwnerReturnType, +} from '../actions/addChainOwner'; +import { + removeChainOwner, + RemoveChainOwnerParameters, + RemoveChainOwnerReturnType, +} from '../actions/removeChainOwner'; +import { + setMaxTxGasLimit, + SetMaxTxGasLimitParameters, + SetMaxTxGasLimitReturnType, +} from '../actions/setMaxTxGasLimit'; +import { + setParentPricePerUnit, + SetParentPricePerUnitParameters, + SetParentPricePerUnitReturnType, +} from '../actions/setParentPricePerUnit'; +import { + setParentPricingRewardRate, + SetParentPricingRewardRateParameters, + SetParentPricingRewardRateReturnType, +} from '../actions/setParentPricingRewardRate'; +import { + setParentPricingRewardRecipient, + SetParentPricingRewardRecipientParameters, + SetParentPricingRewardRecipientReturnType, +} from '../actions/setParentPricingRewardRecipient'; +import { + setSpeedLimit, + SetSpeedLimitParameters, + SetSpeedLimitReturnType, +} from '../actions/setSpeedLimit'; + +export type PublicActionsChildChain = { + // Getters + getAllChainOwners: ( + parameters: GetAllChainOwnersParameters, + ) => Promise; + getInfraFeeAccount: ( + parameters: GetInfraFeeAccountParameters, + ) => Promise; + getNetworkFeeAccount: ( + parameters: GetNetworkFeeAccountParameters, + ) => Promise; + getScheduledUpgrade: ( + parameters: GetScheduledUpgradeParameters, + ) => Promise; + isChainOwner: (parameters: IsChainOwnerParameters) => Promise; + getGasAccountingParams: ( + parameters: GetGasAccountingParamsParameters, + ) => Promise; + getMinimumGasPrice: ( + parameters: GetMinimumGasPriceParameters, + ) => Promise; + getParentBaseFeeEstimate: ( + parameters: GetParentBaseFeeEstimateParameters, + ) => Promise; + getParentRewardRate: ( + parameters: GetParentRewardRateParameters, + ) => Promise; + getParentRewardRecipient: ( + parameters: GetParentRewardRecipientParameters, + ) => Promise; + // Setters + addChainOwner: (parameters: AddChainOwnerParameters) => Promise; + removeChainOwner: (parameters: RemoveChainOwnerParameters) => Promise; + setMaxTxGasLimit: (parameters: SetMaxTxGasLimitParameters) => Promise; + setParentPricePerUnit: ( + parameters: SetParentPricePerUnitParameters, + ) => Promise; + setParentPricingRewardRate: ( + parameters: SetParentPricingRewardRateParameters, + ) => Promise; + setParentPricingRewardRecipient: ( + parameters: SetParentPricingRewardRecipientParameters, + ) => Promise; + setSpeedLimit: (parameters: SetSpeedLimitParameters) => Promise; +}; + +/** + * Public actions for child chain + * + * @example + * import { createPublicClient, http } from 'viem' + * import { publicActionsChildChain } from '@arbitrum/orbit-sdk' + * + * export const publicClientChildChain = createPublicClient({ + * chain: orbitChain, + * transport: http(), + * }).extend(publicActionsChildChain()) + * + * const isAChainOwner = await publicClientChildChain.isChainOwner({ address: zeroAddress }) + */ +export function publicActionsChildChain< + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined, +>() { + return (client: PublicClient) => { + return { + // Getters + getAllChainOwners: () => getAllChainOwners(client), + getInfraFeeAccount: () => getInfraFeeAccount(client), + getNetworkFeeAccount: () => getNetworkFeeAccount(client), + getScheduledUpgrade: () => getScheduledUpgrade(client), + isChainOwner: (args) => isChainOwner(client, args), + getGasAccountingParams: () => getGasAccountingParams(client), + getMinimumGasPrice: () => getMinimumGasPrice(client), + getParentBaseFeeEstimate: () => getParentBaseFeeEstimate(client), + getParentRewardRate: () => getParentRewardRate(client), + getParentRewardRecipient: () => getParentRewardRecipient(client), + // Setters + addChainOwner: (args) => addChainOwner(client, args), + removeChainOwner: (args) => removeChainOwner(client, args), + setMaxTxGasLimit: (args) => setMaxTxGasLimit(client, args), + setParentPricePerUnit: (args) => setParentPricePerUnit(client, args), + setParentPricingRewardRate: (args) => setParentPricingRewardRate(client, args), + setParentPricingRewardRecipient: (args) => setParentPricingRewardRecipient(client, args), + setSpeedLimit: (args) => setSpeedLimit(client, args), + } satisfies PublicActionsChildChain; + }; +} diff --git a/src/decorators/publicActionsChildChain.unit.test.ts b/src/decorators/publicActionsChildChain.unit.test.ts new file mode 100644 index 00000000..94bb86c0 --- /dev/null +++ b/src/decorators/publicActionsChildChain.unit.test.ts @@ -0,0 +1,72 @@ +import { it, expect, describe } from 'vitest'; + +import { createPublicClient, http, zeroAddress } from 'viem'; +import { publicActionsChildChain } from './publicActionsChildChain'; +import { arbitrum } from 'viem/chains'; +import { xai } from '../chains'; + +const client = createPublicClient({ + chain: arbitrum, + transport: http(), +}).extend(publicActionsChildChain()); + +describe('Getters', () => { + it('[getAllChainOwners] Should return all chain owners', async () => { + const allChainOwners = await client.getAllChainOwners(); + expect(allChainOwners).toMatchSnapshot(); + }); + + it('[getInfraFeeAccount] Should return infra fee account', async () => { + const infraFeeAccount = await client.getInfraFeeAccount(); + expect(infraFeeAccount).toMatchSnapshot(); + }); + + it('[getNetworkFeeAccount] Should return network fee account', async () => { + const networkFeeAccount = await client.getNetworkFeeAccount(); + expect(networkFeeAccount).toMatchSnapshot(); + }); + + it('[getScheduledUpgrade] Should return scheduled upgrade', async () => { + const scheduledUpgrade = await client.getScheduledUpgrade(); + expect(scheduledUpgrade).toMatchSnapshot(); + }); + + it('[isChainOwner] Should return if an address is a chain owner', async () => { + const xaiClient = createPublicClient({ + chain: xai, + transport: http(), + }).extend(publicActionsChildChain()); + const isZeroAddressChainOwner = await xaiClient.isChainOwner({ address: zeroAddress }); + expect(isZeroAddressChainOwner).toBeFalsy(); + const allChainOwners = await xaiClient.getAllChainOwners(); + const isChainOwner = await xaiClient.isChainOwner({ + address: allChainOwners[0], + }); + expect(isChainOwner).toBeTruthy(); + }); + + it('[getGasAccountingParams] Should return gas accounting params', async () => { + const gasAccountingParams = await client.getGasAccountingParams(); + expect(gasAccountingParams).toMatchSnapshot(); + }); + + it('[getMinimumGasPrice] Should return minimum gas price', async () => { + const minimumGasPrice = await client.getMinimumGasPrice(); + expect(minimumGasPrice).toMatchSnapshot(); + }); + + it('[getParentBaseFeeEstimate] Should return parent base fee estimate', async () => { + const parentBaseFeeEstimate = await client.getParentBaseFeeEstimate(); + expect(parentBaseFeeEstimate).toMatchSnapshot(); + }); + + it('[getParentRewardRate] Should return parent reward rate', async () => { + const parentRewardRate = await client.getParentRewardRate(); + expect(parentRewardRate).toMatchSnapshot(); + }); + + it('[getParentRewardRecipient] Should return parent reward recipient', async () => { + const parentRewardRecipient = await client.getParentRewardRecipient(); + expect(parentRewardRecipient).toMatchSnapshot(); + }); +}); From 3c5a9297ffb7d5c7cabf1b600c819c3d28fe2393 Mon Sep 17 00:00:00 2001 From: Christophe Date: Mon, 1 Jul 2024 12:44:58 +0000 Subject: [PATCH 52/54] Update getParentBaseFeeEstimate unit test --- .../__snapshots__/publicActionsChildChain.unit.test.ts.snap | 2 -- src/decorators/publicActionsChildChain.unit.test.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap b/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap index 7dc5520d..56398936 100644 --- a/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap +++ b/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap @@ -16,8 +16,6 @@ exports[`Getters > [getMinimumGasPrice] Should return minimum gas price 1`] = `1 exports[`Getters > [getNetworkFeeAccount] Should return network fee account 1`] = `"0x32e7AF5A8151934F3787d0cD59EB6EDd0a736b1d"`; -exports[`Getters > [getParentBaseFeeEstimate] Should return parent base fee estimate 1`] = `106354669n`; - exports[`Getters > [getParentRewardRate] Should return parent reward rate 1`] = `0n`; exports[`Getters > [getParentRewardRecipient] Should return parent reward recipient 1`] = `"0x2E041280627800801E90E9Ac83532fadb6cAd99A"`; diff --git a/src/decorators/publicActionsChildChain.unit.test.ts b/src/decorators/publicActionsChildChain.unit.test.ts index 94bb86c0..08166f26 100644 --- a/src/decorators/publicActionsChildChain.unit.test.ts +++ b/src/decorators/publicActionsChildChain.unit.test.ts @@ -57,7 +57,7 @@ describe('Getters', () => { it('[getParentBaseFeeEstimate] Should return parent base fee estimate', async () => { const parentBaseFeeEstimate = await client.getParentBaseFeeEstimate(); - expect(parentBaseFeeEstimate).toMatchSnapshot(); + expect(parentBaseFeeEstimate).toBeGreaterThan(0n); }); it('[getParentRewardRate] Should return parent reward rate', async () => { From a326949e37df07b9a6ec0dca65d86ca1ba0a50fb Mon Sep 17 00:00:00 2001 From: Christophe Date: Thu, 27 Jun 2024 19:19:38 +0000 Subject: [PATCH 53/54] Feat: Add v1 publicActions for parent chain Closes FS-535 --- src/decorators/publicActionsParentChain.ts | 161 ++++++++++++++++++ .../publicActionsParentChain.unit.test.ts | 45 +++++ 2 files changed, 206 insertions(+) create mode 100644 src/decorators/publicActionsParentChain.ts create mode 100644 src/decorators/publicActionsParentChain.unit.test.ts diff --git a/src/decorators/publicActionsParentChain.ts b/src/decorators/publicActionsParentChain.ts new file mode 100644 index 00000000..b4995147 --- /dev/null +++ b/src/decorators/publicActionsParentChain.ts @@ -0,0 +1,161 @@ +import { Address, Chain, PublicClient, Transport } from 'viem'; + +// Getters +import { + getMaxTimeVariation, + GetMaxTimeVariationParameters, + GetMaxTimeVariationReturnType, +} from '../actions/getMaxTimeVariation'; +import { + isBatchPoster, + IsBatchPosterParameters, + IsBatchPosterReturnType, +} from '../actions/isBatchPoster'; +import { + isValidKeysetHash, + IsValidKeysetHashParameters, + IsValidKeysetHashReturnType, +} from '../actions/isValidKeysetHash'; +// Setters +import { + invalidateKeysetHash, + InvalidateKeysetHashParameters, + InvalidateKeysetHashReturnType, +} from '../actions/invalidateKeysetHash'; +import { + enableBatchPoster, + disableBatchPoster, + SetIsBatchPosterParameters, + SetIsBatchPosterReturnType, +} from '../actions/setIsbatchPoster'; +import { setKeyset, SetKeysetParameters, SetKeysetReturnType } from '../actions/setKeyset'; +import { + setMaxTimeVariation, + SetMaxTimeVariationParameters, + SetMaxTimeVariationReturnType, +} from '../actions/setMaxTimeVariation'; + +type Params = { sequencerInbox: Address } | void; + +export type PublicActionsParentChain = { + // Getters + getMaxTimeVariation: ( + parameters: GetMaxTimeVariationParameters, + ) => Promise; + isBatchPoster: (parameters: IsBatchPosterParameters) => Promise; + isValidKeysetHash: ( + parameters: IsValidKeysetHashParameters, + ) => Promise; + // Setters + invalidateKeysetHash: ( + parameters: InvalidateKeysetHashParameters, + ) => Promise; + enableBatchPoster: ( + parameters: SetIsBatchPosterParameters, + ) => Promise; + disableBatchPoster: ( + parameters: SetIsBatchPosterParameters, + ) => Promise; + setKeyset: (parameters: SetKeysetParameters) => Promise; + setMaxTimeVariation: ( + parameters: SetMaxTimeVariationParameters, + ) => Promise; +}; + +/** + * Simplifies the overall typing with curried sequencerInbox address + * + * By design, sequencerInbox is either passed initially from the decorator, or on each call + * + * Address passed through each call has the priority over the address passed to the decorator, for override + */ + +function getSequencerInboxAddress( + params: Params, + args: { sequencerInbox?: Address } | void, +): Address { + return ((args && args.sequencerInbox) ?? (params && params.sequencerInbox)) as unknown as Address; +} + +/** + * Public actions for parent chain + * + * @example + * import { createPublicClient, http } from 'viem' + * import { publicActionsParentChain } from '@arbitrum/orbit-sdk' + * import { arbitrum } from 'viem/chains' + * + * export const publicClientParentChain = createPublicClient({ + * chain: arbitrum, + * transport: http(), + * }).extend(publicActionsParentChain({ + * sequencerInbox: '0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6' + * })) + * + * const { delayBlocks, futureBlocks, delaySeconds, futureSeconds } = await publicClientParentChain.getMaxTimeVariation() + */ +export function publicActionsParentChain< + TParams extends Params = void, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined, +>(params: void): (client: PublicClient) => PublicActionsParentChain; +export function publicActionsParentChain< + TParams extends Params = { sequencerInbox: Address }, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined, +>(params: TParams): (client: PublicClient) => PublicActionsParentChain; +export function publicActionsParentChain< + TParams extends Params, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined, +>(params: TParams) { + return (client: PublicClient) => { + // sequencerInbox is curried, sequencerInbox param is optional. + return { + // Getters + getMaxTimeVariation: (args) => + getMaxTimeVariation(client, { + ...args, + sequencerInbox: getSequencerInboxAddress(params, args), + }), + isBatchPoster: (args) => + isBatchPoster(client, { + ...args, + sequencerInbox: getSequencerInboxAddress(params, args), + }), + isValidKeysetHash: (args) => + isValidKeysetHash(client, { + ...args, + sequencerInbox: getSequencerInboxAddress(params, args), + }), + // Setters + invalidateKeysetHash: (args) => + invalidateKeysetHash(client, { + ...args, + sequencerInbox: getSequencerInboxAddress(params, args), + }), + enableBatchPoster: (args) => + enableBatchPoster(client, { + ...args, + sequencerInbox: getSequencerInboxAddress(params, args), + }), + disableBatchPoster: (args) => + disableBatchPoster(client, { + ...args, + sequencerInbox: getSequencerInboxAddress(params, args), + }), + setKeyset: (args) => + setKeyset(client, { + ...args, + sequencerInbox: getSequencerInboxAddress(params, args), + }), + setMaxTimeVariation: (args) => + setMaxTimeVariation(client, { + ...args, + sequencerInbox: getSequencerInboxAddress(params, args), + }), + } satisfies PublicActionsParentChain< + TParams extends { sequencerInbox: Address } ? true : false + >; + }; +} diff --git a/src/decorators/publicActionsParentChain.unit.test.ts b/src/decorators/publicActionsParentChain.unit.test.ts new file mode 100644 index 00000000..d65bfcfd --- /dev/null +++ b/src/decorators/publicActionsParentChain.unit.test.ts @@ -0,0 +1,45 @@ +import { it, expect, describe } from 'vitest'; + +import { createPublicClient, http, padHex, zeroAddress } from 'viem'; +import { mainnet } from '../chains'; +import { publicActionsParentChain } from './publicActionsParentChain'; + +const arbOneSequencerInbox = '0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6'; + +const client = createPublicClient({ + chain: mainnet, + transport: http(), +}).extend(publicActionsParentChain({ sequencerInbox: arbOneSequencerInbox })); + +describe('Getters', () => { + it('[maxTimeVariation] Should return max time variation', async () => { + const maxTimeVariation = await client.getMaxTimeVariation(); + expect(maxTimeVariation).toEqual({ + delayBlocks: 5760n, + futureBlocks: 64n, + delaySeconds: 86400n, + futureSeconds: 768n, + }); + }); + + it('[isBatchPoster] Should return if an address is a batch poster', async () => { + const isZeroAddressBatchPoster = await client.isBatchPoster({ + batchPoster: zeroAddress, + }); + expect(isZeroAddressBatchPoster).toBeFalsy(); + }); + + it('[isValidKeysetHash] Should return if a keysetHash is a valid one', async () => { + const isEmptyHashValidKeysetHash = await client.isValidKeysetHash({ + keysetHash: padHex('0x'), + }); + expect(isEmptyHashValidKeysetHash).toBeFalsy(); + + // Test on Nova + const isAValidKeysetHashOnNova = await client.isValidKeysetHash({ + keysetHash: '0x01191accc7ad5a8020e6c6d122984540e9fc48d0457bda63e0a32c8c31994f4a', + sequencerInbox: '0x211e1c4c7f1bf5351ac850ed10fd68cffcf6c21b', + }); + expect(isAValidKeysetHashOnNova).toBeTruthy(); + }); +}); From ef6ab80a101685b8bdb7d6a3e08a23499084610f Mon Sep 17 00:00:00 2001 From: Christophe Date: Wed, 10 Jul 2024 13:42:54 +0000 Subject: [PATCH 54/54] Change chains for unit test --- .../publicActionsParentChain.unit.test.ts | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/decorators/publicActionsParentChain.unit.test.ts b/src/decorators/publicActionsParentChain.unit.test.ts index d65bfcfd..3c5a235a 100644 --- a/src/decorators/publicActionsParentChain.unit.test.ts +++ b/src/decorators/publicActionsParentChain.unit.test.ts @@ -1,19 +1,25 @@ import { it, expect, describe } from 'vitest'; import { createPublicClient, http, padHex, zeroAddress } from 'viem'; -import { mainnet } from '../chains'; +import { sepolia } from '../chains'; import { publicActionsParentChain } from './publicActionsParentChain'; +import { arbitrum } from 'viem/chains'; -const arbOneSequencerInbox = '0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6'; - -const client = createPublicClient({ - chain: mainnet, +const arbSepoliaSequencerInbox = '0x6c97864CE4bEf387dE0b3310A44230f7E3F1be0D'; +const sepoliaClient = createPublicClient({ + chain: sepolia, + transport: http(), +}).extend(publicActionsParentChain({ sequencerInbox: arbSepoliaSequencerInbox })); +const arbitrumClient = createPublicClient({ + chain: arbitrum, transport: http(), -}).extend(publicActionsParentChain({ sequencerInbox: arbOneSequencerInbox })); +}).extend( + publicActionsParentChain({ sequencerInbox: '0x995a9d3ca121D48d21087eDE20bc8acb2398c8B1' }), +); describe('Getters', () => { it('[maxTimeVariation] Should return max time variation', async () => { - const maxTimeVariation = await client.getMaxTimeVariation(); + const maxTimeVariation = await sepoliaClient.getMaxTimeVariation(); expect(maxTimeVariation).toEqual({ delayBlocks: 5760n, futureBlocks: 64n, @@ -23,23 +29,28 @@ describe('Getters', () => { }); it('[isBatchPoster] Should return if an address is a batch poster', async () => { - const isZeroAddressBatchPoster = await client.isBatchPoster({ + const isZeroAddressBatchPoster = await arbitrumClient.isBatchPoster({ batchPoster: zeroAddress, }); expect(isZeroAddressBatchPoster).toBeFalsy(); + + const isBatchPosterOnXai = await arbitrumClient.isBatchPoster({ + batchPoster: '0x7F68dba68E72a250004812fe04F1123Fca89aBa9', + }); + expect(isBatchPosterOnXai).toBeTruthy(); }); it('[isValidKeysetHash] Should return if a keysetHash is a valid one', async () => { - const isEmptyHashValidKeysetHash = await client.isValidKeysetHash({ + const isEmptyHashValidKeysetHash = await arbitrumClient.isValidKeysetHash({ keysetHash: padHex('0x'), }); expect(isEmptyHashValidKeysetHash).toBeFalsy(); - // Test on Nova - const isAValidKeysetHashOnNova = await client.isValidKeysetHash({ - keysetHash: '0x01191accc7ad5a8020e6c6d122984540e9fc48d0457bda63e0a32c8c31994f4a', - sequencerInbox: '0x211e1c4c7f1bf5351ac850ed10fd68cffcf6c21b', + // Test on ProofOfPlay + const isAValidKeysetHashOnPoP = await arbitrumClient.isValidKeysetHash({ + keysetHash: '0xc2c008db9d0d25ca30d60080f5ebd3d114dbccd95f2bd2df05446eae6b1acadf', + sequencerInbox: '0xa58F38102579dAE7C584850780dDA55744f67DF1', }); - expect(isAValidKeysetHashOnNova).toBeTruthy(); + expect(isAValidKeysetHashOnPoP).toBeTruthy(); }); });