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 e8ab29f6..d6e08261 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,30 +61,18 @@ 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 + 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: release + args: --tokenbridge --l3node --l3-token-bridge --l3-fee-token - name: Copy .env run: cp ./.env.example ./.env 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 diff --git a/audit-ci.jsonc b/audit-ci.jsonc index bf718810..6925ec78 100644 --- a/audit-ci.jsonc +++ b/audit-ci.jsonc @@ -65,11 +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" + "GHSA-9vx6-7xxf-x967" ] } 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/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-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..f8ad21e3 --- /dev/null +++ b/examples/setup-fast-withdrawal/index.ts @@ -0,0 +1,321 @@ +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(''); + + // 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 + // + 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.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.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}`); + 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/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/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/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/__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/__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/__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/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/abi/rollupAdminLogicABI.ts b/src/abi/rollupAdminLogicABI.ts deleted file mode 100644 index 393b2e7b..00000000 --- a/src/abi/rollupAdminLogicABI.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 rollupAdminLogicABI = [ - { - 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/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/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/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..a4bbe4c3 --- /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; + +export 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/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/getConfirmPeriodBlocks.ts b/src/actions/getConfirmPeriodBlocks.ts new file mode 100644 index 00000000..120db86a --- /dev/null +++ b/src/actions/getConfirmPeriodBlocks.ts @@ -0,0 +1,27 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithContractAddress } from '../types/Actions'; +import { getRollupAddress } from '../getRollupAddress'; + +export type GetConfirmPeriodBlocksParameters = WithContractAddress< + {}, + 'rollupAdminLogic', + Curried +>; + +export type GetConfirmPeriodBlocksReturnType = ReadContractReturnType< + typeof rollupAdminLogic.abi, + 'confirmPeriodBlocks' +>; + +export async function getConfirmPeriodBlocks( + client: PublicClient, + args: GetConfirmPeriodBlocksParameters, +): Promise { + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.readContract({ + abi: rollupAdminLogic.abi, + functionName: 'confirmPeriodBlocks', + address: rollupAdminLogicAddresss, + }); +} diff --git a/src/actions/getExtraChallengeTimeBlocks.ts b/src/actions/getExtraChallengeTimeBlocks.ts new file mode 100644 index 00000000..0bce1c4f --- /dev/null +++ b/src/actions/getExtraChallengeTimeBlocks.ts @@ -0,0 +1,24 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithContractAddress } from '../types/Actions'; +import { getRollupAddress } from '../getRollupAddress'; + +export type GetExtraChallengeTimeBlocksParameters = + WithContractAddress<{}, 'rollupAdminLogic', Curried>; + +export type GetExtraChallengeTimeBlocksReturnType = ReadContractReturnType< + typeof rollupAdminLogic.abi, + 'extraChallengeTimeBlocks' +>; + +export async function getExtraChallengeTimeBlocks( + client: PublicClient, + args: GetExtraChallengeTimeBlocksParameters, +): Promise { + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.readContract({ + abi: rollupAdminLogic.abi, + functionName: 'extraChallengeTimeBlocks', + address: rollupAdminLogicAddresss, + }); +} 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/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/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/getMinimumAssertionPeriod.ts b/src/actions/getMinimumAssertionPeriod.ts new file mode 100644 index 00000000..0ff81960 --- /dev/null +++ b/src/actions/getMinimumAssertionPeriod.ts @@ -0,0 +1,24 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithContractAddress } from '../types/Actions'; +import { getRollupAddress } from '../getRollupAddress'; + +export type GetMinimumAssertionPeriodParameters = + WithContractAddress<{}, 'rollupAdminLogic', Curried>; + +export type GetMinimumAssertionPeriodReturnType = ReadContractReturnType< + typeof rollupAdminLogic.abi, + 'minimumAssertionPeriod' +>; + +export async function getMinimumAssertionPeriod( + client: PublicClient, + args: GetMinimumAssertionPeriodParameters, +): Promise { + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.readContract({ + abi: rollupAdminLogic.abi, + functionName: 'minimumAssertionPeriod', + address: rollupAdminLogicAddresss, + }); +} 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/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/getParentBaseFeeEstimate.ts b/src/actions/getParentBaseFeeEstimate.ts new file mode 100644 index 00000000..704e6b9e --- /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, + }); +} 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/getWasmModuleRoot.ts b/src/actions/getWasmModuleRoot.ts new file mode 100644 index 00000000..8798b32d --- /dev/null +++ b/src/actions/getWasmModuleRoot.ts @@ -0,0 +1,27 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithContractAddress } from '../types/Actions'; +import { getRollupAddress } from '../getRollupAddress'; + +export type GetWasmModuleRootParameters = WithContractAddress< + {}, + 'rollupAdminLogic', + Curried +>; + +export type GetWasmModuleRootReturnType = ReadContractReturnType< + typeof rollupAdminLogic.abi, + 'wasmModuleRoot' +>; + +export async function getWasmModuleRoot( + client: PublicClient, + args: GetWasmModuleRootParameters, +): Promise { + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.readContract({ + abi: rollupAdminLogic.abi, + functionName: 'wasmModuleRoot', + address: rollupAdminLogicAddresss, + }); +} 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], + }); +} diff --git a/src/actions/index.ts b/src/actions/index.ts new file mode 100644 index 00000000..28c51440 --- /dev/null +++ b/src/actions/index.ts @@ -0,0 +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/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/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/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], + }); +} 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/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/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); +} diff --git a/src/actions/setConfirmPeriodBlocks.ts b/src/actions/setConfirmPeriodBlocks.ts new file mode 100644 index 00000000..47b951a5 --- /dev/null +++ b/src/actions/setConfirmPeriodBlocks.ts @@ -0,0 +1,41 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithAccount, WithContractAddress } from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; + +export type SetConfirmPeriodBlocksParameters = Prettify< + WithAccount> +>; + +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); + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.prepareTransactionRequest({ + to: rollupAdminLogicAddresss, + 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..4f35ce27 --- /dev/null +++ b/src/actions/setExtraChallengeTimeBlocks.ts @@ -0,0 +1,43 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithAccount, WithContractAddress } from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; + +export type SetExtraChallengeTimeBlocksParameters = Prettify< + WithAccount> +>; + +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); + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.prepareTransactionRequest({ + to: rollupAdminLogicAddresss, + 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); +} diff --git a/src/actions/setMaxTxGasLimit.ts b/src/actions/setMaxTxGasLimit.ts new file mode 100644 index 00000000..d388c9d4 --- /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 setMaxTxGasLimit( + 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/setMinimumAssertionPeriod.ts b/src/actions/setMinimumAssertionPeriod.ts new file mode 100644 index 00000000..051b7bc4 --- /dev/null +++ b/src/actions/setMinimumAssertionPeriod.ts @@ -0,0 +1,41 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithAccount, WithContractAddress } from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; + +export type SetMinimumAssertionPeriodParameters = Prettify< + WithAccount> +>; + +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); + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.prepareTransactionRequest({ + to: rollupAdminLogicAddresss, + 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); +} diff --git a/src/actions/setValidator.ts b/src/actions/setValidator.ts new file mode 100644 index 00000000..1163e68b --- /dev/null +++ b/src/actions/setValidator.ts @@ -0,0 +1,53 @@ +import { + Address, + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithAccount, WithContractAddress } from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; + +export type SetIsValidatorParameters = Prettify< + WithAccount< + WithContractAddress< + { + add: Address[]; + remove: Address[]; + }, + 'rollupAdminLogic', + Curried + > + > +>; + +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); + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.prepareTransactionRequest({ + to: rollupAdminLogicAddresss, + 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..a6ecd8eb --- /dev/null +++ b/src/actions/setValidatorWhitelistDisabled.ts @@ -0,0 +1,63 @@ +import { + Chain, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithAccount, WithContractAddress } from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; + +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); + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.prepareTransactionRequest({ + to: rollupAdminLogicAddresss, + 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..d9be7561 --- /dev/null +++ b/src/actions/setWasmModuleRoot.ts @@ -0,0 +1,50 @@ +import { + Chain, + Hex, + PrepareTransactionRequestParameters, + PrepareTransactionRequestReturnType, + PublicClient, + Transport, + encodeFunctionData, +} from 'viem'; +import { rollupAdminLogic } from '../contracts'; +import { WithAccount, WithContractAddress } from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { getRollupAddress } from '../getRollupAddress'; + +export type SetWasmModuleRootParameters = Prettify< + WithAccount< + WithContractAddress< + { + 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); + const rollupAdminLogicAddresss = await getRollupAddress(client, args); + return client.prepareTransactionRequest({ + to: rollupAdminLogicAddresss, + value: BigInt(0), + chain: client.chain, + data, + account: args.account, + } satisfies PrepareTransactionRequestParameters); +} 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/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/contracts.ts b/src/contracts.ts deleted file mode 100644 index 79f9217a..00000000 --- a/src/contracts.ts +++ /dev/null @@ -1,213 +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 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)', - ]), -}; - -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, -}; - -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/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/RollupCreator/index.ts b/src/contracts/RollupCreator/index.ts new file mode 100644 index 00000000..65e52bda --- /dev/null +++ b/src/contracts/RollupCreator/index.ts @@ -0,0 +1,2 @@ +// export the latest version +export * from './v2.1'; diff --git a/src/contracts/RollupCreator/v1.1.ts b/src/contracts/RollupCreator/v1.1.ts new file mode 100644 index 00000000..51b71531 --- /dev/null +++ b/src/contracts/RollupCreator/v1.1.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/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/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/abi/sequencerInboxABI.ts b/src/contracts/SequencerInbox/v1.1.ts similarity index 100% rename from src/abi/sequencerInboxABI.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/contracts/TokenBridgeCreator/index.ts b/src/contracts/TokenBridgeCreator/index.ts new file mode 100644 index 00000000..94a27615 --- /dev/null +++ b/src/contracts/TokenBridgeCreator/index.ts @@ -0,0 +1,2 @@ +// export the latest version +export * from './v1.2'; diff --git a/src/contracts/TokenBridgeCreator/v1.2.ts b/src/contracts/TokenBridgeCreator/v1.2.ts new file mode 100644 index 00000000..91340622 --- /dev/null +++ b/src/contracts/TokenBridgeCreator/v1.2.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: '0x4Af567288e68caD4aA93A272fe6139Ca53859C70', + 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/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/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/createRollupPrepareDeploymentParamsConfigDefaults.ts b/src/createRollupPrepareDeploymentParamsConfigDefaults.ts index e1b52eca..081ccc40 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 { getConsensusReleaseByVersion } from './wasmModuleRoot'; export const defaults = { extraChallengeTimeBlocks: BigInt(0), stakeToken: zeroAddress, baseStake: parseEther(String(0.1)), - wasmModuleRoot, + wasmModuleRoot: getConsensusReleaseByVersion(31).wasmModuleRoot, loserStakeEscrow: zeroAddress, genesisBlockNum: BigInt(0), } as const; diff --git a/src/createRollupPrepareTransaction.ts b/src/createRollupPrepareTransaction.ts index 2b943bb1..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 { rollupCreator } from './contracts'; -import { CreateRollupFunctionInputs } from './types/createRollupTypes'; +import { rollupCreatorABI } from './contracts/RollupCreator'; +import { rollupCreatorABI as rollupCreatorV1Dot1ABI } from './contracts/RollupCreator/v1.1'; -function createRollupDecodeFunctionData(data: `0x${string}`) { - return decodeFunctionData({ - abi: rollupCreator.abi, - 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/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..76eee497 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, }); @@ -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, @@ -196,7 +224,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); }); @@ -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/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/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, }), ) 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 - ethersTransactionReceiptToViemTransactionReceipt(result.txReceipt), + ethersTransactionReceiptToViemTransactionReceipt(result.childTxReceipt), ) as WaitForRetryablesResult ); }, diff --git a/src/createTokenBridgePrepareTransactionReceipt.ts b/src/createTokenBridgePrepareTransactionReceipt.ts index dcd5f06a..ecc61515 100644 --- a/src/createTokenBridgePrepareTransactionReceipt.ts +++ b/src/createTokenBridgePrepareTransactionReceipt.ts @@ -18,11 +18,11 @@ import { publicClientToProvider } from './ethers-compat/publicClientToProvider'; import { viemTransactionReceiptToEthersTransactionReceipt } from './ethers-compat/viemTransactionReceiptToEthersTransactionReceipt'; import { ethersTransactionReceiptToViemTransactionReceipt } from './ethers-compat/ethersTransactionReceiptToViemTransactionReceipt'; import { TokenBridgeContracts } from './types/TokenBridgeContracts'; -import { tokenBridgeCreator } from './contracts'; +import { tokenBridgeCreatorABI } from './contracts/TokenBridgeCreator'; import { createTokenBridgeFetchTokenBridgeContracts } from './createTokenBridgeFetchTokenBridgeContracts'; function findOrbitTokenBridgeCreatedEventLog(txReceipt: TransactionReceipt) { - const abiItem = getAbiItem({ abi: tokenBridgeCreator.abi, name: 'OrbitTokenBridgeCreated' }); + const abiItem = getAbiItem({ abi: tokenBridgeCreatorABI, name: 'OrbitTokenBridgeCreated' }); const eventSelector = getEventSelector(abiItem); const log = txReceipt.logs.find((log) => 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( @@ -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/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/__snapshots__/publicActionsChildChain.unit.test.ts.snap b/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap new file mode 100644 index 00000000..56398936 --- /dev/null +++ b/src/decorators/__snapshots__/publicActionsChildChain.unit.test.ts.snap @@ -0,0 +1,28 @@ +// 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 > [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..08166f26 --- /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).toBeGreaterThan(0n); + }); + + 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(); + }); +}); 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..3c5a235a --- /dev/null +++ b/src/decorators/publicActionsParentChain.unit.test.ts @@ -0,0 +1,56 @@ +import { it, expect, describe } from 'vitest'; + +import { createPublicClient, http, padHex, zeroAddress } from 'viem'; +import { sepolia } from '../chains'; +import { publicActionsParentChain } from './publicActionsParentChain'; +import { arbitrum } from 'viem/chains'; + +const arbSepoliaSequencerInbox = '0x6c97864CE4bEf387dE0b3310A44230f7E3F1be0D'; +const sepoliaClient = createPublicClient({ + chain: sepolia, + transport: http(), +}).extend(publicActionsParentChain({ sequencerInbox: arbSepoliaSequencerInbox })); +const arbitrumClient = createPublicClient({ + chain: arbitrum, + transport: http(), +}).extend( + publicActionsParentChain({ sequencerInbox: '0x995a9d3ca121D48d21087eDE20bc8acb2398c8B1' }), +); + +describe('Getters', () => { + it('[maxTimeVariation] Should return max time variation', async () => { + const maxTimeVariation = await sepoliaClient.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 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 arbitrumClient.isValidKeysetHash({ + keysetHash: padHex('0x'), + }); + expect(isEmptyHashValidKeysetHash).toBeFalsy(); + + // Test on ProofOfPlay + const isAValidKeysetHashOnPoP = await arbitrumClient.isValidKeysetHash({ + keysetHash: '0xc2c008db9d0d25ca30d60080f5ebd3d114dbccd95f2bd2df05446eae6b1acadf', + sequencerInbox: '0xa58F38102579dAE7C584850780dDA55744f67DF1', + }); + expect(isAValidKeysetHashOnPoP).toBeTruthy(); + }); +}); diff --git a/src/decorators/sequencerInboxActions.integration.test.ts b/src/decorators/sequencerInboxActions.integration.test.ts index e68317fe..8c02744c 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(); @@ -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/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/generated.ts b/src/generated.ts deleted file mode 100644 index 95e9c6cf..00000000 --- a/src/generated.ts +++ /dev/null @@ -1,1059 +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: '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: 'previousAdmin', internalType: 'address', type: 'address', indexed: false }, - { name: 'newAdmin', internalType: 'address', type: 'address', indexed: false }, - ], - name: 'AdminChanged', - }, - { - type: 'event', - anonymous: false, - inputs: [{ name: 'beacon', internalType: 'address', type: 'address', indexed: true }], - name: 'BeaconUpgraded', - }, - { - type: 'event', - anonymous: false, - inputs: [{ name: 'implementation', internalType: 'address', type: 'address', indexed: true }], - name: 'Upgraded', - }, - { stateMutability: 'payable', type: 'fallback' }, - { stateMutability: 'payable', type: 'receive' }, -] 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..5b7fa744 100644 --- a/src/getBatchPosters.ts +++ b/src/getBatchPosters.ts @@ -8,20 +8,28 @@ import { getAbiItem, getFunctionSelector, } from 'viem'; -import { rollupCreator, upgradeExecutor } from './contracts'; -import { safeL2ABI, sequencerInboxABI } from './abi'; + +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'; + import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; -const createRollupABI = getAbiItem({ abi: rollupCreator.abi, name: 'createRollup' }); +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); -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({ @@ -30,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, @@ -138,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 1dd965bf..186c6255 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'; @@ -18,6 +21,11 @@ const client = createPublicClient({ transport: http(), }); +const arbitrumSepoliaClient = createPublicClient({ + chain: arbitrumSepolia, + transport: http(), +}); + function mockLog(transactionHash: string) { return { address: '0x193e2887031c148ab54f5e856ea51ae521661200', @@ -123,7 +131,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, @@ -149,6 +157,35 @@ 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/0x77db43157182a69ce0e6d2a0564d2dabb43b306d48ea7b4d877160d6a1c9b66d +it('getBatchPosters returns batch posters for a chain created with RollupCreator v2.1', async () => { + const { isAccurate, batchPosters } = await getBatchPosters(arbitrumSepoliaClient, { + rollup: '0x66d0e72952f4f69aF9D33C1B7C31Fa9aCDbCAF63', + sequencerInbox: '0x43528b8Be52e8D084F147d167487f361553463b5', + }); + expect(batchPosters).toEqual([ + '0x9464aD09CE0d157Efc6c7EefE577C5AA6dEc804D', + '0xC02386B2D10a37e71145B6A7f5569e1db4604213', + '0x6C4483f6DCEDb5a758b28D28E11F805bdACFE245', + '0xf89836dc33f58394fB34B3e690D3829A65C74286', + '0xd1d25Aeb44E99B35E2d5E7Db961c73ec94f92a24', + '0xDc4ECA04032b9178020Ff0c6154A7e87309a429f', + '0xe122F9838A4C8e6834F24D1b9dCa92eb52a8E17e', + '0xB280Fd59090f3D95588d94BACD22b336dE2278e0', + ]); + 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/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/getRollupAddress.ts b/src/getRollupAddress.ts new file mode 100644 index 00000000..8adf7a7e --- /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[`${publicClient.chain?.id}_${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[`${publicClient.chain?.id}_${params.sequencerInbox}`] = rollupAddress; + return rollupAddress; +} diff --git a/src/getValidators.ts b/src/getValidators.ts index 24fbae37..36237c74 100644 --- a/src/getValidators.ts +++ b/src/getValidators.ts @@ -8,29 +8,37 @@ import { getAbiItem, getFunctionSelector, } from 'viem'; -import { rollupCreator, upgradeExecutor } from './contracts'; -import { rollupAdminLogicABI, safeL2ABI } from './abi'; + +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'; + 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 createRollupV1Dot1ABI = getAbiItem({ abi: rollupCreatorV1Dot1ABI, name: 'createRollup' }); +const createRollupV1Dot1FunctionSelector = getFunctionSelector(createRollupV1Dot1ABI); + +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)[], + TAbi extends + | (typeof createRollupABI)[] + | (typeof createRollupV1Dot1ABI)[] + | (typeof setValidatorABI)[], >({ abi, data }: { abi: TAbi; data: Hex }) { const { args } = decodeFunctionData({ abi, @@ -139,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 18186056..f909dcbd 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({ @@ -18,6 +21,11 @@ const client = createPublicClient({ transport: http(), }); +const arbitrumSepoliaClient = createPublicClient({ + chain: arbitrumSepolia, + transport: http(), +}); + function mockLog(transactionHash: string) { return { address: '0x193e2887031c148ab54f5e856ea51ae521661200', @@ -104,7 +112,7 @@ const rollupAddress = '0xe0875cbd144fe66c015a95e5b2d2c15c3b612179'; function setValidatorHelper(args: [Address[], boolean[]]) { return encodeFunctionData({ - abi: rollupAdminLogicABI, + abi: rollupABI, functionName: 'setValidator', args, }); @@ -114,14 +122,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, @@ -146,6 +154,29 @@ 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/0x77db43157182a69ce0e6d2a0564d2dabb43b306d48ea7b4d877160d6a1c9b66d +it('getValidators returns validators for a chain created with RollupCreator v2.1', async () => { + const { isAccurate, validators } = await getValidators(arbitrumSepoliaClient, { + rollup: '0x66d0e72952f4f69aF9D33C1B7C31Fa9aCDbCAF63', + }); + expect(validators).toEqual([ + '0xDBb2c9923b5DE18B151bC55Ed571EDcd1fC7EeB9', + '0x84B2EFFDd54aA5dce861440Ae9B9D320b043a64c', + '0x39B4Ce32E557225a401917a701ac4d267648635a', + '0xe2D0cC872647B1A129B942BbFC980B31E8e94Df2', + ]); + expect(isAccurate).toBeTruthy(); +}); + describe('createRollupFunctionSelector', () => { it('getValidators return all validators with isAccurate flag set to true', async () => { const mockTransport = () => diff --git a/src/index.ts b/src/index.ts index 26d85b2e..5cbd3c94 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,13 @@ -import { - createRollupPrepareConfig, - CreateRollupPrepareConfigParams, - CreateRollupPrepareConfigResult, -} from './createRollupPrepareConfig'; import { createRollupPrepareDeploymentParamsConfig, CreateRollupPrepareDeploymentParamsConfigParams, CreateRollupPrepareDeploymentParamsConfigResult, } from './createRollupPrepareDeploymentParamsConfig'; -import { prepareChainConfig, PrepareChainConfigParams } from './prepareChainConfig'; +import { + prepareChainConfig, + PrepareChainConfigParams, + PrepareChainConfigArbitrumParams, +} from './prepareChainConfig'; import { createRollupEnoughCustomFeeTokenAllowance, CreateRollupEnoughCustomFeeTokenAllowanceParams, @@ -17,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, @@ -93,6 +98,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 +121,29 @@ import { } from './getBatchPosters'; import { getKeysets, GetKeysetsParams, GetKeysetsReturnType } from './getKeysets'; import { isAnyTrust } from './isAnyTrust'; +import { parentChainIsArbitrum } from './parentChainIsArbitrum'; +import { + createSafePrepareTransactionRequest, + CreateSafePrepareTransactionRequestParams, +} from './createSafePrepareTransactionRequest'; +import { + createSafePrepareTransactionReceipt, + CreateSafeTransactionReceipt, +} from './createSafePrepareTransactionReceipt'; +import { + setAnyTrustFastConfirmerPrepareTransactionRequest, + SetAnyTrustFastConfirmerPrepareTransactionRequestParams, +} from './setAnyTrustFastConfirmerPrepareTransactionRequest'; +import { + ConsensusVersion, + getConsensusReleaseByVersion, + GetConsensusReleaseByVersion, + WasmModuleRoot, + isKnownWasmModuleRoot, + getConsensusReleaseByWasmModuleRoot, + GetConsensusReleaseByWasmModuleRoot, +} from './wasmModuleRoot'; +export * from './actions'; export { arbOwnerPublicActions, @@ -120,9 +156,9 @@ export { CreateRollupFunctionInputs, CreateRollupParams, // - createRollupPrepareConfig, - CreateRollupPrepareConfigParams, - CreateRollupPrepareConfigResult, + RollupCreatorVersion, + RollupCreatorLatestVersion, + RollupCreatorABI, // createRollupPrepareDeploymentParamsConfig, CreateRollupPrepareDeploymentParamsConfigParams, @@ -130,6 +166,8 @@ export { // prepareChainConfig, PrepareChainConfigParams, + PrepareChainConfigArbitrumParams, + // createRollupEnoughCustomFeeTokenAllowance, CreateRollupEnoughCustomFeeTokenAllowanceParams, createRollupPrepareCustomFeeTokenApprovalTransactionRequest, @@ -186,6 +224,11 @@ export { createTokenBridgePrepareSetWethGatewayTransactionRequest, createTokenBridgePrepareSetWethGatewayTransactionReceipt, // + feeRouterDeployChildToParentRewardRouter, + FeeRouterDeployChildToParentRewardRouterParams, + feeRouterDeployRewardDistributor, + FeeRouterDeployRewardDistributorParams, + // getDefaultConfirmPeriodBlocks, getDefaultSequencerInboxMaxTimeVariation, SequencerInboxMaxTimeVariation, @@ -203,4 +246,20 @@ export { GetKeysetsReturnType, // isAnyTrust, + parentChainIsArbitrum, + // + createSafePrepareTransactionRequest, + CreateSafePrepareTransactionRequestParams, + createSafePrepareTransactionReceipt, + CreateSafeTransactionReceipt, + setAnyTrustFastConfirmerPrepareTransactionRequest, + SetAnyTrustFastConfirmerPrepareTransactionRequestParams, + // + ConsensusVersion, + getConsensusReleaseByVersion, + GetConsensusReleaseByVersion, + WasmModuleRoot, + isKnownWasmModuleRoot, + getConsensusReleaseByWasmModuleRoot, + GetConsensusReleaseByWasmModuleRoot, }; diff --git a/src/isAnyTrust.ts b/src/isAnyTrust.ts index 24947371..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 { rollupCreator } from './contracts'; -const createRollupABI = getAbiItem({ abi: rollupCreator.abi, name: 'createRollup' }); +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/package.json b/src/package.json index 2d533ecd..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.17.0", + "version": "0.19.0-beta.0", "main": "./dist/index.js", "files": [ "./dist" @@ -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" @@ -26,6 +22,10 @@ "./constants": { "types": "./dist/constants.d.ts", "default": "./dist/constants.js" + }, + "./contracts/*": { + "types": "./dist/contracts/*", + "default": "./dist/contracts/*" } }, "typesVersions": { @@ -33,14 +33,14 @@ "chains": [ "./dist/chains.d.ts" ], - "contracts": [ - "./dist/contracts.d.ts" - ], "utils": [ "./dist/utils/index.d.ts" ], "constants": [ "./dist/constants.d.ts" + ], + "contracts/*": [ + "./dist/contracts/*" ] } }, @@ -51,8 +51,10 @@ "viem": "^1.20.0" }, "dependencies": { - "@arbitrum/sdk": "^4.0.0-alpha.4", - "@arbitrum/token-bridge-contracts": "^1.2.1", + "@arbitrum/sdk": "^4.0.0", + "@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/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/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/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/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/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/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/Actions.ts b/src/types/Actions.ts new file mode 100644 index 00000000..ba515953 --- /dev/null +++ b/src/types/Actions.ts @@ -0,0 +1,34 @@ +import { Address, PrepareTransactionRequestReturnType } 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; + } +>; + +export type WithAccount = Args & { + account: Address; +}; + +export type WithUpgradeExecutor = Args & { + upgradeExecutor: Address | false; +}; + +export type PrepareTransactionRequestReturnTypeWithChainId = PrepareTransactionRequestReturnType & { + chainId: number; +}; 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/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/types/createRollupTypes.ts b/src/types/createRollupTypes.ts index 966e6879..b71d8c8a 100644 --- a/src/types/createRollupTypes.ts +++ b/src/types/createRollupTypes.ts @@ -1,16 +1,42 @@ import { Address, GetFunctionArgs } from 'viem'; -import { rollupCreator } from '../contracts'; +import { rollupCreatorABI } from '../contracts/RollupCreator'; +import { rollupCreatorABI as rollupCreatorV1Dot1ABI } from '../contracts/RollupCreator/v1.1'; -export type CreateRollupFunctionInputs = GetFunctionArgs< - typeof rollupCreator.abi, - 'createRollup' ->['args']; +import { Prettify } from './utils'; -type RequiredKeys = 'config' | 'batchPoster' | '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 & { /** 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]; +}>; 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/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..3c72c7b5 --- /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.2 on Arbitrum Sepolia', async () => { + const implementation = await getImplementation({ + client: arbitrumSepoliaPublicClient, + address: '0x56C486D3786fA26cc61473C499A36Eb9CC1FbD8E', + }); + expect(implementation).toEqual('0x6b6e01852716f2d7dab6b8729bb50e67be68bf04'); +}); 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/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/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/src/wasmModuleRoot.ts b/src/wasmModuleRoot.ts new file mode 100644 index 00000000..a496dc0a --- /dev/null +++ b/src/wasmModuleRoot.ts @@ -0,0 +1,97 @@ +import { Hex } from 'viem'; + +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 GetConsensusReleaseByVersion = Extract< + ConsensusReleases[number], + { version: TConsensusVersion } +>; + +export function getConsensusReleaseByVersion( + consensusVersion: TConsensusVersion, +): GetConsensusReleaseByVersion { + const consensusRelease = consensusReleases + // + .find((release) => release.version === consensusVersion); + + return consensusRelease as GetConsensusReleaseByVersion; +} + +export type GetConsensusReleaseByWasmModuleRoot = Extract< + ConsensusReleases[number], + { wasmModuleRoot: TWasmModuleRoot } +>; + +export function getConsensusReleaseByWasmModuleRoot( + wasmModuleRoot: TWasmModuleRoot, +): GetConsensusReleaseByWasmModuleRoot { + const consensusRelease = consensusReleases + // + .find((release) => release.wasmModuleRoot === wasmModuleRoot); + + return consensusRelease as GetConsensusReleaseByWasmModuleRoot; +} + +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); + }); +}); 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/wagmi.config.ts b/wagmi.config.ts index cf910910..3ecd02e4 100644 --- a/wagmi.config.ts +++ b/wagmi.config.ts @@ -1,5 +1,6 @@ +import { Config } from '@wagmi/cli'; 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 +16,9 @@ import { nitroTestnodeL1, nitroTestnodeL2, nitroTestnodeL3, + chains, } from './src/chains'; +import { getImplementation } from './src/utils/getImplementation'; dotenv.config(); @@ -82,6 +85,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,12 +114,13 @@ type ContractConfig = { name: string; version?: string; address: Record | `0x${string}`; + implementation?: Record; }; const contracts: ContractConfig[] = [ { name: 'RollupCreator', - version: '1.1.0', + version: '1.1', address: { // mainnet L1 [mainnet.id]: '0x90d68b056c411015eae3ec0b98ad94e2c91419f1', @@ -123,9 +139,30 @@ 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.0', + version: '1.2', address: { // mainnet L1 [mainnet.id]: '0x60D9A46F24D5a35b95A78Dd3E793e55D94EE0660', @@ -140,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', }, }, { @@ -173,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) @@ -202,33 +239,60 @@ 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) { + // 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`); + 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; - return { - out: 'src/generated.ts', - plugins: [ - erc({ - 20: true, - 721: false, - 4626: false, - }), - etherscan({ - chainId: arbitrumSepolia.id, - apiKey: arbiscanApiKey, - contracts, - cacheDuration: 0, - }), - ], - }; + configs.push({ + out: `src/contracts/${filePath}.ts`, + plugins: [ + etherscan({ + chainId: arbitrumSepolia.id, + apiKey: arbiscanApiKey, + // todo: fix viem type issue + contracts: [contract], + cacheDuration: 0, + }), + ], + }); + } + + return configs; } diff --git a/yarn.lock b/yarn.lock index 5c0eec09..20c775ca 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" @@ -17,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" @@ -28,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" @@ -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" @@ -652,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" @@ -789,6 +808,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 +891,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" @@ -859,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" @@ -946,6 +1009,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 +1043,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" @@ -1140,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" @@ -1523,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" @@ -1706,7 +1779,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 +1826,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" @@ -1850,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" @@ -2477,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: @@ -3079,7 +3165,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 +3458,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" @@ -3647,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==