Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions docker/contract-deployer.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
FROM ghcr.io/foundry-rs/foundry:v1.3.1 AS foundry

FROM node:20-trixie-slim AS nitro-builder

COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge

RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*

WORKDIR /workspace/nitro-contracts

RUN git init . \
&& git remote add origin https://github.com/OffchainLabs/nitro-contracts.git \
&& git fetch --depth 1 origin 2f747c722d98d5fd662bfda08cd86aa534b22be2 \
&& git checkout --detach FETCH_HEAD \
&& git submodule update --init --recursive --depth 1

RUN cp scripts/config.example.ts scripts/config.ts
RUN yarn install --frozen-lockfile
RUN yarn build:all

FROM node:20-trixie-slim AS token-bridge-builder

COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge

RUN apt-get update && \
apt-get install -y git python3 build-essential && \
rm -rf /var/lib/apt/lists/*

WORKDIR /workspace/token-bridge-contracts

RUN git init . \
&& git remote add origin https://github.com/OffchainLabs/token-bridge-contracts.git \
&& git fetch --depth 1 origin 5975d8f7360816341be7f94fd333ef240f4aec23 \
&& git checkout --detach FETCH_HEAD

RUN yarn install --frozen-lockfile
RUN yarn build

FROM node:20-trixie-slim

COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge

WORKDIR /workspace
COPY --from=nitro-builder /workspace/nitro-contracts /workspace/nitro-contracts
COPY --from=token-bridge-builder /workspace/token-bridge-contracts /workspace/token-bridge-contracts

WORKDIR /workspace/nitro-contracts
ENTRYPOINT ["yarn"]
17 changes: 0 additions & 17 deletions docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,6 @@ services:
- ../config:/config
- tokenbridge-data:/tokenbridge-data

tokenbridge:
image: nitro-testnode-tokenbridge:latest
build:
context: .
dockerfile: tokenbridge.Dockerfile
depends_on:
- sequencer
environment:
- ARB_URL=http://sequencer:8547
- ETH_URL=http://host.docker.internal:8545
volumes:
- ../config:/config
- tokenbridge-data:/workspace
- /var/run/docker.sock:/var/run/docker.sock
extra_hosts:
- "host.docker.internal:host-gateway"

volumes:
sequencer-data:
l3node-data:
Expand Down
75 changes: 0 additions & 75 deletions docker/tokenbridge.Dockerfile

This file was deleted.

131 changes: 93 additions & 38 deletions src/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import { parseEther } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { accounts } from "../accounts.js";
import { writeChainConfig } from "../chain-config.js";
import {
CONTRACT_DEPLOYER_IMAGE,
NITRO_CONTRACTS_WORKDIR,
ensureContractDeployerImage,
} from "../contract-deployer-image.js";
import { clampDepositAmount } from "../deposit-amount.js";
import { composeRestart, composeUp, waitForRpc } from "../docker.js";
import { execOrThrow } from "../exec.js";
Expand All @@ -31,7 +36,7 @@ import {
updateRunStep,
} from "../run-logger.js";
import { startAnvilWithState, startNitroFromSnapshot, stopRuntime } from "../runtime.js";
import { deployRollupViaSdk, prepareNodeConfigFromDeployment } from "../sdk-chain.js";
import { prepareNodeConfigFromDeployment } from "../sdk-chain.js";
import { installSnapshotRelease } from "../snapshot-release.js";
import {
DEFAULT_SNAPSHOT_ID,
Expand Down Expand Up @@ -71,8 +76,7 @@ const L1_RPC_DOCKER = "http://host.docker.internal:8545";
const L2_RPC_DOCKER = "http://host.docker.internal:8547";
const L2_RPC_INTERNAL = "http://sequencer:8547";

const ROLLUPCREATOR_IMAGE = "nitro-testnode-rollupcreator:latest";
const WASM_MODULE_ROOT = "0x8a7513bf7bb3e3db04b0d982d0e973bcf57bf8b88aef7c6d03dba3a81a56a499";
const WASM_MODULE_ROOT = "0xdb698a2576298f25448bc092e52cf13b1e24141c997135d70f217d674bbeb69a";
const L2_DEPOSIT_READY_THRESHOLD_WEI = 250n * 10n ** 18n;
const L3_DEPOSIT_TARGET_WEI = 50n * 10n ** 18n;
const L3_DEPOSIT_RESERVE_WEI = 1n * 10n ** 18n;
Expand Down Expand Up @@ -327,20 +331,80 @@ async function waitForL3RpcWithParentChainNudges(timeoutMs = 300_000): Promise<v
throw new Error(`RPC at ${L3_RPC} not ready after ${timeoutMs}ms`);
}

function deployRollupViaDocker(envVars: Record<string, string>): void {
function deployRollupViaDocker(params: {
dockerParentRpc: string;
parentChainId: string;
deployerKey: string;
childChainName: string;
maxDataSize: string;
ownerAddress: string;
sequencerAddress: string;
dockerChildChainConfigPath: string;
dockerDeploymentOutputPath: string;
dockerChainInfoOutputPath: string;
feeTokenAddress?: string | undefined;
}): void {
ensureContractDeployerImage();
const args = [
"run",
"--rm",
"--add-host",
"host.docker.internal:host-gateway",
"--workdir",
NITRO_CONTRACTS_WORKDIR,
"-v",
`${CONFIG_DIR}:/config`,
"-e",
`PARENT_CHAIN_RPC=${params.dockerParentRpc}`,
"-e",
`DEPLOYER_PRIVKEY=${params.deployerKey}`,
"-e",
`PARENT_CHAIN_ID=${params.parentChainId}`,
"-e",
`CHILD_CHAIN_NAME=${params.childChainName}`,
"-e",
`MAX_DATA_SIZE=${params.maxDataSize}`,
"-e",
`OWNER_ADDRESS=${params.ownerAddress}`,
"-e",
`WASM_MODULE_ROOT=${WASM_MODULE_ROOT}`,
"-e",
`SEQUENCER_ADDRESS=${params.sequencerAddress}`,
"-e",
"AUTHORIZE_VALIDATORS=10",
"-e",
`CHILD_CHAIN_CONFIG_PATH=${params.dockerChildChainConfigPath}`,
"-e",
`CHAIN_DEPLOYMENT_INFO=${params.dockerDeploymentOutputPath}`,
"-e",
`CHILD_CHAIN_INFO=${params.dockerChainInfoOutputPath}`,
];
for (const [key, value] of Object.entries(envVars)) {
args.push("-e", `${key}=${value}`);
if (params.feeTokenAddress) {
args.push("-e", `FEE_TOKEN_ADDRESS=${params.feeTokenAddress}`);
}
args.push(ROLLUPCREATOR_IMAGE, "create-rollup-testnode");
execOrThrow("docker", args, { timeout: 300_000 });
args.push(
CONTRACT_DEPLOYER_IMAGE,
"hardhat",
"run",
"--no-compile",
"scripts/local-deployment/deployCreatorAndCreateRollup.ts",
);
const output = execOrThrow("docker", args, { timeout: 900_000 });
addRollupCreatorToDeployment(
resolve(CONFIG_DIR, params.dockerDeploymentOutputPath.slice(8)),
output,
);
}

function addRollupCreatorToDeployment(deploymentPath: string, output: string): void {
const match = output.match(/RollupCreator created at address:\s+(0x[a-fA-F0-9]{40})/);
const rollupCreator = match?.[1];
if (!rollupCreator) {
return;
}
const deployment = JSON.parse(readFileSync(deploymentPath, "utf-8")) as Record<string, unknown>;
deployment["rollup-creator"] = rollupCreator;
writeFileSync(deploymentPath, JSON.stringify(deployment, null, 2));
}

function patchConfigUrl(configPath: string, hostUrl: string, dockerUrl: string): void {
Expand Down Expand Up @@ -388,18 +452,16 @@ function createL2DeploySteps(): Record<string, StepRunner> {
owner: accounts.l2owner.address,
});
deployRollupViaDocker({
PARENT_CHAIN_RPC: L1_RPC_DOCKER,
DEPLOYER_PRIVKEY: accounts.l2owner.privateKey,
PARENT_CHAIN_ID: "1337",
CHILD_CHAIN_NAME: "arb-dev-test",
MAX_DATA_SIZE: "117964",
OWNER_ADDRESS: accounts.l2owner.address,
WASM_MODULE_ROOT: WASM_MODULE_ROOT,
SEQUENCER_ADDRESS: accounts.sequencer.address,
AUTHORIZE_VALIDATORS: "10",
CHILD_CHAIN_CONFIG_PATH: "/config/l2_chain_config.json",
CHAIN_DEPLOYMENT_INFO: "/config/l2_deployment.json",
CHILD_CHAIN_INFO: "/config/l2_chain_info.json",
dockerParentRpc: L1_RPC_DOCKER,
parentChainId: "1337",
deployerKey: accounts.l2owner.privateKey,
childChainName: "arb-dev-test",
maxDataSize: "117964",
ownerAddress: accounts.l2owner.address,
sequencerAddress: accounts.sequencer.address,
dockerChildChainConfigPath: "/config/l2_chain_config.json",
dockerDeploymentOutputPath: "/config/l2_deployment.json",
dockerChainInfoOutputPath: "/config/l2_chain_info.json",
});
copyConfigFile("l2_deployment.json", "deployment.json");
const deployment = readDeployment("l2_deployment.json");
Expand Down Expand Up @@ -585,25 +647,18 @@ function createL3Steps(feeTokenDecimals?: number): Record<string, StepRunner> {
);
}

await deployRollupViaSdk({
chainConfigPath: resolve(CONFIG_DIR, "l3_chain_config.json"),
chainId: 333333,
chainName: "orbit-dev-test",
parentChainId: 412346,
parentChainIsArbitrum: true,
parentRpcUrl: L2_RPC,
deployRollupViaDocker({
dockerParentRpc: L2_RPC_DOCKER,
parentChainId: "412346",
deployerKey: accounts.l3owner.privateKey,
childChainName: "orbit-dev-test",
maxDataSize: "104857",
ownerAddress: accounts.l3owner.address,
ownerKey: accounts.l3owner.privateKey,
batchPosterAddress: accounts.l3sequencer.address,
batchPosterKey: accounts.l3sequencer.privateKey,
validatorAddress: accounts.l3owner.address,
validatorKey: accounts.l3owner.privateKey,
maxDataSize: 104857n,
wasmModuleRoot: WASM_MODULE_ROOT as `0x${string}`,
deploymentOutputPath: resolve(CONFIG_DIR, "l3_deployment.json"),
chainInfoOutputPath: resolve(CONFIG_DIR, "l3_chain_info.json"),
rawNodeConfigOutputPath: resolve(CONFIG_DIR, "l3-nodeConfig.raw.json"),
...(feeTokenAddress ? { nativeToken: feeTokenAddress as `0x${string}` } : {}),
sequencerAddress: accounts.l3sequencer.address,
dockerChildChainConfigPath: "/config/l3_chain_config.json",
dockerDeploymentOutputPath: "/config/l3_deployment.json",
dockerChainInfoOutputPath: "/config/l3_chain_info.json",
...(feeTokenAddress ? { feeTokenAddress } : {}),
});

copyConfigFile("l3_deployment.json", "l3deployment.json");
Expand Down
40 changes: 40 additions & 0 deletions src/contract-deployer-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { resolve } from "node:path";
import { exec, execOrThrow } from "./exec.js";

const PROJECT_ROOT = resolve(import.meta.dirname, "..");
const CONTRACT_DEPLOYER_DOCKERFILE = resolve(PROJECT_ROOT, "docker/contract-deployer.Dockerfile");

export const CONTRACT_DEPLOYER_IMAGE = "nitro-testnode-contract-deployer:latest";
export const NITRO_CONTRACTS_WORKDIR = "/workspace/nitro-contracts";
export const TOKEN_BRIDGE_CONTRACTS_WORKDIR = "/workspace/token-bridge-contracts";

let contractDeployerImageBuilt = false;

export function ensureContractDeployerImage(): void {
if (contractDeployerImageBuilt) {
return;
}

if (
exec("docker", ["image", "inspect", CONTRACT_DEPLOYER_IMAGE], { timeout: 30_000 }).exitCode ===
0
) {
contractDeployerImageBuilt = true;
return;
}

execOrThrow(
"docker",
[
"build",
"-t",
CONTRACT_DEPLOYER_IMAGE,
"-f",
CONTRACT_DEPLOYER_DOCKERFILE,
resolve(PROJECT_ROOT, "docker"),
],
{ timeout: 1_800_000 },
);

contractDeployerImageBuilt = true;
}
Loading
Loading