diff --git a/.env.example b/.env.example index fa281a3..04412ef 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,9 @@ ########################## # Private keys (Required) ########################## -CHAIN_OWNER_PRIVATE_KEY=0x0 -BATCH_POSTER_PRIVATE_KEY=0x0 -STAKER_PRIVATE_KEY=0x0 +CHAIN_OWNER_PRIVATE_KEY= +BATCH_POSTER_PRIVATE_KEY= +STAKER_PRIVATE_KEY= ########################## @@ -17,7 +17,7 @@ PARENT_CHAIN_BEACON_RPC_URL= ############################ # Arbitrum chain information ############################ -ARBITRUM_CHAIN_NAME= +ARBITRUM_CHAIN_NAME=TestChain USE_GENESIS_FILE=false @@ -35,11 +35,13 @@ DEPLOY_FACTORIES_TO_L2=true # Nitro node ########################## NITRO_DOCKER_IMAGE_TAG="offchainlabs/nitro-node:v3.8.0-62c0aa7" -NITRO_RPC_URL="http://localhost" +NITRO_RPC_URL="http://127.0.0.1" NITRO_PORT=8449 # Whether to split the Nitro node into one batch-poster, one staker, and one rpc node # If set to false, a single Nitro node will handle all three roles SPLIT_NODES=false +# Whether to attach the docker containers to a specific network +DOCKER_NETWORK= ########################## diff --git a/.github/resources/WETH9.sol b/.github/resources/WETH9.sol new file mode 100644 index 0000000..19eb34f --- /dev/null +++ b/.github/resources/WETH9.sol @@ -0,0 +1,62 @@ +pragma solidity ^0.4.18; + +contract WETH9 { + string public name = "Wrapped Ether"; + string public symbol = "WETH"; + uint8 public decimals = 18; + + event Approval(address indexed src, address indexed guy, uint wad); + event Transfer(address indexed src, address indexed dst, uint wad); + event Deposit(address indexed dst, uint wad); + event Withdrawal(address indexed src, uint wad); + + mapping (address => uint) public balanceOf; + mapping (address => mapping (address => uint)) public allowance; + + function() public payable { + deposit(); + } + function deposit() public payable { + balanceOf[msg.sender] += msg.value; + Deposit(msg.sender, msg.value); + } + function withdraw(uint wad) public { + require(balanceOf[msg.sender] >= wad); + balanceOf[msg.sender] -= wad; + msg.sender.transfer(wad); + Withdrawal(msg.sender, wad); + } + + function totalSupply() public view returns (uint) { + return this.balance; + } + + function approve(address guy, uint wad) public returns (bool) { + allowance[msg.sender][guy] = wad; + Approval(msg.sender, guy, wad); + return true; + } + + function transfer(address dst, uint wad) public returns (bool) { + return transferFrom(msg.sender, dst, wad); + } + + function transferFrom(address src, address dst, uint wad) + public + returns (bool) + { + require(balanceOf[src] >= wad); + + if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) { + require(allowance[src][msg.sender] >= wad); + allowance[src][msg.sender] -= wad; + } + + balanceOf[src] -= wad; + balanceOf[dst] += wad; + + Transfer(src, dst, wad); + + return true; + } +} diff --git a/.github/resources/kurtosis-network-params.yaml b/.github/resources/kurtosis-network-params.yaml new file mode 100644 index 0000000..c5f8b41 --- /dev/null +++ b/.github/resources/kurtosis-network-params.yaml @@ -0,0 +1,15 @@ +participants: + - el_type: geth + el_image: "ethereum/client-go:v1.16.7" + el_extra_params: [ + "--state.scheme=hash", + "--gcmode=archive", + "--syncmode=full", + ] + cl_type: prysm + cl_image: "gcr.io/offchainlabs/prysm/beacon-chain:v7.1.0" + vc_type: prysm + vc_image: "gcr.io/offchainlabs/prysm/validator:v7.1.0" +network_params: + network_id: "1337" + prefunded_accounts: '{"0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E": {"balance": "100ETH"}}' \ No newline at end of file diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml new file mode 100644 index 0000000..8168c59 --- /dev/null +++ b/.github/workflows/ci-test.yml @@ -0,0 +1,104 @@ +name: CI + +on: + pull_request: + workflow_dispatch: + +jobs: + test-e2e: + name: Test e2e + runs-on: ubuntu-latest + env: + PARENT_CHAIN_ID: 1337 + PARENT_CHAIN_RPC_URL: "http://172.16.0.10:8545" + PARENT_CHAIN_BEACON_RPC_URL: "http://172.16.0.11:3500" + CHAIN_OWNER_PRIVATE_KEY: "0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659" + BATCH_POSTER_PRIVATE_KEY: "0xcb5790da63720727af975f42c79f69918580209889225fa7128c92402a6d3a65" + STAKER_PRIVATE_KEY: "0x182fecf15bdf909556a0f617a63e05ab22f1493d25a9f1e27c228266c772a890" + MAX_DATA_SIZE: 117964 + CHAIN_MAX_DATA_SIZE: 117964 + ROLLUPCREATOR_FACTORY_ADDRESS: "0x7D0ED5a90b744F5872261a7D5509A85b283E95c9" + TOKENBRIDGECREATOR_FACTORY_ADDRESS: "0xBd7f7c83BdBABfD65a98c6D2AFc9261F3d2Eb03B" + WETH_ADDRESS: "0xD92773693917F0fF664f85c3cB698c33420947ff" + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Kurtosis + run: | + echo "deb [trusted=yes] https://apt.fury.io/kurtosis-tech/ /" | sudo tee /etc/apt/sources.list.d/kurtosis.list + sudo apt update + sudo apt install kurtosis-cli + + - name: Start Kurtosis engine + run: kurtosis engine start + + - name: Run L1 node + run: kurtosis run --enclave l1-network github.com/ethpandaops/ethereum-package --args-file .github/resources/kurtosis-network-params.yaml + + - name: Setup node/yarn + uses: actions/setup-node@v3 + with: + node-version: 22 + cache: 'yarn' + cache-dependency-path: '**/yarn.lock' + + - name: Install packages + run: yarn + + - name: Create .env file + run: cp .env.example .env + + - name: Update submodules + run: | + git submodule update --init --force --recursive nitro-contracts + git submodule update --init --force --recursive token-bridge-contracts + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: v1.3.6 + cache: false + + - name: Build nitro-contracts + run: yarn build-nitro-contracts + + - name: Deploy RollupCreator + env: + CUSTOM_RPC_URL: ${{ env.PARENT_CHAIN_RPC_URL }} + CUSTOM_PRIVKEY: ${{ env.CHAIN_OWNER_PRIVATE_KEY }} + run: CREATE2_PROXY_DEPLOYMENT=true yarn deploy-rollup-creator + + - name: Deploy WETH + run: forge create --rpc-url $PARENT_CHAIN_RPC_URL --private-key $CHAIN_OWNER_PRIVATE_KEY --broadcast ./.github/resources/WETH9.sol:WETH9 + + - name: Build token-bridge-contracts + run: yarn build-token-bridge-contracts + + - name: Deploy TokenBridgeCreator + env: + BASECHAIN_RPC: ${{ env.PARENT_CHAIN_RPC_URL }} + BASECHAIN_DEPLOYER_KEY: ${{ env.CHAIN_OWNER_PRIVATE_KEY }} + BASECHAIN_WETH: ${{ env.WETH_ADDRESS }} + run: yarn deploy-token-bridge-creator + + - name: Create Rollup + run: yarn deploy-chain + + - name: Start nitro + env: + DOCKER_NETWORK: "kt-l1-network" + run: CI_RUN=true yarn start-node + + - name: Check logs + run: docker compose logs nitro + + - name: Initialize chain + run: yarn initialize-chain + + - name: Deploy TokenBridge + run: yarn deploy-token-bridge + + - name: Transfer ownership + run: yarn transfer-ownership \ No newline at end of file diff --git a/blockscout/docker-compose-clean.yaml b/blockscout/docker-compose-clean.yaml index 5d48991..87b57d7 100644 --- a/blockscout/docker-compose-clean.yaml +++ b/blockscout/docker-compose-clean.yaml @@ -1,5 +1,3 @@ -version: '3.9' - services: # Based on ./services/redis.yml redis-db-clean: diff --git a/blockscout/docker-compose.yaml b/blockscout/docker-compose.yaml index 7e5b280..33ee764 100644 --- a/blockscout/docker-compose.yaml +++ b/blockscout/docker-compose.yaml @@ -1,5 +1,3 @@ -version: '3.9' - # Source reference (for other services, and defaults) # https://docs.docker.com/compose/compose-file/ diff --git a/docker-compose-split-nodes.yaml b/docker-compose-split-nodes.yaml index e5d2f29..509c358 100644 --- a/docker-compose-split-nodes.yaml +++ b/docker-compose-split-nodes.yaml @@ -1,5 +1,3 @@ -version: '3.9' - # Configuration for split nodes # Activate with the env variable SPLIT_NODES=true diff --git a/docker-compose.ci.yaml b/docker-compose.ci.yaml new file mode 100644 index 0000000..bad9dec --- /dev/null +++ b/docker-compose.ci.yaml @@ -0,0 +1,18 @@ +services: + nitro: + # Replace the base volumes with: + volumes: + # Named volume for chain data (no host permissions issues) + - nitro_data:/home/user/.arbitrum + + # Bind-mount the config into a different path, read-only + - ./chainConfig/rpc:/home/user/rpc-config:ro + + # Override the command so it uses the new config path + command: + - --conf.file=/home/user/rpc-config/rpc-config.json + - --node.feed.output.enable + - --node.feed.output.port=9642 + +volumes: + nitro_data: \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 46f18cf..e08a662 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,5 +1,3 @@ -version: '3.9' - # Extra services: # - Blockscout (under profile "blockscout") # - Split nodes (under profile "split-nodes") diff --git a/scripts/chain-deployer/deployNewChain.ts b/scripts/chain-deployer/deployNewChain.ts index 5d472b3..3b2c45f 100644 --- a/scripts/chain-deployer/deployNewChain.ts +++ b/scripts/chain-deployer/deployNewChain.ts @@ -34,7 +34,7 @@ if ( !process.env.STAKER_PRIVATE_KEY ) { throw new Error( - 'The following environment variables must be present: PARENT_CHAIN_ID, CHAIN_OWNER_PRIVATE_KEY, BATC_POSTER_PRIVATE_KEY, STAKER_PRIVATE_KEY', + 'The following environment variables must be present: PARENT_CHAIN_ID, CHAIN_OWNER_PRIVATE_KEY, BATCH_POSTER_PRIVATE_KEY, STAKER_PRIVATE_KEY', ); } diff --git a/shell-scripts/deploy-rollupcreator.sh b/shell-scripts/deploy-rollupcreator.sh index 643cce2..5b09c02 100755 --- a/shell-scripts/deploy-rollupcreator.sh +++ b/shell-scripts/deploy-rollupcreator.sh @@ -1,8 +1,11 @@ #!/bin/bash # Loading .env file +# (This small hack preserves existing exported environment variables, usually set in CLI) set -o allexport +curenv=$(declare -p -x) source .env +eval "$curenv" set +o allexport # Check whether the required environment variables are set diff --git a/shell-scripts/deploy-tokenbridgecreator.sh b/shell-scripts/deploy-tokenbridgecreator.sh index 88709a0..97213fa 100755 --- a/shell-scripts/deploy-tokenbridgecreator.sh +++ b/shell-scripts/deploy-tokenbridgecreator.sh @@ -1,8 +1,11 @@ #!/bin/bash # Loading .env file +# (This small hack preserves existing exported environment variables, usually set in CLI) set -o allexport +curenv=$(declare -p -x) source .env +eval "$curenv" set +o allexport # Check whether the required environment variables are set diff --git a/shell-scripts/local-deployment.sh b/shell-scripts/local-deployment.sh new file mode 100644 index 0000000..e69de29 diff --git a/shell-scripts/start-nitro.sh b/shell-scripts/start-nitro.sh index e50d2fd..eb9b2f6 100755 --- a/shell-scripts/start-nitro.sh +++ b/shell-scripts/start-nitro.sh @@ -1,21 +1,57 @@ #!/usr/bin/env bash # Loading .env file +# (This small hack preserves existing exported environment variables, usually set in CLI) set -o allexport +curenv=$(declare -p -x) source .env +eval "$curenv" set +o allexport # Add single-node or split-nodes profile based on $SPLIT_NODES PROFILES="" if [ "$SPLIT_NODES" = "true" ]; then - PROFILES="$PROFILES --profile split-nodes" + PROFILES="$PROFILES split-nodes" else - PROFILES="$PROFILES --profile single-node" + PROFILES="$PROFILES single-node" fi # Add blockscout profile if enabled if [ "$ENABLE_BLOCKSCOUT" = "true" ]; then - PROFILES="$PROFILES --profile blockscout" + PROFILES="$PROFILES blockscout" fi -docker compose $PROFILES up +# Enable the selected profiles +export COMPOSE_PROFILES="$PROFILES" + +# If running in CI, layer docker-compose.ci.yaml on top +COMPOSE_FILES=() +if [ "$CI_RUN" = "true" ]; then + echo "CI_RUN=true detected: using docker-compose.ci.yaml overlay" + COMPOSE_FILES=(-f docker-compose.yaml -f docker-compose.ci.yaml) +else + COMPOSE_FILES=() +fi + +# Obtain the list of services to be started +mapfile -t SERVICES < <(docker compose config --services) +echo "Services: ${SERVICES[*]}" + +# Create containers without starting them +docker compose "${COMPOSE_FILES[@]}" create "${SERVICES[@]}" + +# Connect containers to the testnet docker network if needed +if [ -n "$DOCKER_NETWORK" ]; then + for svc in "${SERVICES[@]}"; do + echo "Connecting service $svc to network $DOCKER_NETWORK" + cid=$(docker compose "${COMPOSE_FILES[@]}" ps -a -q "$svc") + [ -z "$cid" ] && continue + docker network connect "$DOCKER_NETWORK" "$cid" 2>/dev/null || true + echo "Service connected" + done +fi + +# Start all services +docker compose "${COMPOSE_FILES[@]}" start "${SERVICES[@]}" + +echo "Nitro services started with profiles: $COMPOSE_PROFILES" \ No newline at end of file diff --git a/src/utils/chain-info-helpers.ts b/src/utils/chain-info-helpers.ts index 0449638..fa0a91c 100644 --- a/src/utils/chain-info-helpers.ts +++ b/src/utils/chain-info-helpers.ts @@ -46,7 +46,7 @@ export const getChainConfiguration = () => { }; export const chainIsL1 = (chain: Chain) => { - return chain.id == 1 || chain.id == 11155111; + return chain.id == 1 || chain.id == 11155111 || chain.id == 1337; }; export const chainIsAnytrust = (): boolean => { diff --git a/src/utils/node-configuration.ts b/src/utils/node-configuration.ts index be3a0ab..36c7147 100644 --- a/src/utils/node-configuration.ts +++ b/src/utils/node-configuration.ts @@ -50,7 +50,7 @@ export const buildNodeConfiguration = ( // Preparing the node configuration // const nodeConfigParameters: PrepareNodeConfigParams = { - chainName: process.env.ARBITRUM_CHAIN_NAME || 'My Arbitrum chain', + chainName: process.env.ARBITRUM_CHAIN_NAME || 'MyArbitrumChain', chainConfig, coreContracts, batchPosterPrivateKey,