Skip to content

Commit

Permalink
Merge pull request #98 from OffchainLabs/bold-upgrade
Browse files Browse the repository at this point in the history
feat: bold upgrader
  • Loading branch information
PlasmaPower authored Dec 6, 2024
2 parents e28b144 + ddbfb34 commit 1c6a92f
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 24 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,20 @@ jobs:

- name: Startup Nitro testnode
run: ${{ github.workspace }}/.github/workflows/testnode.bash --init-force ${{ (matrix.l3node == 'l3node' && '--l3node') || (matrix.l3node == 'l3node-token-6' && '--l3node --l3-fee-token --l3-token-bridge --l3-fee-token-decimals 6') || '' }} ${{ matrix.tokenbridge == 'tokenbridge' && '--tokenbridge' || '--no-tokenbridge' }} --detach ${{ matrix.pos == 'pos' && '--pos' || '' }} --simple ${{ (matrix.simple == 'simple' && '--simple') || (matrix.simple == 'no-simple' && '--no-simple') || '' }}

bold_upgrade:
runs-on: ubuntu-8

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host

- name: Startup Nitro testnode
run: ${{ github.workspace }}/.github/workflows/testnode.bash --init-force --bold-upgrade --simple --detach
14 changes: 14 additions & 0 deletions boldupgrader/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM node:18-bullseye-slim
RUN apt-get update && \
apt-get install -y git docker.io python3 make gcc g++ curl jq
ARG BOLD_CONTRACTS_BRANCH=bold-merge-script
WORKDIR /workspace
RUN git clone --no-checkout https://github.com/OffchainLabs/nitro-contracts.git ./
RUN git checkout ${BOLD_CONTRACTS_BRANCH}
RUN yarn install && yarn cache clean
RUN curl -L https://foundry.paradigm.xyz | bash
ENV PATH="${PATH}:/root/.foundry/bin"
RUN foundryup
RUN touch scripts/config.ts
RUN yarn build:all
ENTRYPOINT ["yarn"]
11 changes: 11 additions & 0 deletions docker-compose-ci-cache.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@
"type=docker"
]
},
"boldupgrader": {
"cache-from": [
"type=local,src=/tmp/.buildx-cache"
],
"cache-to": [
"type=local,dest=/tmp/.buildx-cache,mode=max"
],
"output": [
"type=docker"
]
},
"tokenbridge": {
"cache-from": [
"type=local,src=/tmp/.buildx-cache"
Expand Down
21 changes: 21 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,26 @@ services:
- "tokenbridge-data:/workspace"
- /var/run/docker.sock:/var/run/docker.sock

boldupgrader:
depends_on:
- geth
- sequencer
pid: host
build:
context: boldupgrader/
args:
BOLD_CONTRACTS_BRANCH: ${BOLD_CONTRACTS_BRANCH:-}
environment:
- L1_RPC_URL=http://geth:8545
- L1_PRIV_KEY=0xdc04c5399f82306ec4b4d654a342f40e2e0620fe39950d967e1e574b32d4dd36
- CONFIG_NETWORK_NAME=local
- DEPLOYED_CONTRACTS_DIR=./scripts/files/
- DISABLE_VERIFICATION=true
volumes:
- "config:/config"
- "boldupgrader-data:/workspace"
- /var/run/docker.sock:/var/run/docker.sock

rollupcreator:
depends_on:
- geth
Expand Down Expand Up @@ -383,3 +403,4 @@ volumes:
config:
postgres-data:
tokenbridge-data:
boldupgrader-data:
86 changes: 68 additions & 18 deletions scripts/ethcommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ 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 TestWETH9 from "@arbitrum/token-bridge-contracts/build/contracts/contracts/tokenbridge/test/TestWETH9.sol/TestWETH9.json";
import * as fs from "fs";
import { ARB_OWNER } from "./consts";
const path = require("path");
Expand Down Expand Up @@ -139,6 +140,14 @@ async function deployERC20Contract(deployerWallet: Wallet, decimals: number): Pr
return token.address;
}

async function deployWETHContract(deployerWallet: Wallet): Promise<string> {
const wethFactory = new ContractFactory(TestWETH9.abi, TestWETH9.bytecode, deployerWallet);
const weth = await wethFactory.deploy("Wrapped Ether", "WETH");
await weth.deployTransaction.wait();

return weth.address;
}

export const bridgeFundsCommand = {
command: "bridge-funds",
describe: "sends funds from l1 to l2",
Expand Down Expand Up @@ -299,6 +308,10 @@ export const createERC20Command = {
boolean: true,
describe: "if true, deploy on L1 and bridge to L2",
},
l1: {
boolean: true,
describe: "if true, deploy on L1 only",
},
decimals: {
string: true,
describe: "number of decimals for token",
Expand All @@ -308,26 +321,26 @@ export const createERC20Command = {
handler: async (argv: any) => {
console.log("create-erc20");

if (argv.bridgeable) {
// deploy token on l1 and bridge to l2
const l1l2tokenbridge = JSON.parse(
fs
.readFileSync(path.join(consts.tokenbridgedatapath, "l1l2_network.json"))
.toString()
);
if (argv.bridgeable || argv.l1) {

// deploy token on l1
const l1provider = new ethers.providers.WebSocketProvider(argv.l1url);
const l2provider = new ethers.providers.WebSocketProvider(argv.l2url);

const deployerWallet = new Wallet(
ethers.utils.sha256(ethers.utils.toUtf8Bytes(argv.deployer)),
l1provider
);
const deployerWallet = namedAccount(argv.deployer).connect(l1provider);

const tokenAddress = await deployERC20Contract(deployerWallet, argv.decimals);
const token = new ethers.Contract(tokenAddress, ERC20.abi, deployerWallet);
console.log("Contract deployed at L1 address:", token.address);

if (!argv.bridgeable) return;

// bridge to l2
const l2provider = new ethers.providers.WebSocketProvider(argv.l2url);
const l1l2tokenbridge = JSON.parse(
fs
.readFileSync(path.join(consts.tokenbridgedatapath, "l1l2_network.json"))
.toString()
);

const l1GatewayRouter = new ethers.Contract(l1l2tokenbridge.l2Network.tokenBridge.l1GatewayRouter, L1GatewayRouter.abi, deployerWallet);
await (await token.functions.approve(l1l2tokenbridge.l2Network.tokenBridge.l1ERC20Gateway, ethers.constants.MaxUint256)).wait();
const supply = await token.totalSupply();
Expand Down Expand Up @@ -361,10 +374,7 @@ export const createERC20Command = {

// no l1-l2 token bridge, deploy token on l2 directly
argv.provider = new ethers.providers.WebSocketProvider(argv.l2url);
const deployerWallet = new Wallet(
ethers.utils.sha256(ethers.utils.toUtf8Bytes(argv.deployer)),
argv.provider
);
const deployerWallet = namedAccount(argv.deployer).connect(argv.provider);
const tokenAddress = await deployERC20Contract(deployerWallet, argv.decimals);
console.log("Contract deployed at address:", tokenAddress);

Expand Down Expand Up @@ -392,11 +402,19 @@ export const transferERC20Command = {
string: true,
describe: "address (see general help)",
},
l1: {
boolean: true,
describe: "if true, transfer on L1",
},
},
handler: async (argv: any) => {
console.log("transfer-erc20");

argv.provider = new ethers.providers.WebSocketProvider(argv.l2url);
if (argv.l1) {
argv.provider = new ethers.providers.WebSocketProvider(argv.l1url);
} else {
argv.provider = new ethers.providers.WebSocketProvider(argv.l2url);
}
const account = namedAccount(argv.from).connect(argv.provider);
const tokenContract = new ethers.Contract(argv.token, ERC20.abi, account);
const tokenDecimals = await tokenContract.decimals();
Expand All @@ -406,6 +424,38 @@ export const transferERC20Command = {
},
};

export const createWETHCommand = {
command: "create-weth",
describe: "creates WETH on L1",
builder: {
deployer: {
string: true,
describe: "account (see general help)"
},
deposit: {
number: true,
describe: "amount of weth to deposit",
default: 100,
}
},
handler: async (argv: any) => {
console.log("create-weth");

const l1provider = new ethers.providers.WebSocketProvider(argv.l1url);
const deployerWallet = namedAccount(argv.deployer).connect(l1provider);

const wethAddress = await deployWETHContract(deployerWallet);
const weth = new ethers.Contract(wethAddress, TestWETH9.abi, deployerWallet);
console.log("WETH deployed at L1 address:", weth.address);

if (argv.deposit > 0) {
const amount = ethers.utils.parseEther(argv.deposit.toString());
const depositTx = await deployerWallet.sendTransaction({ to: wethAddress, value: amount, data:"0xd0e30db0" }); // deposit()
await depositTx.wait();
}
},
};

export const sendL1Command = {
command: "send-l1",
describe: "sends funds between l1 accounts",
Expand Down
2 changes: 2 additions & 0 deletions scripts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
bridgeNativeTokenToL3Command,
bridgeToL3Command,
createERC20Command,
createWETHCommand,
transferERC20Command,
sendL1Command,
sendL2Command,
Expand All @@ -38,6 +39,7 @@ async function main() {
.command(bridgeToL3Command)
.command(bridgeNativeTokenToL3Command)
.command(createERC20Command)
.command(createWETHCommand)
.command(transferERC20Command)
.command(sendL1Command)
.command(sendL2Command)
Expand Down
37 changes: 31 additions & 6 deletions test-node.bash
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@ set -eu
NITRO_NODE_VERSION=offchainlabs/nitro-node:v3.2.1-d81324d-dev
BLOCKSCOUT_VERSION=offchainlabs/blockscout:v1.1.0-0e716c8

# 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_NITRO_CONTRACTS_VERSION="v2.1.1-beta.0"
DEFAULT_TOKEN_BRIDGE_VERSION="v1.2.2"

# The is the latest bold-merge commit in nitro-contracts at the time
DEFAULT_BOLD_CONTRACTS_VERSION="42d80e40"

# Set default versions if not overriden by provided env vars
: ${NITRO_CONTRACTS_BRANCH:=$DEFAULT_NITRO_CONTRACTS_VERSION}
: ${BOLD_CONTRACTS_BRANCH:=$DEFAULT_BOLD_CONTRACTS_VERSION}
: ${TOKEN_BRIDGE_BRANCH:=$DEFAULT_TOKEN_BRIDGE_VERSION}
export NITRO_CONTRACTS_BRANCH
export BOLD_CONTRACTS_BRANCH
export TOKEN_BRIDGE_BRANCH

echo "Using NITRO_CONTRACTS_BRANCH: $NITRO_CONTRACTS_BRANCH"
echo "Using BOLD_CONTRACTS_BRANCH: $BOLD_CONTRACTS_BRANCH"
echo "Using TOKEN_BRIDGE_BRANCH: $TOKEN_BRIDGE_BRANCH"

mydir=`dirname $0`
Expand Down Expand Up @@ -44,6 +49,7 @@ blockscout=false
tokenbridge=false
l3node=false
consensusclient=false
boldupgrade=false
redundantsequencers=0
l3_custom_fee_token=false
l3_token_bridge=false
Expand Down Expand Up @@ -203,6 +209,10 @@ while [[ $# -gt 0 ]]; do
l1chainid=1337
shift
;;
--bold-upgrade)
boldupgrade=true
shift
;;
--l3node)
l3node=true
shift
Expand Down Expand Up @@ -282,8 +292,8 @@ while [[ $# -gt 0 ]]; do
echo --no-build-dev-nitro don\'t rebuild dev nitro docker image
echo --build-dev-blockscout rebuild dev blockscout docker image
echo --no-build-dev-blockscout don\'t rebuild dev blockscout docker image
echo --build-utils rebuild scripts, rollupcreator, token bridge docker images
echo --no-build-utils don\'t rebuild scripts, rollupcreator, token bridge docker images
echo --build-utils rebuild scripts, rollupcreator, boldupgrader, token bridge docker images
echo --no-build-utils don\'t rebuild scripts, rollupcreator, boldupgrader, token bridge docker images
echo --force-build-utils force rebuilding utils, useful if NITRO_CONTRACTS_ or TOKEN_BRIDGE_BRANCH changes
echo
echo script runs inside a separate docker. For SCRIPT-ARGS, run $0 script --help
Expand Down Expand Up @@ -352,7 +362,7 @@ if $dev_blockscout && $build_dev_blockscout; then
fi

if $build_utils; then
LOCAL_BUILD_NODES="scripts rollupcreator"
LOCAL_BUILD_NODES="scripts rollupcreator boldupgrader"
# always build tokenbridge in CI mode to avoid caching issues
if $tokenbridge || $l3_token_bridge || $ci; then
LOCAL_BUILD_NODES="$LOCAL_BUILD_NODES tokenbridge"
Expand Down Expand Up @@ -473,11 +483,11 @@ if $force_init; then
docker compose up --wait $INITIAL_SEQ_NODES
docker compose run scripts bridge-funds --ethamount 100000 --wait
docker compose run scripts send-l2 --ethamount 100 --to l2owner --wait
rollupAddress=`docker compose run --entrypoint sh poster -c "jq -r '.[0].rollup.rollup' /config/deployed_chain_info.json | tail -n 1 | tr -d '\r\n'"`

if $tokenbridge; then
echo == Deploying L1-L2 token bridge
sleep 10 # no idea why this sleep is needed but without it the deploy fails randomly
rollupAddress=`docker compose run --entrypoint sh poster -c "jq -r '.[0].rollup.rollup' /config/deployed_chain_info.json | tail -n 1 | tr -d '\r\n'"`
docker compose run -e ROLLUP_OWNER_KEY=$l2ownerKey -e ROLLUP_ADDRESS=$rollupAddress -e PARENT_KEY=$devprivkey -e PARENT_RPC=http://geth:8545 -e CHILD_KEY=$devprivkey -e CHILD_RPC=http://sequencer:8547 tokenbridge deploy:local:token-bridge
docker compose run --entrypoint sh tokenbridge -c "cat network.json && cp network.json l1l2_network.json && cp network.json localNetwork.json"
echo
Expand All @@ -486,6 +496,21 @@ if $force_init; then
echo == Deploy CacheManager on L2
docker compose run -e CHILD_CHAIN_RPC="http://sequencer:8547" -e CHAIN_OWNER_PRIVKEY=$l2ownerKey rollupcreator deploy-cachemanager-testnode

if $boldupgrade; then
echo == Deploying WETH as BOLD stake token
stakeTokenAddress=`docker compose run scripts create-weth --deployer l2owner --deposit 100 | tail -n 1 | awk '{ print $NF }'`
echo BOLD stake token address: $stakeTokenAddress
docker compose run scripts transfer-erc20 --token $stakeTokenAddress --l1 --amount 100 --from l2owner --to validator
echo == Preparing BOLD upgrade
docker compose run -e TESTNODE_MODE=true -e ROLLUP_ADDRESS=$rollupAddress -e STAKE_TOKEN=$stakeTokenAddress boldupgrader script:bold-prepare
# retry this 10 times because the staker might not have made a node yet
for i in {1..10}; do
docker compose run -e TESTNODE_MODE=true -e ROLLUP_ADDRESS=$rollupAddress -e STAKE_TOKEN=$stakeTokenAddress boldupgrader script:bold-populate-lookup && break || true
echo "Failed to populate lookup table, retrying..."
sleep 10
done
docker compose run -e TESTNODE_MODE=true -e ROLLUP_ADDRESS=$rollupAddress -e STAKE_TOKEN=$stakeTokenAddress boldupgrader script:bold-local-execute
fi

if $l3node; then
echo == Funding l3 users
Expand Down

0 comments on commit 1c6a92f

Please sign in to comment.