diff --git a/scripts/consts.ts b/scripts/consts.ts index ff322260..edfcedd6 100644 --- a/scripts/consts.ts +++ b/scripts/consts.ts @@ -5,3 +5,5 @@ export const tokenbridgedatapath = "/tokenbridge-data"; // Not secure. Do not use for production purposes export const l1mnemonic = "indoor dish desk flag debris potato excuse depart ticket judge file exit"; + +export const ARB_OWNER = "0x0000000000000000000000000000000000000070"; \ No newline at end of file diff --git a/scripts/ethcommands.ts b/scripts/ethcommands.ts index 1ba9768e..ac85ed69 100644 --- a/scripts/ethcommands.ts +++ b/scripts/ethcommands.ts @@ -3,8 +3,10 @@ import { BigNumber, ContractFactory, ethers, Wallet } from "ethers"; import * as consts from "./consts"; import { namedAccount, namedAddress } from "./accounts"; import * as L1GatewayRouter from "@arbitrum/token-bridge-contracts/build/contracts/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol/L1GatewayRouter.json"; +import * as L1AtomicTokenBridgeCreator from "@arbitrum/token-bridge-contracts/build/contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol/L1AtomicTokenBridgeCreator.json"; import * as ERC20 from "@openzeppelin/contracts/build/contracts/ERC20.json"; import * as fs from "fs"; +import { ARB_OWNER } from "./consts"; const path = require("path"); async function sendTransaction(argv: any, threadId: number) { @@ -235,6 +237,56 @@ export const bridgeNativeTokenToL3Command = { }, }; +export const transferL3ChainOwnershipCommand = { + command: "transfer-l3-chain-ownership", + describe: "transfer L3 chain ownership to upgrade executor", + builder: { + creator: { + string: true, + describe: "address of the token bridge creator", + }, + wait: { + boolean: true, + describe: "wait till ownership is transferred", + default: false, + }, + }, + handler: async (argv: any) => { + // get inbox address from config file + const deploydata = JSON.parse( + fs + .readFileSync(path.join(consts.configpath, "l3deployment.json")) + .toString() + ); + const inboxAddr = ethers.utils.hexlify(deploydata.inbox); + + // get L3 upgrade executor address from token bridge creator + const l2provider = new ethers.providers.WebSocketProvider(argv.l2url); + const tokenBridgeCreator = new ethers.Contract(argv.creator, L1AtomicTokenBridgeCreator.abi, l2provider); + const [,,,,,,,l3UpgradeExecutorAddress,] = await tokenBridgeCreator.inboxToL2Deployment(inboxAddr); + + // set TX params + argv.provider = new ethers.providers.WebSocketProvider(argv.l3url); + argv.to = "address_" + ARB_OWNER; + argv.from = "l3owner"; + argv.ethamount = "0"; + + // add L3 UpgradeExecutor to chain owners + const arbOwnerIface = new ethers.utils.Interface([ + "function addChainOwner(address newOwner) external", + "function removeChainOwner(address ownerToRemove) external" + ]) + argv.data = arbOwnerIface.encodeFunctionData("addChainOwner", [l3UpgradeExecutorAddress]); + await runStress(argv, sendTransaction); + + // remove L3 owner from chain owners + argv.data = arbOwnerIface.encodeFunctionData("removeChainOwner", [namedAccount("l3owner").address]); + await runStress(argv, sendTransaction); + + argv.provider.destroy(); + } +}; + export const createERC20Command = { command: "create-erc20", describe: "creates simple ERC20 on L2", diff --git a/scripts/index.ts b/scripts/index.ts index e0a1aa48..69cfe156 100644 --- a/scripts/index.ts +++ b/scripts/index.ts @@ -20,6 +20,7 @@ import { sendL3Command, sendRPCCommand, waitForSyncCommand, + transferL3ChainOwnershipCommand, } from "./ethcommands"; async function main() { @@ -42,6 +43,7 @@ async function main() { .command(sendL2Command) .command(sendL3Command) .command(sendRPCCommand) + .command(transferL3ChainOwnershipCommand) .command(writeConfigCommand) .command(writeGethGenesisCommand) .command(writeL2ChainConfigCommand) diff --git a/test-node.bash b/test-node.bash index 91b2bef1..7a86c54a 100755 --- a/test-node.bash +++ b/test-node.bash @@ -5,7 +5,8 @@ set -e NITRO_NODE_VERSION=offchainlabs/nitro-node:v3.0.1-cf4b74e-dev BLOCKSCOUT_VERSION=offchainlabs/blockscout:v1.0.0-c8db5b1 -DEFAULT_NITRO_CONTRACTS_VERSION="v2.1.0" +# This commit matches v2.1.0 release of nitro-contracts, with additional support to set arb owner through upgrade executor +DEFAULT_NITRO_CONTRACTS_VERSION="99c07a7db2fcce75b751c5a2bd4936e898cda065" DEFAULT_TOKEN_BRIDGE_VERSION="v1.2.2" # Set default versions if not overriden by provided env vars @@ -465,6 +466,11 @@ if $force_init; then fi docker compose run -e PARENT_WETH_OVERRIDE=$l2Weth -e ROLLUP_OWNER_KEY=$l3ownerkey -e ROLLUP_ADDRESS=$rollupAddress -e PARENT_RPC=http://sequencer:8547 -e PARENT_KEY=$deployer_key -e CHILD_RPC=http://l3node:3347 -e CHILD_KEY=$deployer_key tokenbridge deploy:local:token-bridge docker compose run --entrypoint sh tokenbridge -c "cat network.json && cp network.json l2l3_network.json" + + # set L3 UpgradeExecutor, deployed by token bridge creator in previous step, to be the L3 chain owner. L3owner (EOA) and alias of L2 UpgradeExectuor have the executor role on the L3 UpgradeExecutor + echo == Set L3 UpgradeExecutor to be chain owner + tokenBridgeCreator=`docker compose run --entrypoint sh tokenbridge -c "cat l2l3_network.json" | jq -r '.l1TokenBridgeCreator'` + docker compose run scripts transfer-l3-chain-ownership --creator $tokenBridgeCreator echo fi