From d4c266d3322d1e49c88ffe9da374d61298c5352c Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:14:42 +0530 Subject: [PATCH 01/36] chore: add workspace in package.json --- docker/l1-chain/package.json | 85 ++++++++++++++++++++++++ packages/solidity-contracts/package.json | 10 ++- pnpm-lock.yaml | 10 +++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 docker/l1-chain/package.json diff --git a/docker/l1-chain/package.json b/docker/l1-chain/package.json new file mode 100644 index 00000000..24b1ad6f --- /dev/null +++ b/docker/l1-chain/package.json @@ -0,0 +1,85 @@ +{ + "name": "@fuel-bridge/solidity-contracts", + "version": "1.0.0", + "description": "The Fuel v2 Solidity smart contracts.", + "license": "APACHE-2.0", + "files": [ + "typechain", + "contracts", + "artifacts", + "dist" + ], + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "typings": "dist/index.d.ts", + "main": "dist/index.js", + "scripts": { + "build": "run-s clean compile build:exports", + "build:exports": "tsup", + "clean": "pnpm hardhat clean", + "compile": "pnpm hardhat compile --show-stack-traces", + "coverage": "pnpm run build && pnpm hardhat coverage --temp artifacts --network hardhat", + "check": "pnpm solhint \"contracts/**/*.sol\"", + "node": "pnpm hardhat node --network hardhat --hostname 0.0.0.0", + "start-mining": "pnpm hardhat run --no-compile --network localhost scripts/startAutoMining.ts", + "serve-deployments": "pnpm ts-node scripts/serveDeployments.ts", + "test": "pnpm hardhat test", + "integration-test": "pnpm mocha -b -r ts-node/register 'integration-tests/**/*.ts'", + "node:up": "sh ./scripts/node:up.sh", + "hardhat:test:integration": "DISABLE_GAS_REPORTER=true pnpm hardhat --network mainnetFork test fork-integration-tests/**/*.ts --bail", + "test-no-compile": "pnpm hardhat test --no-compile", + "test-parallel": "pnpx mocha 'test/**/*.ts' --recursive --parallel --require hardhat/register", + "prettier": "prettier --write --plugin=prettier-plugin-solidity 'contracts/**/*.sol'", + "lint": "prettier --list-different --plugin=prettier-plugin-solidity 'contracts/**/*.sol'" + }, + "devDependencies": { + "@fuel-ts/merkle": "^0.21.2", + "@inquirer/prompts": "^5.3.8", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.4", + "@nomicfoundation/hardhat-ethers": "^3.0.5", + "@nomicfoundation/hardhat-network-helpers": "^1.0.10", + "@nomicfoundation/hardhat-verify": "1.1.1", + "@openzeppelin/contracts": "^4.8.3", + "@openzeppelin/contracts-upgradeable": "^4.8.3", + "@openzeppelin/hardhat-upgrades": "^3.0.4", + "@safe-global/api-kit": "^2.4.6", + "@safe-global/protocol-kit": "^4.1.1", + "@safe-global/safe-core-sdk-types": "^5.1.0", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", + "@types/chai": "^4.3.4", + "@types/cors": "2.8.17", + "mocha": "^10.0.0", + "@types/express": "^4.17.14", + "@types/lodash": "^4.14.202", + "@types/mocha": "^10.0.0", + "@types/node": "^18.11.9", + "@typescript-eslint/eslint-plugin": "^5.43.0", + "@typescript-eslint/parser": "^5.43.0", + "axios": "^1.7.7", + "chai": "^4.3.7", + "cors": "2.8.5", + "dotenv": "^16.0.3", + "ethers": "6.13.1", + "express": "^4.18.2", + "fuels": "0.96.1", + "hardhat": "^2.20.1", + "hardhat-deploy": "^0.12.4", + "inquirer": "^10.1.8", + "lodash": "^4.17.21", + "markdownlint": "^0.26.2", + "markdownlint-cli": "^0.32.2", + "node-fetch": "^2.6.6", + "npm-run-all": "^4.1.5", + "prettier-plugin-solidity": "^1.1.3", + "solc": "^0.8.17", + "solhint": "3.3.7", + "solidity-coverage": "^0.8.5", + "ts-generator": "^0.1.1", + "ts-node": "^10.9.1", + "tsup": "^7.2.0", + "typechain": "^8.3.2", + "typescript": "^4.9.3" + } + } + \ No newline at end of file diff --git a/packages/solidity-contracts/package.json b/packages/solidity-contracts/package.json index 70087cf7..41874449 100644 --- a/packages/solidity-contracts/package.json +++ b/packages/solidity-contracts/package.json @@ -21,14 +21,21 @@ "coverage": "pnpm run build && pnpm hardhat coverage --temp artifacts --network hardhat", "check": "pnpm solhint \"contracts/**/*.sol\"", "node": "pnpm hardhat node --network hardhat", + "test:integration": "pnpm mocha -b -r ts-node/register 'integration-tests/**/*.ts'", + "node:up": "sh ./scripts/node:up.sh", "start-mining": "pnpm hardhat run --no-compile --network localhost scripts/startAutoMining.ts", "serve-deployments": "pnpm ts-node scripts/serveDeployments.ts", "test": "pnpm hardhat test", + "upgrade:test:integration": "sh ./scripts/test.sh", "test-no-compile": "pnpm hardhat test --no-compile", "test-parallel": "pnpx mocha 'test/**/*.ts' --recursive --parallel --require hardhat/register", "prettier": "prettier --write --plugin=prettier-plugin-solidity 'contracts/**/*.sol'", "lint": "prettier --list-different --plugin=prettier-plugin-solidity 'contracts/**/*.sol'" }, + "peerDependencies": { + "@fuel-bridge/test-utils": "workspace:*", + "@fuel-bridge/fungible-token": "workspace:*" + }, "devDependencies": { "@fuel-ts/merkle": "^0.21.2", "@inquirer/prompts": "^5.3.8", @@ -54,6 +61,7 @@ "@typescript-eslint/parser": "^5.43.0", "chai": "^4.3.7", "cors": "2.8.5", + "mocha": "^10.0.0", "dotenv": "^16.0.3", "ethers": "6.13.1", "express": "^4.18.2", @@ -76,4 +84,4 @@ "typechain": "^8.3.2", "typescript": "^4.9.3" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc55af5d..94419ef0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -127,6 +127,13 @@ importers: version: link:../solidity-contracts packages/solidity-contracts: + dependencies: + '@fuel-bridge/fungible-token': + specifier: workspace:* + version: link:../fungible-token + '@fuel-bridge/test-utils': + specifier: workspace:* + version: link:../test-utils devDependencies: '@fuel-ts/merkle': specifier: ^0.21.2 @@ -230,6 +237,9 @@ importers: markdownlint-cli: specifier: ^0.32.2 version: 0.32.2 + mocha: + specifier: ^10.0.0 + version: 10.4.0 node-fetch: specifier: ^2.6.6 version: 2.7.0 From 61e3417200a4225b024b1049cc2faf9bdee933b9 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:17:15 +0530 Subject: [PATCH 02/36] feat: add docker setup in contracts package --- docker/l1-chain/Dockerfile | 2 +- .../docker/block-committer/Dockerfile | 21 ++ .../docker/block-committer/block-committer.sh | 54 ++++ .../docker/docker-compose.yml | 99 ++++++ .../docker/envs/fuel_core.env | 1 + .../docker/envs/l1_chain.env | 1 + .../docker/fuel-core/Dockerfile | 55 ++++ .../docker/fuel-core/fuel_core.sh | 71 +++++ .../docker/fuel-core/genesis_coins.json | 299 ++++++++++++++++++ .../docker/l1-chain/Dockerfile | 43 +++ .../docker/l1-chain/l1_chain.sh | 39 +++ .../docker/l1-chain/package.json | 84 +++++ 12 files changed, 768 insertions(+), 1 deletion(-) create mode 100644 packages/solidity-contracts/docker/block-committer/Dockerfile create mode 100644 packages/solidity-contracts/docker/block-committer/block-committer.sh create mode 100644 packages/solidity-contracts/docker/docker-compose.yml create mode 100644 packages/solidity-contracts/docker/envs/fuel_core.env create mode 100644 packages/solidity-contracts/docker/envs/l1_chain.env create mode 100644 packages/solidity-contracts/docker/fuel-core/Dockerfile create mode 100644 packages/solidity-contracts/docker/fuel-core/fuel_core.sh create mode 100644 packages/solidity-contracts/docker/fuel-core/genesis_coins.json create mode 100644 packages/solidity-contracts/docker/l1-chain/Dockerfile create mode 100644 packages/solidity-contracts/docker/l1-chain/l1_chain.sh create mode 100644 packages/solidity-contracts/docker/l1-chain/package.json diff --git a/docker/l1-chain/Dockerfile b/docker/l1-chain/Dockerfile index 7970a8b3..a4828892 100644 --- a/docker/l1-chain/Dockerfile +++ b/docker/l1-chain/Dockerfile @@ -10,7 +10,7 @@ RUN apk --no-cache add git curl RUN npm i -g pnpm # clone the contracts repo -ADD ./packages/solidity-contracts/package.json /l1chain/fuel-v2-contracts/ +ADD docker/l1-chain/package.json /l1chain/fuel-v2-contracts/ # copy over the fuel chain and replace consts values WORKDIR /l1chain/fuel-v2-contracts diff --git a/packages/solidity-contracts/docker/block-committer/Dockerfile b/packages/solidity-contracts/docker/block-committer/Dockerfile new file mode 100644 index 00000000..b9399970 --- /dev/null +++ b/packages/solidity-contracts/docker/block-committer/Dockerfile @@ -0,0 +1,21 @@ +FROM ghcr.io/fuellabs/fuel-block-committer:v0.10.4 + +ARG COMMITER_IP=0.0.0.0 +ARG COMMITER_PORT=8888 + +# dependencies +ENV DEBIAN_FRONTEND=noninteractive +RUN apt update && apt install -y curl jq && rm -rf /var/lib/apt/lists/* + +# copy chain config +WORKDIR /block-committer + +# expose fuel node port +ENV HOST="${COMMITER_IP}" +ENV PORT="${COMMITER_PORT}" + +EXPOSE ${PORT} + +# copy over script and run +COPY ./block-committer.sh . +ENTRYPOINT ["sh", "./block-committer.sh"] diff --git a/packages/solidity-contracts/docker/block-committer/block-committer.sh b/packages/solidity-contracts/docker/block-committer/block-committer.sh new file mode 100644 index 00000000..f2be6988 --- /dev/null +++ b/packages/solidity-contracts/docker/block-committer/block-committer.sh @@ -0,0 +1,54 @@ +#!/bin/sh +set -euo + +RETRIES=${RETRIES:-60} +DELAY=${DELAY:-10} +JSON='{"jsonrpc":"2.0","id":0,"method":"net_version","params":[]}' +HEALTH_URL=${HEALTH_URL:-"http://fuel_core:4001/v1/health"} + +if [ -z "$COMMITTER__ETH__RPC" ]; then + echo "Must specify \$ETHEREUM_RPC." + exit 1 +fi +if [ -z "$COMMITTER__FUEL__GRAPHQL_ENDPOINT" ]; then + echo "Must specify \$FUEL_GRAPHQL_ENDPOINT." + exit 1 +fi + +echo $COMMITTER__FUEL__GRAPHQL_ENDPOINT/health + +# wait for the base layer to be up +echo "Waiting for Fuel Core chain." +curl \ + --fail \ + --show-error \ + --silent \ + --retry-connrefused \ + --retry $RETRIES \ + --retry-delay $DELAY \ + $HEALTH_URL > /dev/null +echo "Connected to Fuel Core chain." + +# get the deployments file from the deployer +echo "Waiting for l1 chain deployment data." +curl \ + --fail \ + --show-error \ + --silent \ + --retry-connrefused \ + --retry-all-errors \ + --retry $RETRIES \ + --retry-delay 5 \ + $DEPLOYMENTS_HTTP \ + -o addresses.json +echo "Got l1 chain deployment data." + +# pull data from deployer dump +export COMMITTER__ETH__STATE_CONTRACT_ADDRESS=$(cat "./addresses.json" | jq -r .FuelChainState) +echo "COMMITTER__ETH__STATE_CONTRACT_ADDRESS: $COMMITTER__ETH__STATE_CONTRACT_ADDRESS" +echo "ETHEREUM_RPC: $COMMITTER__ETH__RPC" +echo "FUEL_GRAPHQL_ENDPOINT: $COMMITTER__FUEL__GRAPHQL_ENDPOINT" + +# start the Block Commiter +echo "Starting block commiter" +exec /root/fuel-block-committer diff --git a/packages/solidity-contracts/docker/docker-compose.yml b/packages/solidity-contracts/docker/docker-compose.yml new file mode 100644 index 00000000..b23c6721 --- /dev/null +++ b/packages/solidity-contracts/docker/docker-compose.yml @@ -0,0 +1,99 @@ +version: '3.4' + +services: + db: + image: postgres:14 + environment: + POSTGRES_USER: username + POSTGRES_PASSWORD: password + POSTGRES_DB: committer_db + healthcheck: + test: ['CMD-SHELL', 'pg_isready -U username -d committer_db'] + interval: 5s + timeout: 5s + retries: 5 + + l1_chain: + image: fueldev/l1chain:${DOCKER_TAG_L1_CHAIN:-latest} + build: + dockerfile: ./docker/l1-chain/Dockerfile + # Use build context of the root directory + # to allow copying solidity-contracts on Dockerfile + context: ../ + env_file: + - ./envs/l1_chain.env + ports: + # expose the service to the host for integration testing + - ${L1_CHAIN_HTTP_PORT:-8545}:9545 + - ${DEPLOYMENTS_PORT:-8080}:8081 + stop_grace_period: 1s + + fuel_core: + image: fueldev/fuelcore:${DOCKER_TAG_FUEL_CORE:-latest} + depends_on: + l1_chain: + condition: service_started + platform: linux/amd64 + build: + context: ./fuel-core/ + env_file: + - ./envs/fuel_core.env + environment: + L1_CHAIN_HTTP: http://l1_chain:9545 + DEPLOYMENTS_HTTP: http://l1_chain:8081/deployments.local.json + RUST_LOG: debug + DEBUG: true + DB_PATH: /db + ports: + # expose the service to the host for integration testing + - ${FUEL_CORE_HTTP_PORT:-4000}:4001 + stop_grace_period: 1s + restart: always + + fuel_block_commiter: + image: ghcr.io/fuellabs/fuel-block-committer:v0.10.4 + platform: linux/amd64 + build: + context: ./block-committer/ + environment: + COMMITTER__ETH__RPC: 'ws://l1_chain:9545/' + COMMITTER__ETH__L1_KEYS__MAIN: 'Private(8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba)' + COMMITTER__ETH__L1_KEYS__BLOB: 'Private(59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d)' + COMMITTER__FUEL__GRAPHQL_ENDPOINT: 'http://fuel_core:4001/graphql' + COMMITTER__FUEL__NUM_BUFFERED_REQUESTS: '5' + COMMITTER__APP__DB__PORT: '5432' + COMMITTER__APP__DB__HOST: 'db' + COMMITTER__APP__DB__USERNAME: 'username' + COMMITTER__APP__DB__PASSWORD: 'password' + COMMITTER__APP__DB__MAX_CONNECTIONS: '10' + COMMITTER__APP__DB__USE_SSL: 'false' + COMMITTER__APP__DB__DATABASE: 'committer_db' + COMMITTER__APP__PORT: '8080' + COMMITTER__APP__HOST: '0.0.0.0' + COMMITTER__APP__BLOCK_CHECK_INTERVAL: '5s' + COMMITTER__APP__TX_FINALIZATION_CHECK_INTERVAL: '5s' + COMMITTER__APP__NUM_BLOCKS_TO_FINALIZE_TX: '3' + COMMITTER__APP__GAS_BUMP_TIMEOUT: '300s' + COMMITTER__APP__TX_MAX_FEE: '4000000000000000' + COMMITTER__APP__SEND_TX_REQUEST_TIMEOUT: '10s' + COMMITTER__APP__BUNDLE__ACCUMULATION_TIMEOUT: '3600s' + COMMITTER__APP__BUNDLE__BLOCKS_TO_ACCUMULATE: '400' + COMMITTER__APP__BUNDLE__OPTIMIZATION_TIMEOUT: '60s' + COMMITTER__APP__BUNDLE__BLOCK_HEIGHT_LOOKBACK: '8500' + COMMITTER__APP__BUNDLE__COMPRESSION_LEVEL: 'level6' + COMMITTER__APP__BUNDLE__OPTIMIZATION_STEP: '100' + COMMITTER__APP__BUNDLE__FRAGMENTS_TO_ACCUMULATE: '3' + COMMITTER__APP__BUNDLE__FRAGMENT_ACCUMULATION_TIMEOUT: '10m' + COMMITTER__APP__BUNDLE__NEW_BUNDLE_CHECK_INTERVAL: '3s' + DEPLOYMENTS_HTTP: http://l1_chain:8081/deployments.local.json + ports: + # expose the service to the host for integration testing + - ${COMMITTER_HTTP_PORT:-8888}:8888 + depends_on: + db: + condition: service_healthy + l1_chain: + condition: service_started + fuel_core: + condition: service_started + restart: always diff --git a/packages/solidity-contracts/docker/envs/fuel_core.env b/packages/solidity-contracts/docker/envs/fuel_core.env new file mode 100644 index 00000000..7b0bf02d --- /dev/null +++ b/packages/solidity-contracts/docker/envs/fuel_core.env @@ -0,0 +1 @@ +CONSENSUS_KEY_SECRET="0xa449b1ffee0e2205fa924c6740cc48b3b473aa28587df6dab12abc245d1f5298" \ No newline at end of file diff --git a/packages/solidity-contracts/docker/envs/l1_chain.env b/packages/solidity-contracts/docker/envs/l1_chain.env new file mode 100644 index 00000000..efddf6ab --- /dev/null +++ b/packages/solidity-contracts/docker/envs/l1_chain.env @@ -0,0 +1 @@ +TENDERLY_RPC_URL= \ No newline at end of file diff --git a/packages/solidity-contracts/docker/fuel-core/Dockerfile b/packages/solidity-contracts/docker/fuel-core/Dockerfile new file mode 100644 index 00000000..3d8b69db --- /dev/null +++ b/packages/solidity-contracts/docker/fuel-core/Dockerfile @@ -0,0 +1,55 @@ +# IMPORTANT! +# Make sure to check: +# https://github.com/FuelLabs/chain-configuration/tree/master/upgradelog/ignition-testnet +# and apply the latest state_transition_function and consensus_parameter +# when upgrading fuel-core +FROM ghcr.io/fuellabs/fuel-core:v0.40.0 + +ARG FUEL_IP=0.0.0.0 +ARG FUEL_PORT=4001 +ARG CONSENSUS_KEY_SECRET="" + +# dependencies +ENV DEBIAN_FRONTEND=noninteractive +RUN apt update && apt install -y git curl jq && rm -rf /var/lib/apt/lists/* + +# copy chain config +WORKDIR /fuel + +COPY ./genesis_coins.json . + +RUN git clone \ + https://github.com/FuelLabs/chain-configuration.git \ + /chain-configuration + +# Anchor the chain configuration to a specific commit to avoid CI breaking +RUN cd /chain-configuration && git checkout 8e4f7b52d7112f929a7cd95b988dfebfd10e87ec + +# Copy the base local configuration +RUN cp -R /chain-configuration/local/* ./ + +# Copy the devnet consensus parameters and state transition bytecode +RUN cp /chain-configuration/upgradelog/ignition-devnet/consensus_parameters/14.json \ + ./latest_consensus_parameters.json +RUN cp /chain-configuration/upgradelog/ignition-devnet/state_transition_function/16.wasm \ + ./state_transition_bytecode.wasm + +# update local state_config with custom genesis coins config +RUN jq '.coins = input' \ + state_config.json genesis_coins.json > tmp.json \ + && mv tmp.json state_config.json + +# update local state_config with testnet consensus parameters +RUN jq '.consensus_parameters = input' \ + state_config.json latest_consensus_parameters.json > tmp.json \ + && mv tmp.json state_config.json + +# expose fuel node port +ENV FUEL_IP="${FUEL_IP}" +ENV FUEL_PORT="${FUEL_PORT}" +ENV CONSENSUS_KEY_SECRET="${CONSENSUS_KEY_SECRET}" +EXPOSE ${FUEL_PORT} + +# copy over script and run +COPY ./fuel_core.sh . +CMD ["sh", "./fuel_core.sh"] \ No newline at end of file diff --git a/packages/solidity-contracts/docker/fuel-core/fuel_core.sh b/packages/solidity-contracts/docker/fuel-core/fuel_core.sh new file mode 100644 index 00000000..a1c2c3a3 --- /dev/null +++ b/packages/solidity-contracts/docker/fuel-core/fuel_core.sh @@ -0,0 +1,71 @@ +#!/bin/sh +set -euo + +#!/bin/sh +set -euo + +RETRIES=${RETRIES:-90} +DA_COMPRESSION=${DA_COMPRESSION:-"3600sec"} +GRAPHQL_COMPLEXITY=${GRAPHQL_COMPLEXITY:-500000} +JSON='{"jsonrpc":"2.0","id":0,"method":"net_version","params":[]}' +# FUEL_DB_PATH=./mnt/db/ + +if [ -z "$L1_CHAIN_HTTP" ]; then + echo "Must specify \$L1_CHAIN_HTTP." + exit 1 +fi + +# wait for the base layer to be up +echo "Waiting for l1 chain." +curl \ + --fail \ + --show-error \ + --silent \ + -H "Content-Type: application/json" \ + --retry-connrefused \ + --retry $RETRIES \ + --retry-delay 1 \ + -d $JSON \ + $L1_CHAIN_HTTP > /dev/null +echo "Connected to l1 chain." + +# get the deployments file from the deployer +echo "Waiting for l1 chain deployment data." +curl \ + --fail \ + --show-error \ + --silent \ + --retry-connrefused \ + --retry-all-errors \ + --retry $RETRIES \ + --retry-delay 5 \ + $DEPLOYMENTS_HTTP \ + -o addresses.json +echo "Got l1 chain deployment data." + +# pull data from deployer dump +export FUEL_MESSAGE_PORTAL_CONTRACT_ADDRESS=$(cat "./addresses.json" | jq -r .FuelMessagePortal) +# export FUEL_MESSAGE_PORTAL_CONTRACT_ADDRESS=$(jq -r '.address' /l1chain/fuel-v2-contracts/deployments/localhost/FuelMessagePortal.json) +echo "FUEL_MESSAGE_PORTAL_CONTRACT_ADDRESS: $FUEL_MESSAGE_PORTAL_CONTRACT_ADDRESS" +echo "L1_CHAIN_HTTP: $L1_CHAIN_HTTP" + +# start the Fuel client +#--db-path ${FUEL_DB_PATH} +echo "Starting fuel node." +exec /root/fuel-core run \ + --ip $FUEL_IP \ + --port $FUEL_PORT \ + --utxo-validation \ + --vm-backtrace \ + --enable-relayer \ + --relayer $L1_CHAIN_HTTP \ + --relayer-v2-listening-contracts $FUEL_MESSAGE_PORTAL_CONTRACT_ADDRESS \ + --poa-interval-period=1s \ + --relayer-da-deploy-height=21371952 \ + --debug \ + --da-compression $DA_COMPRESSION \ + --graphql-max-complexity $GRAPHQL_COMPLEXITY \ + --min-gas-price 0 \ + --tx-ttl-check-interval 10sec \ + --tx-pool-ttl 30sec \ + --snapshot ./ diff --git a/packages/solidity-contracts/docker/fuel-core/genesis_coins.json b/packages/solidity-contracts/docker/fuel-core/genesis_coins.json new file mode 100644 index 00000000..fd78763e --- /dev/null +++ b/packages/solidity-contracts/docker/fuel-core/genesis_coins.json @@ -0,0 +1,299 @@ +[ + { + "owner": "0xc8e615a4089466174459ef19cfd257d2e17adfabff3b8f219dbb5fb4eca87c50", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000001", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x92dffc873b56f219329ed03bb69bebe8c3d8b041088574882f7a6404f02e2f28", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000002", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x456bdaffaf74fe03521754ac445d148033c0c6acf7d593132c43f92fdbc7324c", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000003", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x639880ece7753a32e09164d14dad7436c57737e567f18b98f6ee30fec6b247ec", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000004", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0xfd8c520ef8caff0ad3289aa64acecd4ef86ac8f643fd9b76bf2d163a86a66716", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000005", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x8247104854dd733cb475901d55047f57cb3c8cafe3a9f7233de3325b8bf56a5c", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000006", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x53de37ae51fcfecb17ee3589f68904ac75bf5ec109edeb1065ccb63145287da6", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000007", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x17f4bef51f63f0c28af20d4223a3bf5cf1735a3b7ec52b4fcfbdbb5f30582a6b", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000008", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x95725e9083d8ed1cb52dcf6429d0cfce00cc375eeac5b620b5c36f5b1e734b31", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000009", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x08792a75d5714165aa117fd75450f9efcfb7124d034ef271f2919e4cc287046c", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x000000000000000000000000000000000000000000000000000000000000000a", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x6a16fba49dbdf7689c52b7a22951a54dc164076d27bdc6042b5d8377d68ca10b", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x000000000000000000000000000000000000000000000000000000000000000b", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x6494a55c0e3da212fdd0515507d00ae99151c7966e1448079c76bc447b577254", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x000000000000000000000000000000000000000000000000000000000000000c", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0xe0e1c94a9f9e02454772813ba6a6261b5228db1fabde3a68b23c0e9744ce22fc", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x000000000000000000000000000000000000000000000000000000000000000d", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x425f3e91aedff36e72ae60a8a1d328e625d66d39fcc98d5fcd1ba7df65a9f878", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x000000000000000000000000000000000000000000000000000000000000000e", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0xe2242f2e4971c34bc6fe5e1c0043b1aba717cb6a51f31f0dc0708cca73df905a", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x000000000000000000000000000000000000000000000000000000000000000f", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x6aa67cb316f329111dc708bb766360f5026a614edb11882e14d4cc04f26e0a08", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000010", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0xef5c2b712c4f3a10a37d6371cab2b03a6afd12e4ffcc9567d45d8c4b6e217e5c", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000011", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0xa82f66642de54993b32036eef7914f2dbaa217aa3209707b64d0b90187456a1f", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000012", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x9c9c1f3346b54fe6cb379fa27f338464592515fd865656089c4a23ac34390e6f", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000013", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "owner": "0x8a332bc33f4c10ad36392a9ca958a5ddf56081cc764f61613ea119e42ced6ac5", + "amount": 1000000000000, + "asset_id": "0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07", + "tx_id": "0x0000000000000000000000000000000000000000000000000000000000000014", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0 + }, + { + "tx_id": "0000000000000000000000000000000000000000000000000000000000000015", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "6b63804cfbf9856e68e5b6e7aef238dc8311ec55bec04df774003a2c96e0418e", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "0000000000000000000000000000000000000000000000000000000000000016", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "54944e5b8189827e470e5a8bacfc6c3667397dc4e1eef7ef3519d16d6d6c6610", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "0000000000000000000000000000000000000000000000000000000000000017", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "e10f526b192593793b7a1559a391445faba82a1d669e3eb2dcd17f9c121b24b1", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "0000000000000000000000000000000000000000000000000000000000000018", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "577e424ee53a16e6a85291feabc8443862495f74ac39a706d2dd0b9fc16955eb", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "0000000000000000000000000000000000000000000000000000000000000019", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "c36be0e14d3eaf5d8d233e0f4a40b3b4e48427d25f84c460d2b03b242a38479e", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "000000000000000000000000000000000000000000000000000000000000002a", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "a1184d77d0d08a064e03b2bd9f50863e88faddea4693a05ca1ee9b1732ea99b7", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "000000000000000000000000000000000000000000000000000000000000002b", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "b5566df884bee4e458151c2fe4082c8af38095cc442c61e0dc83a371d70d88fd", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "000000000000000000000000000000000000000000000000000000000000002c", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "9da7247e1d63d30d69f136f0f8654ee8340362c785b50f0a60513c7edbf5bb7c", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "000000000000000000000000000000000000000000000000000000000000002d", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "4b2ca966aad1a9d66994731db5138933cf61679107c3cde2a10d9594e47c084e", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "000000000000000000000000000000000000000000000000000000000000002e", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "26183fbe7375045250865947695dfc12500dcc43efb9102b4e8c4d3c20009dcb", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "000000000000000000000000000000000000000000000000000000000000002f", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "81f3a10b61828580d06cc4c7b0ed8f59b9fb618be856c55d33decd95489a1e23", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "0000000000000000000000000000000000000000000000000000000000000030", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "587aa0482482efea0234752d1ad9a9c438d1f34d2859b8bef2d56a432cb68e33", + "amount": 1152921504606846976, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + }, + { + "tx_id": "0000000000000000000000000000000000000000000000000000000000000031", + "output_index": 0, + "tx_pointer_block_height": 0, + "tx_pointer_tx_idx": 0, + "owner": "53a9c6a74bee79c5e04115a007984f4bddaafed75f512f68766c6ed59d0aedec", + "amount": 1125899906842624, + "asset_id": "f8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07" + } +] diff --git a/packages/solidity-contracts/docker/l1-chain/Dockerfile b/packages/solidity-contracts/docker/l1-chain/Dockerfile new file mode 100644 index 00000000..5e2f20f5 --- /dev/null +++ b/packages/solidity-contracts/docker/l1-chain/Dockerfile @@ -0,0 +1,43 @@ +FROM node:20-alpine AS BUILD_IMAGE + +# dependencies +RUN apk --no-cache add git curl +RUN npm i -g pnpm + +ARG L1_IP=0.0.0.0 +ARG L1_PORT=9545 +ARG SERVE_PORT=8081 + +WORKDIR /l1chain/fuel-v2-contracts + +# clone the contracts repo +COPY docker/l1-chain/package.json /l1chain/fuel-v2-contracts/ + +# build the ethereum contracts and environment +RUN pnpm install +COPY contracts/test/PlaceHolder.sol /l1chain/fuel-v2-contracts/contracts/test/PlaceHolder.sol +COPY hardhat.config.ts /l1chain/fuel-v2-contracts/ +COPY scripts/ /l1chain/fuel-v2-contracts/scripts/ +RUN pnpm compile + +# replace the fuel chain consts values and change contract code +COPY contracts/ /l1chain/fuel-v2-contracts/contracts/ +COPY deploy/ /l1chain/fuel-v2-contracts/deploy/ +COPY deployments/ /l1chain/fuel-v2-contracts/deployments/ +COPY protocol/ /l1chain/fuel-v2-contracts/protocol/ + + +# remove build dependencies +# RUN pnpm prune --prod +RUN pnpm compile + + +ENV L1_IP="${L1_IP}" +ENV L1_PORT="${L1_PORT}" +ENV SERVE_PORT="${SERVE_PORT}" +EXPOSE ${L1_PORT} +EXPOSE ${SERVE_PORT} + +# copy over script and run +COPY ./docker/l1-chain/l1_chain.sh /l1chain/l1_chain.sh +CMD ["sh", "/l1chain/l1_chain.sh"] diff --git a/packages/solidity-contracts/docker/l1-chain/l1_chain.sh b/packages/solidity-contracts/docker/l1-chain/l1_chain.sh new file mode 100644 index 00000000..e0df10bc --- /dev/null +++ b/packages/solidity-contracts/docker/l1-chain/l1_chain.sh @@ -0,0 +1,39 @@ +#!/bin/sh +set -euo + +RETRIES=${RETRIES:-120} +JSON='{"jsonrpc":"2.0","id":0,"method":"net_version","params":[]}' + +L1_CHAIN_HTTP="http://127.0.0.1:$L1_PORT" + +echo "Starting l1 chain." +pnpm hardhat node --network hardhat --port $L1_PORT --hostname $L1_IP & + +# wait for the base layer to be up +echo "Waiting for l1 chain." +curl \ + --fail \ + --show-error \ + --silent \ + -H "Content-Type: application/json" \ + --retry-connrefused \ + --retry $RETRIES \ + --retry-delay 1 \ + -d $JSON \ + $L1_CHAIN_HTTP > /dev/null + +echo "Connected to l1 chain." + +export LOCALHOST_HTTP=$L1_CHAIN_HTTP + +# Start auto mining +# We use a separate process to start auto mining because +# the deployment of contracts can fail if the chain is +# mining at the same time. +RPC_URL=$L1_CHAIN_HTTP pnpm run start-mining + +# serve contract deployment data +echo "Starting deployment data server." +pnpm run serve-deployments + + diff --git a/packages/solidity-contracts/docker/l1-chain/package.json b/packages/solidity-contracts/docker/l1-chain/package.json new file mode 100644 index 00000000..8d7842f8 --- /dev/null +++ b/packages/solidity-contracts/docker/l1-chain/package.json @@ -0,0 +1,84 @@ +{ + "name": "@fuel-bridge/solidity-contracts", + "version": "1.0.0", + "description": "The Fuel v2 Solidity smart contracts.", + "license": "APACHE-2.0", + "files": [ + "typechain", + "contracts", + "artifacts", + "dist" + ], + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "typings": "dist/index.d.ts", + "main": "dist/index.js", + "scripts": { + "build": "run-s clean compile build:exports", + "build:exports": "tsup", + "clean": "pnpm hardhat clean", + "compile": "pnpm hardhat compile --show-stack-traces", + "coverage": "pnpm run build && pnpm hardhat coverage --temp artifacts --network hardhat", + "check": "pnpm solhint \"contracts/**/*.sol\"", + "node": "pnpm hardhat node --network hardhat --hostname 0.0.0.0", + "start-mining": "pnpm hardhat run --no-compile --network localhost scripts/startAutoMining.ts", + "serve-deployments": "pnpm ts-node scripts/serveDeployments.ts", + "test": "pnpm hardhat test", + "integration-test": "pnpm mocha -b -r ts-node/register 'integration-tests/**/*.ts'", + "node:up": "sh ./scripts/node:up.sh", + "hardhat:test:integration": "DISABLE_GAS_REPORTER=true pnpm hardhat --network mainnetFork test fork-integration-tests/**/*.ts --bail", + "test-no-compile": "pnpm hardhat test --no-compile", + "test-parallel": "pnpx mocha 'test/**/*.ts' --recursive --parallel --require hardhat/register", + "prettier": "prettier --write --plugin=prettier-plugin-solidity 'contracts/**/*.sol'", + "lint": "prettier --list-different --plugin=prettier-plugin-solidity 'contracts/**/*.sol'" + }, + "devDependencies": { + "@fuel-ts/merkle": "^0.21.2", + "@inquirer/prompts": "^5.3.8", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.4", + "@nomicfoundation/hardhat-ethers": "^3.0.5", + "@nomicfoundation/hardhat-network-helpers": "^1.0.10", + "@nomicfoundation/hardhat-verify": "1.1.1", + "@openzeppelin/contracts": "^4.8.3", + "@openzeppelin/contracts-upgradeable": "^4.8.3", + "@openzeppelin/hardhat-upgrades": "^3.0.4", + "@safe-global/api-kit": "^2.4.6", + "@safe-global/protocol-kit": "^4.1.1", + "@safe-global/safe-core-sdk-types": "^5.1.0", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", + "@types/chai": "^4.3.4", + "@types/cors": "2.8.17", + "mocha": "^10.0.0", + "@types/express": "^4.17.14", + "@types/lodash": "^4.14.202", + "@types/mocha": "^10.0.0", + "@types/node": "^18.11.9", + "@typescript-eslint/eslint-plugin": "^5.43.0", + "@typescript-eslint/parser": "^5.43.0", + "axios": "^1.7.7", + "chai": "^4.3.7", + "cors": "2.8.5", + "dotenv": "^16.0.3", + "ethers": "6.13.1", + "express": "^4.18.2", + "fuels": "0.96.1", + "hardhat": "^2.20.1", + "hardhat-deploy": "^0.12.4", + "inquirer": "^10.1.8", + "lodash": "^4.17.21", + "markdownlint": "^0.26.2", + "markdownlint-cli": "^0.32.2", + "node-fetch": "^2.6.6", + "npm-run-all": "^4.1.5", + "prettier-plugin-solidity": "^1.1.3", + "solc": "^0.8.17", + "solhint": "3.3.7", + "solidity-coverage": "^0.8.5", + "ts-generator": "^0.1.1", + "ts-node": "^10.9.1", + "tsup": "^7.2.0", + "typechain": "^8.3.2", + "typescript": "^4.9.3" + } +} From a51dc48b0df0479060746cc054e41ebfbde53de5 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:18:09 +0530 Subject: [PATCH 03/36] chore: add test placeholder contract --- packages/solidity-contracts/contracts/test/PlaceHolder.sol | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/solidity-contracts/contracts/test/PlaceHolder.sol diff --git a/packages/solidity-contracts/contracts/test/PlaceHolder.sol b/packages/solidity-contracts/contracts/test/PlaceHolder.sol new file mode 100644 index 00000000..e18ceb0f --- /dev/null +++ b/packages/solidity-contracts/contracts/test/PlaceHolder.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; +/// @dev The only purpose of this contract is to be copied during the Dockerfile build +/// so that hardhat downloads the compiler and it gets cached +contract PlaceHolder {} \ No newline at end of file From a32de3fb3079b00f41e1869aff9790d7f72a1d41 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:19:33 +0530 Subject: [PATCH 04/36] feat: add upgrade scripts --- .../deploy/hardhat/001.chain_state.ts | 4 + .../hardhat/002.fuel_message_portal_v3.ts | 4 + .../deploy/hardhat/003.erc20_gateway_v4.ts | 4 + .../hardhat/005.register_block_committer.ts | 17 +-- .../deploy/hardhat/006._erc721_gateway_v3.ts | 26 ++++- .../deploy/hardhat/007.set_asset_issuer_id.ts | 4 + .../008.set_canonical_token_bytecode.ts | 1 - .../deploy/hardhat/009.chain_state_upgrade.ts | 101 ++++++++++++++++++ .../deploy/hardhat/010.portal_upgrade.ts | 86 +++++++++++++++ .../deploy/hardhat/011.gateway_upgrade.ts | 97 +++++++++++++++++ .../hardhat/999.serve_deployment_file.ts | 79 ++++++++++++-- 11 files changed, 406 insertions(+), 17 deletions(-) create mode 100644 packages/solidity-contracts/deploy/hardhat/009.chain_state_upgrade.ts create mode 100644 packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts create mode 100644 packages/solidity-contracts/deploy/hardhat/011.gateway_upgrade.ts diff --git a/packages/solidity-contracts/deploy/hardhat/001.chain_state.ts b/packages/solidity-contracts/deploy/hardhat/001.chain_state.ts index 1d9f0e2d..30b4b275 100644 --- a/packages/solidity-contracts/deploy/hardhat/001.chain_state.ts +++ b/packages/solidity-contracts/deploy/hardhat/001.chain_state.ts @@ -13,6 +13,10 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { upgrades: { deployProxy, erc1967 }, deployments: { save }, } = hre; + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + if (isForking) return; + const [deployer] = await ethers.getSigners(); const contract = await deployProxy(new FuelChainState(deployer), [], { diff --git a/packages/solidity-contracts/deploy/hardhat/002.fuel_message_portal_v3.ts b/packages/solidity-contracts/deploy/hardhat/002.fuel_message_portal_v3.ts index 225aaf25..5468571c 100644 --- a/packages/solidity-contracts/deploy/hardhat/002.fuel_message_portal_v3.ts +++ b/packages/solidity-contracts/deploy/hardhat/002.fuel_message_portal_v3.ts @@ -14,6 +14,10 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { upgrades: { deployProxy, erc1967 }, deployments: { get, save }, } = hre; + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + if (isForking) return; + const [deployer] = await ethers.getSigners(); const { address: fuelChainState } = await get('FuelChainState'); diff --git a/packages/solidity-contracts/deploy/hardhat/003.erc20_gateway_v4.ts b/packages/solidity-contracts/deploy/hardhat/003.erc20_gateway_v4.ts index bef7f203..2f117733 100644 --- a/packages/solidity-contracts/deploy/hardhat/003.erc20_gateway_v4.ts +++ b/packages/solidity-contracts/deploy/hardhat/003.erc20_gateway_v4.ts @@ -9,6 +9,10 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { upgrades: { deployProxy, erc1967 }, deployments: { get, save }, } = hre; + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + if (isForking) return; + const [deployer] = await ethers.getSigners(); const fuelMessagePortal = await get('FuelMessagePortal'); diff --git a/packages/solidity-contracts/deploy/hardhat/005.register_block_committer.ts b/packages/solidity-contracts/deploy/hardhat/005.register_block_committer.ts index f0fa19ab..9acd6bbe 100644 --- a/packages/solidity-contracts/deploy/hardhat/005.register_block_committer.ts +++ b/packages/solidity-contracts/deploy/hardhat/005.register_block_committer.ts @@ -7,16 +7,21 @@ const COMMITTER_ADDRESS = '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers, deployments } = hre; + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + const [deployer] = await ethers.getSigners(); - const { address } = await deployments.get('FuelChainState'); + if (!isForking) { + const { address } = await deployments.get('FuelChainState'); - const fuelChainState = FuelChainState__factory.connect(address, deployer); - const COMMITTER_ROLE = await fuelChainState.COMMITTER_ROLE(); + const fuelChainState = FuelChainState__factory.connect(address, deployer); + const COMMITTER_ROLE = await fuelChainState.COMMITTER_ROLE(); - await fuelChainState - .grantRole(COMMITTER_ROLE, COMMITTER_ADDRESS) - .then((tx) => tx.wait()); + await fuelChainState + .grantRole(COMMITTER_ROLE, COMMITTER_ADDRESS) + .then((tx) => tx.wait()); + } console.log('Granted role COMMITTER_ROLE to', COMMITTER_ADDRESS); }; diff --git a/packages/solidity-contracts/deploy/hardhat/006._erc721_gateway_v3.ts b/packages/solidity-contracts/deploy/hardhat/006._erc721_gateway_v3.ts index 3f4734bf..69129a74 100644 --- a/packages/solidity-contracts/deploy/hardhat/006._erc721_gateway_v3.ts +++ b/packages/solidity-contracts/deploy/hardhat/006._erc721_gateway_v3.ts @@ -1,5 +1,7 @@ +import fs from 'fs'; import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import type { DeployFunction } from 'hardhat-deploy/dist/types'; +import path from 'path'; import { FuelERC721GatewayV2__factory as FuelERC721GatewayV2 } from '../../typechain'; @@ -9,13 +11,33 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { upgrades: { deployProxy, erc1967 }, deployments: { get, save }, } = hre; + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + const [deployer] = await ethers.getSigners(); - const fuelMessagePortal = await get('FuelMessagePortal'); + let portlAddress; + if (isForking) { + const deploymentPath = path.join( + __dirname, + '..', + '..', + '/', + 'deployments', + 'mainnet', + 'FuelMessagePortal.json' + ); + + const deployment = JSON.parse(fs.readFileSync(deploymentPath, 'utf8')); + portlAddress = deployment.address; + } else { + const fuelMessagePortal = await get('FuelMessagePortal'); + portlAddress = fuelMessagePortal.address; + } const contract = await deployProxy( new FuelERC721GatewayV2(deployer), - [fuelMessagePortal.address], + [portlAddress], { initializer: 'initialize', } diff --git a/packages/solidity-contracts/deploy/hardhat/007.set_asset_issuer_id.ts b/packages/solidity-contracts/deploy/hardhat/007.set_asset_issuer_id.ts index 025d7345..f689131a 100644 --- a/packages/solidity-contracts/deploy/hardhat/007.set_asset_issuer_id.ts +++ b/packages/solidity-contracts/deploy/hardhat/007.set_asset_issuer_id.ts @@ -16,6 +16,10 @@ const ASSET_ISSUER_ID = const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { ethers, deployments } = hre; + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + if (isForking) return; + const [deployer] = await ethers.getSigners(); await deployments.execute( diff --git a/packages/solidity-contracts/deploy/hardhat/008.set_canonical_token_bytecode.ts b/packages/solidity-contracts/deploy/hardhat/008.set_canonical_token_bytecode.ts index f7ec8ccb..698cf33d 100644 --- a/packages/solidity-contracts/deploy/hardhat/008.set_canonical_token_bytecode.ts +++ b/packages/solidity-contracts/deploy/hardhat/008.set_canonical_token_bytecode.ts @@ -1,6 +1,5 @@ import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import type { DeployFunction } from 'hardhat-deploy/dist/types'; - import { USDT_ADDRESS, USDC_ADDRESS, diff --git a/packages/solidity-contracts/deploy/hardhat/009.chain_state_upgrade.ts b/packages/solidity-contracts/deploy/hardhat/009.chain_state_upgrade.ts new file mode 100644 index 00000000..48fdf219 --- /dev/null +++ b/packages/solidity-contracts/deploy/hardhat/009.chain_state_upgrade.ts @@ -0,0 +1,101 @@ +import fs from 'fs'; +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; +import path from 'path'; + +import { FuelChainState__factory } from '../../typechain'; + +const BLOCKS_PER_COMMIT_INTERVAL = 30; +const TIME_TO_FINALIZE = 5; +const COMMIT_COOLDOWN = TIME_TO_FINALIZE; + +const ADMIN = '0x32da601374b38154f05904B16F44A1911Aa6f314'; +let COMMITTER_ADDRESS = '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { erc1967 }, + } = hre; + + const [deployer] = await ethers.getSigners(); + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + let address; + + if (isForking) { + const deploymentPath = path.join( + __dirname, + '..', + '..', + '/', + 'deployments', + 'mainnet', + 'FuelChainState.json' + ); + + const deployment = JSON.parse(fs.readFileSync(deploymentPath, 'utf8')); + address = deployment.address; + + const chainState = FuelChainState__factory.connect(address, deployer); + + const factory = await hre.ethers.getContractFactory('FuelChainState'); + + const newImplementation = await factory.deploy( + TIME_TO_FINALIZE, + BLOCKS_PER_COMMIT_INTERVAL, + COMMIT_COOLDOWN + ); + + const newImplementationAddress = await newImplementation.getAddress(); + + let txData = chainState.interface.encodeFunctionData('upgradeTo', [ + newImplementationAddress, + ]); + + await deployer.sendTransaction({ + to: ADMIN, + value: ethers.parseEther('100'), + }); + + const impersonatedSigner = await ethers.getImpersonatedSigner(ADMIN); + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + const COMMITTER_ROLE = await chainState.COMMITTER_ROLE(); + + txData = await chainState.interface.encodeFunctionData('grantRole', [ + COMMITTER_ROLE, + COMMITTER_ADDRESS, + ]); + + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + COMMITTER_ADDRESS = '0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65'; + + txData = await chainState.interface.encodeFunctionData('grantRole', [ + COMMITTER_ROLE, + COMMITTER_ADDRESS, + ]); + + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Upgraded FuelChainState to', implementation); + + return true; + } +}; + +func.tags = ['upgrade_chain_state']; +func.id = 'upgrade_chain_state'; +export default func; diff --git a/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts b/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts new file mode 100644 index 00000000..14682a6a --- /dev/null +++ b/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts @@ -0,0 +1,86 @@ +import { MaxUint256 } from 'ethers'; +import fs from 'fs'; +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; +import path from 'path'; + +import { FuelMessagePortalV3__factory as FuelMessagePortal } from '../../typechain'; + +const RATE_LIMIT_DURATION = 3600 * 24 * 7; + +const ADMIN = '0x32da601374b38154f05904B16F44A1911Aa6f314'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { erc1967 }, + } = hre; + + const [deployer] = await ethers.getSigners(); + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + let address; + + if (isForking) { + const deploymentPath = path.join( + __dirname, + '..', + '..', + '/', + 'deployments', + 'mainnet', + 'FuelMessagePortal.json' + ); + + const deployment = JSON.parse(fs.readFileSync(deploymentPath, 'utf8')); + address = deployment.address; + + const portal = FuelMessagePortal.connect(address, deployer); + + const SET_RATE_LIMITER_ROLE = await portal.SET_RATE_LIMITER_ROLE(); + + const factory = await hre.ethers.getContractFactory('FuelMessagePortalV3'); + + const newImplementation = await factory.deploy( + MaxUint256, + RATE_LIMIT_DURATION + ); + + const newImplementationAddress = await newImplementation.getAddress(); + + let txData = portal.interface.encodeFunctionData('upgradeTo', [ + newImplementationAddress, + ]); + + await deployer.sendTransaction({ + to: ADMIN, + value: ethers.parseEther('100'), + }); + + const impersonatedSigner = await ethers.getImpersonatedSigner(ADMIN); + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + txData = await portal.interface.encodeFunctionData('grantRole', [ + SET_RATE_LIMITER_ROLE, + await deployer.getAddress(), + ]); + + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Upgraded FuelMessagePortal to', implementation); + + return true; + } +}; + +func.tags = ['upgrade_portal']; +func.id = 'upgrade_portal'; +export default func; diff --git a/packages/solidity-contracts/deploy/hardhat/011.gateway_upgrade.ts b/packages/solidity-contracts/deploy/hardhat/011.gateway_upgrade.ts new file mode 100644 index 00000000..9b6e0d82 --- /dev/null +++ b/packages/solidity-contracts/deploy/hardhat/011.gateway_upgrade.ts @@ -0,0 +1,97 @@ +import fs from 'fs'; +import type { HardhatRuntimeEnvironment } from 'hardhat/types'; +import type { DeployFunction } from 'hardhat-deploy/dist/types'; +import path from 'path'; + +import { FuelERC20GatewayV4__factory } from '../../typechain'; + +const ADMIN = '0x32da601374b38154f05904B16F44A1911Aa6f314'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { + ethers, + upgrades: { erc1967 }, + } = hre; + + const [deployer] = await ethers.getSigners(); + + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; + let address; + + if (isForking) { + const deploymentPath = path.join( + __dirname, + '..', + '..', + '/', + 'deployments', + 'mainnet', + 'FuelERC20GatewayV4.json' + ); + + const deployment = JSON.parse(fs.readFileSync(deploymentPath, 'utf8')); + address = deployment.address; + + const portal = FuelERC20GatewayV4__factory.connect(address, deployer); + + const ADMIN_ROLE = await portal.DEFAULT_ADMIN_ROLE(); + const SET_RATE_LIMITER_ROLE = await portal.SET_RATE_LIMITER_ROLE(); + + const factory = await hre.ethers.getContractFactory('FuelERC20GatewayV4'); + + const newImplementation = await factory.deploy(); + + const newImplementationAddress = await newImplementation.getAddress(); + + let txData = portal.interface.encodeFunctionData('upgradeTo', [ + newImplementationAddress, + ]); + + await deployer.sendTransaction({ + to: ADMIN, + value: ethers.parseEther('100'), + }); + + const impersonatedSigner = await ethers.getImpersonatedSigner(ADMIN); + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + txData = await portal.interface.encodeFunctionData('grantRole', [ + ADMIN_ROLE, + await deployer.getAddress(), + ]); + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + txData = await portal.interface.encodeFunctionData('grantRole', [ + SET_RATE_LIMITER_ROLE, + await deployer.getAddress(), + ]); + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + txData = await portal.interface.encodeFunctionData('requireWhitelist', [ + false, + ]); + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + const implementation = await erc1967.getImplementationAddress(address); + + console.log('Upgraded FuelGateway to', implementation); + + return true; + } +}; + +func.tags = ['upgrade_gateway']; +func.id = 'upgrade_gateway'; +export default func; diff --git a/packages/solidity-contracts/deploy/hardhat/999.serve_deployment_file.ts b/packages/solidity-contracts/deploy/hardhat/999.serve_deployment_file.ts index 9900c7e0..79b4a47b 100644 --- a/packages/solidity-contracts/deploy/hardhat/999.serve_deployment_file.ts +++ b/packages/solidity-contracts/deploy/hardhat/999.serve_deployment_file.ts @@ -1,18 +1,79 @@ -import { promises as fs } from 'fs'; +import fs from 'fs'; +import { writeFile } from 'fs'; import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import type { DeployFunction } from 'hardhat-deploy/dist/types'; +import path from 'path'; +import { promisify } from 'util'; import { FuelChainState__factory } from '../../typechain'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, ethers } = hre; - const allDeployments = await deployments.all(); + + let address: any; + const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; const deploymentsFile: { [name: string]: string } = {}; - for (const key of Object.keys(allDeployments)) { - deploymentsFile[key] = allDeployments[key].address; + + if (isForking) { + let deploymentDir = path.join( + __dirname, + '..', + '..', + '/', + 'deployments', + 'mainnet' + ); + + fs.readdirSync(deploymentDir) + .filter((file) => path.extname(file) === '.json') + .forEach((file) => { + const filePath = path.join(deploymentDir, file); + try { + const deployment = JSON.parse(fs.readFileSync(filePath, 'utf8')); + // Use filename (without .json) as the key + const contractName = path.basename(file, '.json'); + deploymentsFile[contractName] = deployment.address; + } catch (error) { + console.error(`Error reading deployment file ${file}:`, error); + } + }); + + deploymentDir = path.join( + __dirname, + '..', + '..', + '/', + 'deployments', + 'localhost', + 'FuelERC721Gateway.json' + ); + + const deployment = JSON.parse(fs.readFileSync(deploymentDir, 'utf8')); + deploymentsFile['FuelERC721Gateway'] = deployment.address; + + deploymentDir = path.join( + __dirname, + '..', + '..', + '/', + 'deployments', + 'mainnet', + 'FuelChainState.json' + ); + + const chainStateDeployment = JSON.parse( + fs.readFileSync(deploymentDir, 'utf8') + ); + address = chainStateDeployment.address; + } else { + const allDeployments = await deployments.all(); + for (const key of Object.keys(allDeployments)) { + deploymentsFile[key] = allDeployments[key].address; + } + + ({ address } = await deployments.get('FuelChainState')); } - const { address } = await deployments.get('FuelChainState'); const state = FuelChainState__factory.connect(address, ethers.provider); deploymentsFile['BLOCKS_PER_COMMIT_INTERVAL'] = ( @@ -25,10 +86,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { await state.TIME_TO_FINALIZE() ).toString(); - await fs.writeFile( + const writeFileAsync = promisify(writeFile); + + await writeFileAsync( 'deployments/deployments.local.json', - JSON.stringify(deploymentsFile, null, ' '), - 'utf-8' + JSON.stringify(deploymentsFile, null, 2), + 'utf8' ); }; From fab154b4a69ab7a15a71eec31d1892a3e493906b Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:19:52 +0530 Subject: [PATCH 05/36] chore: enable forking in hardhat config --- packages/solidity-contracts/hardhat.config.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/solidity-contracts/hardhat.config.ts b/packages/solidity-contracts/hardhat.config.ts index 2815dc62..887110fb 100644 --- a/packages/solidity-contracts/hardhat.config.ts +++ b/packages/solidity-contracts/hardhat.config.ts @@ -41,6 +41,10 @@ const config: HardhatUserConfig = { accounts: { count: 128, }, + forking: { + enabled: !!process.env.TENDERLY_RPC_URL, + url: process.env.TENDERLY_RPC_URL ? process.env.TENDERLY_RPC_URL : '', + }, deploy: ['deploy/hardhat'], }, localhost: { From 8647dbcdb00bb4440fa463c18a6162f5fb607781 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:20:25 +0530 Subject: [PATCH 06/36] chore: add shell scripts --- .../solidity-contracts/scripts/node:up.sh | 1 + packages/solidity-contracts/scripts/test.sh | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 packages/solidity-contracts/scripts/node:up.sh create mode 100644 packages/solidity-contracts/scripts/test.sh diff --git a/packages/solidity-contracts/scripts/node:up.sh b/packages/solidity-contracts/scripts/node:up.sh new file mode 100644 index 00000000..71620aaf --- /dev/null +++ b/packages/solidity-contracts/scripts/node:up.sh @@ -0,0 +1 @@ +docker compose -f ./docker/docker-compose.yml up -d --build \ No newline at end of file diff --git a/packages/solidity-contracts/scripts/test.sh b/packages/solidity-contracts/scripts/test.sh new file mode 100644 index 00000000..b57d53fd --- /dev/null +++ b/packages/solidity-contracts/scripts/test.sh @@ -0,0 +1,35 @@ +# Start the docker compose file with L1 and Fuel Node +echo "\n\nStarting docker..." +pnpm run node:up + +# Wait for the nodes to be ready and run the tests +HEALTH_CHECK_COUNTER=0 +HELTH_CHECK_OUTPUT="" +MAX_CHECK_ATTEMPTS=50 + +waitForNodesToBeReady() { + NODE_URL="http://localhost:4000/v1/playground"; + + printf "\rWaiting for node.${HELTH_CHECK_OUTPUT}" + + if [ $HEALTH_CHECK_COUNTER -gt $MAX_CHECK_ATTEMPTS ]; then + echo "\n\nTests failed" + exit 1 + fi + + if curl --silent --head --request GET $NODE_URL | grep "200 OK" > /dev/null; then + # If the node responds with 200, it is ready + # to run the tests. + echo "\nRun tests..." + pnpm pnpm run test:integration + else + # If the request not returns 200 the node is not ready yet + # sleep for 6 seconds before and try again. + HEALTH_CHECK_COUNTER=$((HEALTH_CHECK_COUNTER+1)) + HELTH_CHECK_OUTPUT="${HELTH_CHECK_OUTPUT}." + sleep 6 + waitForNodesToBeReady + fi +} + +waitForNodesToBeReady \ No newline at end of file From e684961c84d360b06a3d045548dc028509886afe Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:20:51 +0530 Subject: [PATCH 07/36] chore: add additional committer signer in test setup --- packages/test-utils/src/utils/setup.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/test-utils/src/utils/setup.ts b/packages/test-utils/src/utils/setup.ts index 35640936..3882ef7e 100644 --- a/packages/test-utils/src/utils/setup.ts +++ b/packages/test-utils/src/utils/setup.ts @@ -13,7 +13,7 @@ import { FuelERC721Gateway__factory, } from '@fuel-bridge/solidity-contracts/typechain'; import * as dotenv from 'dotenv'; -import type { Signer as EthSigner } from 'ethers'; +import type { Signer as EthSigner, Provider as EthProvider } from 'ethers'; import { JsonRpcProvider, ethers, @@ -50,6 +50,7 @@ const eth_private_keys: string[] = [ const def_pk_eth_deployer: string = eth_private_keys[0]; const def_pk_eth_signer1: string = eth_private_keys[3]; const def_pk_eth_signer2: string = eth_private_keys[4]; +const def_pk_eth_signer3: string = eth_private_keys[5]; const def_pk_fuel_deployer: string = '0xde97d8624a438121b86a1956544bd72ed68cd69f2c99555b08b1e8c51ffd511c'; @@ -66,6 +67,7 @@ export interface SetupOptions { pk_eth_deployer?: string; pk_eth_signer1?: string; pk_eth_signer2?: string; + pk_eth_signer3?: string; pk_fuel_deployer?: string; pk_fuel_signer1?: string; pk_fuel_signer2?: string; @@ -109,6 +111,8 @@ export async function setupEnvironment( opts.pk_eth_signer1 || process.env.PK_ETH_SIGNER1 || def_pk_eth_signer1; const pk_eth_signer2: string = opts.pk_eth_signer2 || process.env.PK_ETH_SIGNER2 || def_pk_eth_signer2; + const pk_eth_signer3: string = + opts.pk_eth_signer3 || process.env.PK_ETH_SIGNER3 || def_pk_eth_signer3; const pk_fuel_deployer: string = opts.pk_fuel_deployer || process.env.PK_FUEL_DEPLOYER || @@ -213,6 +217,18 @@ export async function setupEnvironment( await tx.wait(); } + const eth_signer3 = new NonceManager( + new ethers.Wallet(pk_eth_signer3, eth_provider) + ); + const eth_signer3Balance = await eth_provider.getBalance(eth_signer3); + if (eth_signer3Balance < parseEther('1') && skip_deployer_balance) { + const tx = await eth_deployer.sendTransaction({ + to: eth_signer3, + value: parseEther('1'), + }); + await tx.wait(); + } + // Get contract addresses let eth_fuelChainStateAddress: string = fuel_chain_consensus_addr; let eth_fuelMessagePortalAddress: string = fuel_message_portal_addr; @@ -302,7 +318,7 @@ export async function setupEnvironment( fuelERC20Gateway: eth_fuelERC20Gateway, fuelERC721Gateway: eth_fuelERC721Gateway, deployer: eth_deployer, - signers: [eth_signer1, eth_signer2], + signers: [eth_signer1, eth_signer2, eth_signer3], }, fuel: { provider: fuel_provider, @@ -310,4 +326,4 @@ export async function setupEnvironment( signers: [fuel_signer1, fuel_signer2], }, }; -} +} \ No newline at end of file From c21c645ca79cb8e262ba06b22f3c30ad7b57fce9 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:21:18 +0530 Subject: [PATCH 08/36] feat: add fork integration tests --- .../integration-tests/bridge_erc20.ts | 726 ++++++++++++++++++ .../integration-tests/transfer_eth.ts | 509 ++++++++++++ 2 files changed, 1235 insertions(+) create mode 100644 packages/solidity-contracts/integration-tests/bridge_erc20.ts create mode 100644 packages/solidity-contracts/integration-tests/transfer_eth.ts diff --git a/packages/solidity-contracts/integration-tests/bridge_erc20.ts b/packages/solidity-contracts/integration-tests/bridge_erc20.ts new file mode 100644 index 00000000..65954400 --- /dev/null +++ b/packages/solidity-contracts/integration-tests/bridge_erc20.ts @@ -0,0 +1,726 @@ +import type { BridgeFungibleToken } from '@fuel-bridge/fungible-token'; +import type { TestEnvironment } from '@fuel-bridge/test-utils'; +import { + setupEnvironment, + relayCommonMessage, + waitForMessage, + createRelayMessageParams, + getOrDeployECR20Contract, + getOrDeployL2Bridge, + FUEL_TX_PARAMS, + getMessageOutReceipt, + fuel_to_eth_address, + waitForBlockFinalization, + getTokenId, + getBlock, + FUEL_CALL_TX_PARAMS, + hardhatSkipTime, +} from '@fuel-bridge/test-utils'; +import chai from 'chai'; +import { toBeHex, parseEther } from 'ethers'; +import type { JsonRpcProvider, Signer } from 'ethers'; +import { Address, BN } from 'fuels'; +import type { + AbstractAddress, + WalletUnlocked as FuelWallet, + MessageProof, + Provider, +} from 'fuels'; + +import { RATE_LIMIT_AMOUNT, RATE_LIMIT_DURATION } from '../protocol/constants'; +import type { Token } from '../typechain'; + +const { expect } = chai; + +describe('Bridging ERC20 tokens', async function () { + // Timeout 6 minutes + const DEFAULT_TIMEOUT_MS: number = 400_000; + const FUEL_MESSAGE_TIMEOUT_MS: number = 30_000; + const DECIMAL_DIFF = 1_000_000_000n; + + let env: TestEnvironment; + let eth_testToken: Token; + let eth_testTokenAddress: string; + let eth_erc20GatewayAddress: string; + let fuel_bridge: BridgeFungibleToken; + let fuel_bridgeImpl: BridgeFungibleToken; + let fuel_bridgeContractId: string; + let fuel_testAssetId: string; + + // override the default test timeout from 2000ms + this.timeout(DEFAULT_TIMEOUT_MS); + + async function forwardFuelChain(provider: Provider, blocksToForward: string) { + await provider.produceBlocks(Number(blocksToForward)).catch(console.error); + } + + async function getBlockWithHeight(env: any, height: string): Promise { + const BLOCK_BY_HEIGHT_QUERY = `query Block($height: U64) { + block(height: $height) { + id + } + }`; + const BLOCK_BY_HEIGHT_ARGS = { + height: height, + }; + + return fetch(env.fuel.provider.url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query: BLOCK_BY_HEIGHT_QUERY, + variables: BLOCK_BY_HEIGHT_ARGS, + }), + }) + .then((res: any) => res.json()) + .then(async (res) => { + if (!res.data.block) { + throw new Error(`Could not fetch block with height ${height}`); + } + + return res.data.block; + }); + } + + async function generateWithdrawalMessageProof( + fuel_bridge: BridgeFungibleToken, + fuelTokenSender: FuelWallet, + ethereumTokenReceiverAddress: string, + NUM_TOKENS: bigint, + DECIMAL_DIFF: bigint + ): Promise { + // withdraw tokens back to the base chain + fuel_bridge.account = fuelTokenSender; + const paddedAddress = + '0x' + ethereumTokenReceiverAddress.slice(2).padStart(64, '0'); + const fuelTokenSenderBalance = await fuelTokenSender.getBalance( + fuel_testAssetId + ); + const transactionRequest = await fuel_bridge.functions + .withdraw(paddedAddress) + .addContracts([fuel_bridge, fuel_bridgeImpl]) + .txParams({ + tip: 0, + maxFee: 1, + }) + .callParams({ + forward: { + amount: new BN(NUM_TOKENS.toString()).div( + new BN(DECIMAL_DIFF.toString()) + ), + assetId: fuel_testAssetId, + }, + }) + .fundWithRequiredCoins(); + + const tx = await fuelTokenSender.sendTransaction(transactionRequest); + const fWithdrawTxResult = await tx.waitForResult(); + expect(fWithdrawTxResult.status).to.equal('success'); + + // check that the sender balance has decreased by the expected amount + const newSenderBalance = await fuelTokenSender.getBalance(fuel_testAssetId); + + expect( + newSenderBalance.eq( + fuelTokenSenderBalance.sub(toBeHex(NUM_TOKENS / DECIMAL_DIFF)) + ) + ).to.be.true; + + // Wait for the commited block + const withdrawBlock = await getBlock( + env.fuel.provider.url, + fWithdrawTxResult.blockId! + ); + + const TIME_TO_FINALIZE = await env.eth.fuelChainState.TIME_TO_FINALIZE(); + + const blocksPerCommitInterval = ( + await env.eth.fuelChainState.BLOCKS_PER_COMMIT_INTERVAL() + ).toString(); + + // Add + 1 to the block height to wait the next block + // that enable to proof the message + const nextBlockHeight = new BN(withdrawBlock.header.height).add(new BN(1)); + const commitHeight = new BN(nextBlockHeight).div(blocksPerCommitInterval); + + let cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); + + await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour + await env.eth.provider.send('evm_mine', []); // Mine a new block + await env.eth.fuelChainState + .connect(env.eth.signers[1]) + .commit( + '0x0000000000000000000000000000000000000000000000000000000000000000', + commitHeight.toString() + ); + + await env.eth.provider.send('evm_increaseTime', [ + Number(TIME_TO_FINALIZE) * 2, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block + + cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); + + await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour + await env.eth.provider.send('evm_mine', []); // Mine a new block + + await forwardFuelChain(env.fuel.provider, blocksPerCommitInterval); + + const block = await getBlockWithHeight(env, nextBlockHeight.toString()); + + await env.eth.fuelChainState + .connect(env.eth.signers[1]) + .commit(block.id, commitHeight.toString()); + + await env.eth.provider.send('evm_increaseTime', [ + Number(TIME_TO_FINALIZE) * 2, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block + + const messageOutReceipt = getMessageOutReceipt(fWithdrawTxResult.receipts); + return await fuelTokenSender.provider.getMessageProof( + tx.id, + messageOutReceipt.nonce, + block.id + ); + } + + async function relayMessageFromFuel( + env: TestEnvironment, + withdrawMessageProof: MessageProof + ) { + // wait for block finalization + await waitForBlockFinalization(env, withdrawMessageProof); + + // construct relay message proof data + const relayMessageParams = createRelayMessageParams(withdrawMessageProof); + + // relay message + await env.eth.fuelMessagePortal.relayMessage( + relayMessageParams.message, + relayMessageParams.rootBlockHeader, + relayMessageParams.blockHeader, + relayMessageParams.blockInHistoryProof, + relayMessageParams.messageInBlockProof + ); + } + + async function relayMessageFromEthereum( + env: TestEnvironment, + fuelTokenMessageReceiver: AbstractAddress, + fuelTokenMessageNonce: BN, + fuel_AssetId: string, + amount: bigint + ) { + // relay the message ourselves + const message = await waitForMessage( + env.fuel.provider, + fuelTokenMessageReceiver, + fuelTokenMessageNonce, + FUEL_MESSAGE_TIMEOUT_MS + ); + expect(message).to.not.be.null; + + const tx = await relayCommonMessage(env.fuel.deployer, message, { + maturity: undefined, + contractIds: [fuel_bridgeImpl.id.toHexString()], + }); + + const txResult = await tx.waitForResult(); + + expect(txResult.status).to.equal('success'); + expect(txResult.mintedAssets.length).to.equal(1); + + const [mintedAsset] = txResult.mintedAssets; + + expect(mintedAsset.assetId).to.equal(fuel_AssetId); + expect(mintedAsset.amount.toString()).to.equal( + (amount / DECIMAL_DIFF).toString() + ); + } + + before(async () => { + env = await setupEnvironment({}); + eth_erc20GatewayAddress = ( + await env.eth.fuelERC20Gateway.getAddress() + ).toLowerCase(); + + eth_testToken = await getOrDeployECR20Contract(env); + eth_testTokenAddress = (await eth_testToken.getAddress()).toLowerCase(); + + const { contract, implementation } = await getOrDeployL2Bridge( + env, + env.eth.fuelERC20Gateway + ); + + fuel_bridge = contract; + fuel_bridgeImpl = implementation; + + fuel_bridgeContractId = fuel_bridge.id.toHexString(); + + await env.eth.fuelERC20Gateway + .connect(env.eth.deployer) + .setAssetIssuerId(fuel_bridgeContractId); + fuel_testAssetId = getTokenId(fuel_bridge, eth_testTokenAddress); + + // initializing rate limit params for the token + await env.eth.fuelERC20Gateway + .connect(env.eth.deployer) + .resetRateLimitAmount( + eth_testTokenAddress, + RATE_LIMIT_AMOUNT.toString(), + RATE_LIMIT_DURATION + ); + + await env.eth.fuelERC20Gateway + .connect(env.eth.deployer) + .updateRateLimitStatus(eth_testTokenAddress, true); + + const { value: expectedGatewayContractId } = await fuel_bridge.functions + .bridged_token_gateway() + .addContracts([fuel_bridge, fuel_bridgeImpl]) + .txParams(FUEL_CALL_TX_PARAMS) + .dryRun(); + + // check that values for the test token and gateway contract match what + // was compiled into the bridge-fungible-token binaries + + expect(fuel_to_eth_address(expectedGatewayContractId)).to.equal( + eth_erc20GatewayAddress + ); + expect(await eth_testToken.decimals()).to.equal(18n); + + // mint tokens as starting balances + await eth_testToken + .mint(await env.eth.deployer.getAddress(), 10_000) + .then((tx) => tx.wait()); + + await eth_testToken + .mint(await env.eth.signers[0].getAddress(), 10_000) + .then((tx) => tx.wait()); + + await eth_testToken + .mint(await env.eth.signers[1].getAddress(), 10_000) + .then((tx) => tx.wait()); + }); + + describe('Bridge ERC20 to Fuel', async () => { + const NUM_TOKENS = 100000000000000000000n; + let ethereumTokenSender: Signer; + let ethereumTokenSenderAddress: string; + let ethereumTokenSenderBalance: bigint; + let fuelTokenReceiver: FuelWallet; + let fuelTokenReceiverAddress: string; + let fuelTokenReceiverBalance: BN; + let fuelTokenMessageNonce: BN; + let fuelTokenMessageReceiver: AbstractAddress; + + before(async () => { + ethereumTokenSender = env.eth.signers[0]; + ethereumTokenSenderAddress = await ethereumTokenSender.getAddress(); + + await eth_testToken + .mint(ethereumTokenSenderAddress, NUM_TOKENS) + .then((tx) => tx.wait()); + + ethereumTokenSenderBalance = await eth_testToken.balanceOf( + ethereumTokenSenderAddress + ); + + fuelTokenReceiver = env.fuel.signers[0]; + fuelTokenReceiverAddress = fuelTokenReceiver.address.toHexString(); + fuelTokenReceiverBalance = await fuelTokenReceiver.getBalance( + fuel_testAssetId + ); + }); + + it('Bridge ERC20 via FuelERC20Gateway', async () => { + // approve FuelERC20Gateway to spend the tokens + await eth_testToken + .connect(ethereumTokenSender) + .approve(eth_erc20GatewayAddress, NUM_TOKENS) + .then((tx) => tx.wait()); + + // use the FuelERC20Gateway to deposit test tokens and receive equivalent tokens on Fuel + const receipt = await env.eth.fuelERC20Gateway + .connect(ethereumTokenSender) + .deposit(fuelTokenReceiverAddress, eth_testTokenAddress, NUM_TOKENS) + .then((tx) => tx.wait()); + + expect(receipt!.status).to.equal(1); + // parse events from logs + const [event, ...restOfEvents] = + await env.eth.fuelMessagePortal.queryFilter( + env.eth.fuelMessagePortal.filters.MessageSent, + receipt!.blockNumber, + receipt!.blockNumber + ); + expect(restOfEvents.length).to.be.eq(0); // Should be only 1 event + + fuelTokenMessageNonce = new BN(event.args.nonce.toString()); + fuelTokenMessageReceiver = Address.fromB256(event.args.recipient); + + // check that the sender balance has decreased by the expected amount + const newSenderBalance = await eth_testToken.balanceOf( + ethereumTokenSenderAddress + ); + expect(newSenderBalance === ethereumTokenSenderBalance - NUM_TOKENS).to.be + .true; + }); + + it('Relay messages from Ethereum on Fuel', async () => { + // override the default test timeout from 2000ms + this.timeout(FUEL_MESSAGE_TIMEOUT_MS); + // relay the standard erc20 deposit + await relayMessageFromEthereum( + env, + fuelTokenMessageReceiver, + fuelTokenMessageNonce, + fuel_testAssetId, + NUM_TOKENS + ); + + // override the default test timeout from 2000ms + this.timeout(FUEL_MESSAGE_TIMEOUT_MS); + }); + + it('Check metadata was registered', async () => { + await fuel_bridge.functions + .asset_to_l1_address({ bits: fuel_testAssetId }) + .addContracts([fuel_bridge, fuel_bridgeImpl]) + .call(); + + const { value: l2_decimals } = await fuel_bridge.functions + .decimals({ bits: fuel_testAssetId }) + .addContracts([fuel_bridge, fuel_bridgeImpl]) + .get(); + + expect(l2_decimals).to.be.equal(9); + }); + + it('Check ERC20 arrived on Fuel', async () => { + // check that the recipient balance has increased by the expected amount + const newReceiverBalance = await fuelTokenReceiver.getBalance( + fuel_testAssetId + ); + + expect( + newReceiverBalance.eq( + fuelTokenReceiverBalance.add(toBeHex(NUM_TOKENS / DECIMAL_DIFF)) + ) + ).to.be.true; + }); + + it('Bridge metadata', async () => { + // use the FuelERC20Gateway to deposit test tokens and receive equivalent tokens on Fuel + const receipt = await env.eth.fuelERC20Gateway + .connect(ethereumTokenSender) + .sendMetadata(eth_testTokenAddress) + .then((tx) => tx.wait()); + + // parse events from logs + const [event, ...restOfEvents] = + await env.eth.fuelMessagePortal.queryFilter( + env.eth.fuelMessagePortal.filters.MessageSent, + receipt!.blockNumber, + receipt!.blockNumber + ); + expect(restOfEvents.length).to.be.eq(0); // Should be only 1 event + + const nonce = new BN(event.args.nonce.toString()); + const fuelReceiver = Address.fromB256(event.args.recipient); + + // relay the message ourselves + const message = await waitForMessage( + env.fuel.provider, + fuelReceiver, + nonce, + FUEL_MESSAGE_TIMEOUT_MS + ); + expect(message).to.not.be.null; + + const tx = await relayCommonMessage(env.fuel.deployer, message, { + ...FUEL_TX_PARAMS, + maturity: undefined, + contractIds: [fuel_bridgeImpl.id.toHexString()], + }); + + const txResult = await tx.waitForResult(); + expect(txResult.status).to.equal('success'); + + const fuel_name = ( + await fuel_bridge.functions.name({ bits: fuel_testAssetId }).dryRun() + ).value; + const fuel_symbol = ( + await fuel_bridge.functions.symbol({ bits: fuel_testAssetId }).dryRun() + ).value; + + const eth_name = await eth_testToken.name(); + const eth_symbol = await eth_testToken.symbol(); + + expect(fuel_name).to.equal(eth_name); + expect(fuel_symbol).to.equal(eth_symbol); + }); + }); + + describe('Bridge ERC20 from Fuel', async () => { + const NUM_TOKENS = 10000000000000000000n; + const largeRateLimit = `30`; + let fuelTokenSender: FuelWallet; + let ethereumTokenReceiver: Signer; + let ethereumTokenReceiverAddress: string; + let ethereumTokenReceiverBalance: bigint; + let withdrawMessageProof: MessageProof | null; + let tokenBalanceBeforeWithdrawingOnFuel: BN; + + before(async () => { + fuelTokenSender = env.fuel.signers[0]; + ethereumTokenReceiver = env.eth.signers[0]; + ethereumTokenReceiverAddress = await ethereumTokenReceiver.getAddress(); + ethereumTokenReceiverBalance = await eth_testToken.balanceOf( + ethereumTokenReceiverAddress + ); + + tokenBalanceBeforeWithdrawingOnFuel = await fuelTokenSender.getBalance( + fuel_testAssetId + ); + }); + + it('Bridge ERC20 via Fuel token contract', async () => { + // withdraw tokens back to the base chain + withdrawMessageProof = await generateWithdrawalMessageProof( + fuel_bridge, + fuelTokenSender, + ethereumTokenReceiverAddress, + NUM_TOKENS, + DECIMAL_DIFF + ); + }); + + it('Relay Message from Fuel on Ethereum', async () => { + const withdrawnAmountBeforeRelay = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + const rateLimitEndDuratioBeforeRelay = + await env.eth.fuelERC20Gateway.currentPeriodEnd(eth_testTokenAddress); + + // relay message + await relayMessageFromFuel(env, withdrawMessageProof!); + + // check rate limit params + const withdrawnAmountAfterRelay = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + const rateLimitEndDuratioAfterRelay = + await env.eth.fuelERC20Gateway.currentPeriodEnd(eth_testTokenAddress); + + expect(rateLimitEndDuratioAfterRelay === rateLimitEndDuratioBeforeRelay) + .to.be.true; + + expect( + withdrawnAmountAfterRelay === NUM_TOKENS + withdrawnAmountBeforeRelay + ).to.be.true; + }); + + it('Check the remaining token balance on Fuel after the first withdrawal', async () => { + // fetch the remaining token balance + const currentTokenBalance = await fuelTokenSender.getBalance( + fuel_testAssetId + ); + + // currentTokenBalance has BN type by default hence the use of BN for conversion here + const expectedRemainingTokenBalanceOnFuel = + tokenBalanceBeforeWithdrawingOnFuel.sub( + new BN((NUM_TOKENS / DECIMAL_DIFF).toString()) + ); + + expect(currentTokenBalance.eq(expectedRemainingTokenBalanceOnFuel)).to.be + .true; + }); + + it('Rate limit parameters are updated when current withdrawn amount is more than the new limit & set a new higher limit', async () => { + const deployer = await env.eth.deployer; + const newRateLimit = '5'; + + let withdrawnAmountBeforeReset = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + await env.eth.fuelERC20Gateway + .connect(deployer) + .resetRateLimitAmount( + eth_testTokenAddress, + parseEther(newRateLimit), + RATE_LIMIT_DURATION + ); + + let currentWithdrawnAmountAfterSettingLimit = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + // current withdrawn amount doesn't change when rate limit is updated + + expect( + currentWithdrawnAmountAfterSettingLimit === withdrawnAmountBeforeReset + ).to.be.true; + + withdrawnAmountBeforeReset = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + await env.eth.fuelERC20Gateway + .connect(deployer) + .resetRateLimitAmount( + eth_testTokenAddress, + parseEther(largeRateLimit), + RATE_LIMIT_DURATION + ); + + currentWithdrawnAmountAfterSettingLimit = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + expect( + currentWithdrawnAmountAfterSettingLimit === withdrawnAmountBeforeReset + ).to.be.true; + }); + + it('Rate limit parameters are updated when the initial duration is over', async () => { + const deployer = await env.eth.deployer; + + const rateLimitDuration = + await env.eth.fuelERC20Gateway.rateLimitDuration(eth_testTokenAddress); + + // fast forward time + await hardhatSkipTime( + env.eth.provider as JsonRpcProvider, + rateLimitDuration * 2n + ); + const currentPeriodEndBeforeRelay = + await env.eth.fuelERC20Gateway.currentPeriodEnd(eth_testTokenAddress); + + await env.eth.fuelERC20Gateway + .connect(deployer) + .resetRateLimitAmount( + eth_testTokenAddress, + parseEther(largeRateLimit), + RATE_LIMIT_DURATION + ); + + const currentWitdrawnAmountAfterReset = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + expect(currentWitdrawnAmountAfterReset == 0n).to.be.true; + + // withdraw tokens back to the base chain + withdrawMessageProof = await generateWithdrawalMessageProof( + fuel_bridge, + fuelTokenSender, + ethereumTokenReceiverAddress, + NUM_TOKENS, + DECIMAL_DIFF + ); + + // relay message + await relayMessageFromFuel(env, withdrawMessageProof!); + + const currentPeriodEndAfterRelay = + await env.eth.fuelERC20Gateway.currentPeriodEnd(eth_testTokenAddress); + + expect(currentPeriodEndAfterRelay > currentPeriodEndBeforeRelay).to.be + .true; + + const currentPeriodAmount = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + expect(currentPeriodAmount === NUM_TOKENS).to.be.true; + }); + + it('Check the remaining token balance on Fuel after the second withdrawal', async () => { + // fetch the remaining token balance + const currentTokenBalance = await fuelTokenSender.getBalance( + fuel_testAssetId + ); + + // currentTokenBalance has BN type by default hence the use of BN for conversion here + const expectedRemainingTokenBalanceOnFuel = + tokenBalanceBeforeWithdrawingOnFuel.sub( + new BN(((NUM_TOKENS * 2n) / DECIMAL_DIFF).toString()) + ); + + expect(currentTokenBalance.eq(expectedRemainingTokenBalanceOnFuel)).to.be + .true; + }); + + it('Rate limit parameters are updated when new limit is set after the initial duration', async () => { + const rateLimitDuration = + await env.eth.fuelERC20Gateway.rateLimitDuration(eth_testTokenAddress); + + const deployer = await env.eth.deployer; + const newRateLimit = `40`; + + // fast forward time + await hardhatSkipTime( + env.eth.provider as JsonRpcProvider, + rateLimitDuration * 2n + ); + + const currentWithdrawnAmountBeforeSettingLimit = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + const currentPeriodEndBeforeSettingLimit = + await env.eth.fuelERC20Gateway.currentPeriodEnd(eth_testTokenAddress); + + await env.eth.fuelERC20Gateway + .connect(deployer) + .resetRateLimitAmount( + eth_testTokenAddress, + parseEther(newRateLimit), + RATE_LIMIT_DURATION + ); + + const currentPeriodEndAfterSettingLimit = + await env.eth.fuelERC20Gateway.currentPeriodEnd(eth_testTokenAddress); + const currentWithdrawnAmountAfterSettingLimit = + await env.eth.fuelERC20Gateway.currentPeriodAmount( + eth_testTokenAddress + ); + + expect( + currentPeriodEndAfterSettingLimit > currentPeriodEndBeforeSettingLimit + ).to.be.true; + + expect( + currentWithdrawnAmountBeforeSettingLimit > + currentWithdrawnAmountAfterSettingLimit + ).to.be.true; + + expect(currentWithdrawnAmountAfterSettingLimit === 0n).to.be.true; + }); + + it('Check ERC20 arrived on Ethereum', async () => { + // check that the recipient balance has increased by the expected amount + const newReceiverBalance = await eth_testToken.balanceOf( + ethereumTokenReceiverAddress + ); + expect( + newReceiverBalance === ethereumTokenReceiverBalance + NUM_TOKENS * 2n + ).to.be.true; + }); + }); +}); diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts new file mode 100644 index 00000000..9d5d1a4c --- /dev/null +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -0,0 +1,509 @@ +import type { TestEnvironment } from '@fuel-bridge/test-utils'; +import { + setupEnvironment, + fuels_parseEther, + createRelayMessageParams, + getMessageOutReceipt, + waitForMessage, + waitForBlockFinalization, + getBlock, + FUEL_CALL_TX_PARAMS, +} from '@fuel-bridge/test-utils'; +import chai from 'chai'; +import { parseEther } from 'ethers'; +import type { Signer } from 'ethers'; +import { Address, BN, padFirst12BytesOfEvmAddress } from 'fuels'; +import type { + AbstractAddress, + WalletUnlocked as FuelWallet, + MessageProof, + Provider, +} from 'fuels'; + +const { expect } = chai; + +describe('Transferring ETH', async function () { + // Timeout 6 minutes + const DEFAULT_TIMEOUT_MS: number = 400_000; + const FUEL_MESSAGE_TIMEOUT_MS: number = 30_000; + let BASE_ASSET_ID: string; + + let env: TestEnvironment; + + // override the default test timeout of 2000ms + this.timeout(DEFAULT_TIMEOUT_MS); + + async function forwardFuelChain(provider: Provider, blocksToForward: string) { + await provider.produceBlocks(Number(blocksToForward)).catch(console.error); + } + + async function getBlockWithHeight(env: any, height: string): Promise { + const BLOCK_BY_HEIGHT_QUERY = `query Block($height: U64) { + block(height: $height) { + id + } + }`; + const BLOCK_BY_HEIGHT_ARGS = { + height: height, + }; + + return fetch(env.fuel.provider.url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query: BLOCK_BY_HEIGHT_QUERY, + variables: BLOCK_BY_HEIGHT_ARGS, + }), + }) + .then((res: any) => res.json()) + .then(async (res) => { + if (!res.data.block) { + throw new Error(`Could not fetch block with height ${height}`); + } + + return res.data.block; + }); + } + + async function generateWithdrawalMessageProof( + fuelETHSender: FuelWallet, + ethereumETHReceiverAddress: string, + NUM_ETH: string + ): Promise { + // withdraw ETH back to the base chain + const fWithdrawTx = await fuelETHSender.withdrawToBaseLayer( + Address.fromString( + padFirst12BytesOfEvmAddress(ethereumETHReceiverAddress) + ), + fuels_parseEther(NUM_ETH), + FUEL_CALL_TX_PARAMS + ); + const fWithdrawTxResult = await fWithdrawTx.waitForResult(); + expect(fWithdrawTxResult.status).to.equal('success'); + + // Wait for the commited block + const withdrawBlock = await getBlock( + env.fuel.provider.url, + fWithdrawTxResult.blockId! + ); + + const TIME_TO_FINALIZE = await env.eth.fuelChainState.TIME_TO_FINALIZE(); + + const blocksPerCommitInterval = ( + await env.eth.fuelChainState.BLOCKS_PER_COMMIT_INTERVAL() + ).toString(); + + // Add + 1 to the block height to wait the next block + // that enable to proof the message + const nextBlockHeight = new BN(withdrawBlock.header.height).add(new BN(1)); + const commitHeight = new BN(nextBlockHeight).div(blocksPerCommitInterval); + + let cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); + + await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour + await env.eth.provider.send('evm_mine', []); // Mine a new block + await env.eth.fuelChainState + .connect(env.eth.signers[1]) + .commit( + '0x0000000000000000000000000000000000000000000000000000000000000000', + commitHeight.toString() + ); + + await env.eth.provider.send('evm_increaseTime', [ + Number(TIME_TO_FINALIZE) * 2, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block + + cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); + + await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour + await env.eth.provider.send('evm_mine', []); // Mine a new block + + await forwardFuelChain(env.fuel.provider, blocksPerCommitInterval); + + const block = await getBlockWithHeight(env, nextBlockHeight.toString()); + + await env.eth.fuelChainState + .connect(env.eth.signers[1]) + .commit(block.id, commitHeight.toString()); + + await env.eth.provider.send('evm_increaseTime', [ + Number(TIME_TO_FINALIZE) * 2, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block + + // get message proof + const messageOutReceipt = getMessageOutReceipt(fWithdrawTxResult.receipts); + + return await fuelETHSender.provider.getMessageProof( + fWithdrawTx.id, + messageOutReceipt.nonce, + block.id + ); + } + + async function relayMessage( + env: TestEnvironment, + withdrawMessageProof: MessageProof + ) { + // wait for block finalization + await waitForBlockFinalization(env, withdrawMessageProof); + + // construct relay message proof data + const relayMessageParams = createRelayMessageParams(withdrawMessageProof); + + // relay message + await env.eth.fuelMessagePortal.relayMessage( + relayMessageParams.message, + relayMessageParams.rootBlockHeader, + relayMessageParams.blockHeader, + relayMessageParams.blockInHistoryProof, + relayMessageParams.messageInBlockProof + ); + } + + before(async () => { + env = await setupEnvironment({}); + BASE_ASSET_ID = env.fuel.provider.getBaseAssetId(); + }); + + describe('Send ETH to Fuel', async () => { + const NUM_ETH = '30'; + let ethereumETHSender: Signer; + let ethereumETHSenderAddress: string; + let fuelETHReceiver: AbstractAddress; + let fuelETHReceiverAddress: string; + let fuelETHReceiverBalance: BN; + let fuelETHMessageNonce: BN; + + before(async () => { + ethereumETHSender = env.eth.signers[0]; + ethereumETHSenderAddress = await ethereumETHSender.getAddress(); + fuelETHReceiver = env.fuel.signers[0].address; + fuelETHReceiverAddress = fuelETHReceiver.toHexString(); + + fuelETHReceiverBalance = await env.fuel.provider.getBalance( + fuelETHReceiver, + BASE_ASSET_ID + ); + }); + + it('Send ETH via MessagePortal', async () => { + // use the FuelMessagePortal to directly send ETH which should be immediately spendable + const tx = await env.eth.fuelMessagePortal + .connect(ethereumETHSender) + .depositETH(fuelETHReceiverAddress, { + value: parseEther(NUM_ETH), + }); + const receipt = await tx.wait(); + expect(receipt!.status).to.equal(1); + + // parse events from logs + const filter = env.eth.fuelMessagePortal.filters.MessageSent( + undefined, // Args set to null since there should be just 1 event for MessageSent + undefined, + undefined, + undefined, + undefined + ); + + const [event, ...restOfEvents] = + await env.eth.fuelMessagePortal.queryFilter( + filter, + receipt!.blockNumber, + receipt!.blockNumber + ); + expect(restOfEvents.length).to.be.eq(0); // Should be only 1 event + + fuelETHMessageNonce = new BN(event.args.nonce.toString()); + + // check that the sender balance has decreased by the expected amount + const newSenderBalance = await env.eth.provider.getBalance( + ethereumETHSenderAddress, + receipt!.blockNumber + ); + + const txCost = receipt!.fee; + + const expectedSenderBalance = + (await env.eth.provider.getBalance( + ethereumETHSender, + receipt!.blockNumber - 1 + )) - + txCost - + parseEther(NUM_ETH); + + expect(newSenderBalance).to.be.eq(expectedSenderBalance); + }); + + it('Wait for ETH to arrive on Fuel', async function () { + // wait for message to appear in fuel client + expect( + await waitForMessage( + env.fuel.provider, + fuelETHReceiver, + fuelETHMessageNonce, + FUEL_MESSAGE_TIMEOUT_MS + ) + ).to.not.be.null; + + // check that the recipient balance has increased by the expected amount + const newReceiverBalance = await env.fuel.provider.getBalance( + fuelETHReceiver, + BASE_ASSET_ID + ); + expect( + newReceiverBalance.eq( + fuelETHReceiverBalance.add(fuels_parseEther(NUM_ETH)) + ) + ).to.be.true; + }); + }); + + describe('Send ETH from Fuel', async () => { + const NUM_ETH = '0.001'; + let fuelETHSender: FuelWallet; + let fuelETHSenderBalance: BN; + let ethereumETHReceiver: Signer; + let ethereumETHReceiverAddress: string; + let ethereumETHReceiverBalance: bigint; + let withdrawMessageProof: MessageProof | null; + + before(async () => { + fuelETHSender = env.fuel.signers[1]; + fuelETHSenderBalance = await fuelETHSender.getBalance(BASE_ASSET_ID); + ethereumETHReceiver = env.eth.signers[1]; + ethereumETHReceiverAddress = await ethereumETHReceiver.getAddress(); + ethereumETHReceiverBalance = await env.eth.provider.getBalance( + ethereumETHReceiver + ); + }); + + it('Send ETH via OutputMessage', async () => { + withdrawMessageProof = await generateWithdrawalMessageProof( + fuelETHSender, + ethereumETHReceiverAddress, + NUM_ETH + ); + + // check that the sender balance has decreased by the expected amount + const newSenderBalance = await fuelETHSender.getBalance(BASE_ASSET_ID); + + // Get just the first 3 digits of the balance to compare to the expected balance + // this is required because the payment of gas fees is not deterministic + const diffOnSenderBalance = newSenderBalance + .sub(fuelETHSenderBalance) + .formatUnits(); + expect(diffOnSenderBalance.startsWith(NUM_ETH)).to.be.true; + }); + + it('Relay Message from Fuel on Ethereum', async () => { + await relayMessage(env, withdrawMessageProof!); + }); + + it('Check ETH arrived on Ethereum', async () => { + // check that the recipient balance has increased by the expected amount + const newReceiverBalance = await env.eth.provider.getBalance( + ethereumETHReceiver + ); + + expect( + newReceiverBalance <= ethereumETHReceiverBalance + parseEther(NUM_ETH) + ).to.be.true; + }); + }); + + describe('ETH Withdrawls based on rate limit updates', async () => { + const NUM_ETH = '9'; + const largeRateLimit = `30`; + let fuelETHSender: FuelWallet; + let ethereumETHReceiver: Signer; + let ethereumETHReceiverAddress: string; + let withdrawMessageProof: MessageProof | null; + let rateLimitDuration: bigint; + + before(async () => { + fuelETHSender = env.fuel.signers[1]; + ethereumETHReceiver = env.eth.signers[1]; + ethereumETHReceiverAddress = await ethereumETHReceiver.getAddress(); + + await env.eth.fuelMessagePortal + .connect(env.eth.deployer) + .updateRateLimitStatus(true); + rateLimitDuration = await env.eth.fuelMessagePortal.RATE_LIMIT_DURATION(); + }); + + it('Checks rate limit params after relaying', async () => { + withdrawMessageProof = await generateWithdrawalMessageProof( + fuelETHSender, + ethereumETHReceiverAddress, + NUM_ETH + ); + + const withdrawnAmountBeforeRelay = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + await relayMessage(env, withdrawMessageProof!); + + const currentPeriodAmount = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + expect( + currentPeriodAmount === parseEther(NUM_ETH) + withdrawnAmountBeforeRelay + ).to.be.true; + }); + + it('Relays ETH after the rate limit is updated', async () => { + const deployer = env.eth.deployer; + const newRateLimit = `30`; + + await env.eth.fuelMessagePortal + .connect(deployer) + .resetRateLimitAmount(parseEther(newRateLimit)); + + withdrawMessageProof = await generateWithdrawalMessageProof( + fuelETHSender, + ethereumETHReceiverAddress, + NUM_ETH + ); + + const withdrawnAmountBeforeRelay = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + let currentWIthdrawnAmountReset = false; + + if (withdrawnAmountBeforeRelay > parseEther(newRateLimit)) { + currentWIthdrawnAmountReset = true; + + // fast forward time + await env.eth.provider.send('evm_increaseTime', [ + Number(rateLimitDuration) * 2, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block + } + + await relayMessage(env, withdrawMessageProof!); + + const currentPeriodAmount = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + if (currentWIthdrawnAmountReset) + expect(currentPeriodAmount === parseEther(NUM_ETH)).to.be.true; + else { + expect( + currentPeriodAmount === + parseEther(NUM_ETH) + withdrawnAmountBeforeRelay + ).to.be.true; + } + }); + + it('Rate limit parameters are updated when current withdrawn amount is more than the new limit & set a new higher limit', async () => { + const deployer = env.eth.deployer; + const newRateLimit = `10`; + + let withdrawnAmountBeforeReset = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + await env.eth.fuelMessagePortal + .connect(deployer) + .resetRateLimitAmount(parseEther(newRateLimit)); + + let currentWithdrawnAmountAfterSettingLimit = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + // current withdrawn amount doesn't change when rate limit is updated + + expect( + currentWithdrawnAmountAfterSettingLimit === withdrawnAmountBeforeReset + ).to.be.true; + + withdrawnAmountBeforeReset = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + await env.eth.fuelMessagePortal + .connect(deployer) + .resetRateLimitAmount(parseEther(largeRateLimit)); + + currentWithdrawnAmountAfterSettingLimit = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + expect( + currentWithdrawnAmountAfterSettingLimit === withdrawnAmountBeforeReset + ).to.be.true; + }); + + it('Rate limit parameters are updated when the initial duration is over', async () => { + const deployer = env.eth.deployer; + + // fast forward time + await env.eth.provider.send('evm_increaseTime', [ + Number(rateLimitDuration) * 2, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block + + const currentPeriodEndBeforeRelay = + await env.eth.fuelMessagePortal.currentPeriodEnd(); + + await env.eth.fuelMessagePortal + .connect(deployer) + .resetRateLimitAmount(parseEther(largeRateLimit)); + + withdrawMessageProof = await generateWithdrawalMessageProof( + fuelETHSender, + ethereumETHReceiverAddress, + NUM_ETH + ); + + await relayMessage(env, withdrawMessageProof!); + + const currentPeriodEndAfterRelay = + await env.eth.fuelMessagePortal.currentPeriodEnd(); + + expect(currentPeriodEndAfterRelay > currentPeriodEndBeforeRelay).to.be + .true; + + const currentPeriodAmount = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + expect(currentPeriodAmount === parseEther(NUM_ETH)).to.be.true; + }); + + it('Rate limit parameters are updated when new limit is set after the initial duration', async () => { + const deployer = await env.eth.deployer; + const newRateLimit = `40`; + + const currentWithdrawnAmountBeforeSettingLimit = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + const currentPeriodEndBeforeSettingLimit = + await env.eth.fuelMessagePortal.currentPeriodEnd(); + + // fast forward time + await env.eth.provider.send('evm_increaseTime', [ + Number(rateLimitDuration) * 2, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block + + await env.eth.fuelMessagePortal + .connect(deployer) + .resetRateLimitAmount(parseEther(newRateLimit)); + + const currentPeriodEndAfterSettingLimit = + await env.eth.fuelMessagePortal.currentPeriodEnd(); + const currentWithdrawnAmountAfterSettingLimit = + await env.eth.fuelMessagePortal.currentPeriodAmount(); + + expect( + currentPeriodEndAfterSettingLimit > currentPeriodEndBeforeSettingLimit + ).to.be.true; + + expect( + currentWithdrawnAmountBeforeSettingLimit > + currentWithdrawnAmountAfterSettingLimit + ).to.be.true; + + expect(currentWithdrawnAmountAfterSettingLimit == 0n).to.be.true; + }); + }); +}); From f36aef9a9c845c77ade0475bc79e57db3959d312 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 15:21:59 +0530 Subject: [PATCH 09/36] feat: add github action for fork integration tests --- .github/workflows/upgrade-test-suite.yml | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/upgrade-test-suite.yml diff --git a/.github/workflows/upgrade-test-suite.yml b/.github/workflows/upgrade-test-suite.yml new file mode 100644 index 00000000..002d0178 --- /dev/null +++ b/.github/workflows/upgrade-test-suite.yml @@ -0,0 +1,36 @@ +name: Upgrade Test Suite + +on: + push: + branches: + - main + pull_request: + branches: + - main # Target branch for the PR + release: + types: [published] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + upgrade-test-suite: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v3 + - uses: FuelLabs/github-actions/setups/node@master + with: + node-version: 20.16.0 + pnpm-version: 9.0.6 + - name: Sets the tenderly rpc endpoint in the L1 docker container env + run: | + cat << EOF > l1_chain.env + TENDERLY_RPC_URL=${{ secrets.TENDERLY_RPC_URL }} + EOF + working-directory: ./packages/solidity-contracts/docker/envs + - name: Run integration tests on a L1 fork after upgrading contracts + run: | + pnpm upgrade:test:integration + working-directory: ./packages/solidity-contracts From 7b932fbe6be8de3393851fc383c26ccd21baa141 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 27 Dec 2024 18:06:02 +0530 Subject: [PATCH 10/36] chore: add build command in workflow --- .github/workflows/upgrade-test-suite.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/upgrade-test-suite.yml b/.github/workflows/upgrade-test-suite.yml index 002d0178..7ca7c424 100644 --- a/.github/workflows/upgrade-test-suite.yml +++ b/.github/workflows/upgrade-test-suite.yml @@ -24,6 +24,8 @@ jobs: with: node-version: 20.16.0 pnpm-version: 9.0.6 + - name: Build project + run: pnpm build - name: Sets the tenderly rpc endpoint in the L1 docker container env run: | cat << EOF > l1_chain.env From 2ebc8b7e1bc83417a37fa01764d479cd673c6c03 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Mon, 30 Dec 2024 10:55:27 +0530 Subject: [PATCH 11/36] chore: add docker and rust setup in ci --- .github/workflows/upgrade-test-suite.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/upgrade-test-suite.yml b/.github/workflows/upgrade-test-suite.yml index 7ca7c424..82ec5a43 100644 --- a/.github/workflows/upgrade-test-suite.yml +++ b/.github/workflows/upgrade-test-suite.yml @@ -24,6 +24,11 @@ jobs: with: node-version: 20.16.0 pnpm-version: 9.0.6 + - uses: FuelLabs/github-actions/setups/docker@master + with: + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: ./.github/actions/setup-rust - name: Build project run: pnpm build - name: Sets the tenderly rpc endpoint in the L1 docker container env From 22dafb85c359bb6c894367cdba08a930778da1cb Mon Sep 17 00:00:00 2001 From: viraj124 Date: Mon, 30 Dec 2024 15:28:08 +0530 Subject: [PATCH 12/36] chore: debug ci failure --- .../integration-tests/bridge_erc20.ts | 14 +++++++++++--- .../integration-tests/transfer_eth.ts | 12 ++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/solidity-contracts/integration-tests/bridge_erc20.ts b/packages/solidity-contracts/integration-tests/bridge_erc20.ts index 65954400..fa6dc64f 100644 --- a/packages/solidity-contracts/integration-tests/bridge_erc20.ts +++ b/packages/solidity-contracts/integration-tests/bridge_erc20.ts @@ -146,16 +146,20 @@ describe('Bridging ERC20 tokens', async function () { const commitHeight = new BN(nextBlockHeight).div(blocksPerCommitInterval); let cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); - + + // fast forward post the commit cooldown period await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour await env.eth.provider.send('evm_mine', []); // Mine a new block + + // override the commit hash in a existing block await env.eth.fuelChainState .connect(env.eth.signers[1]) .commit( '0x0000000000000000000000000000000000000000000000000000000000000000', commitHeight.toString() ); - + + // fast forward to the block finalization time await env.eth.provider.send('evm_increaseTime', [ Number(TIME_TO_FINALIZE) * 2, ]); @@ -163,17 +167,21 @@ describe('Bridging ERC20 tokens', async function () { cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); + // fast forward post the commit cooldown period await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour await env.eth.provider.send('evm_mine', []); // Mine a new block - + + // produce more blocks to fetch the block height await forwardFuelChain(env.fuel.provider, blocksPerCommitInterval); const block = await getBlockWithHeight(env, nextBlockHeight.toString()); + // reset the commit hash in the local L2 network await env.eth.fuelChainState .connect(env.eth.signers[1]) .commit(block.id, commitHeight.toString()); + // fast forward to the block finalization time await env.eth.provider.send('evm_increaseTime', [ Number(TIME_TO_FINALIZE) * 2, ]); diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts index 9d5d1a4c..5df1477f 100644 --- a/packages/solidity-contracts/integration-tests/transfer_eth.ts +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -102,8 +102,11 @@ describe('Transferring ETH', async function () { let cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); + // fast forward post the commit cooldown period await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour await env.eth.provider.send('evm_mine', []); // Mine a new block + + // override the commit hash in a existing block await env.eth.fuelChainState .connect(env.eth.signers[1]) .commit( @@ -111,6 +114,7 @@ describe('Transferring ETH', async function () { commitHeight.toString() ); + // fast forward to the block finalization time await env.eth.provider.send('evm_increaseTime', [ Number(TIME_TO_FINALIZE) * 2, ]); @@ -118,17 +122,21 @@ describe('Transferring ETH', async function () { cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); + // fast forward post the commit cooldown period await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour await env.eth.provider.send('evm_mine', []); // Mine a new block + // produce more blocks to fetch the block height await forwardFuelChain(env.fuel.provider, blocksPerCommitInterval); const block = await getBlockWithHeight(env, nextBlockHeight.toString()); + // reset the commit hash in the local L2 network await env.eth.fuelChainState .connect(env.eth.signers[1]) .commit(block.id, commitHeight.toString()); + // fast forward to the block finalization time await env.eth.provider.send('evm_increaseTime', [ Number(TIME_TO_FINALIZE) * 2, ]); @@ -446,9 +454,13 @@ describe('Transferring ETH', async function () { const currentPeriodEndBeforeRelay = await env.eth.fuelMessagePortal.currentPeriodEnd(); + console.log("reset limit") + await env.eth.fuelMessagePortal .connect(deployer) .resetRateLimitAmount(parseEther(largeRateLimit)); + + console.log("generateWithdrawalMessageProof") withdrawMessageProof = await generateWithdrawalMessageProof( fuelETHSender, From 092e1db464e56b9b2e9f9935f7b64ac06c71162a Mon Sep 17 00:00:00 2001 From: viraj124 Date: Mon, 30 Dec 2024 16:53:18 +0530 Subject: [PATCH 13/36] chore: fast forward finalization time before relay --- .../solidity-contracts/integration-tests/transfer_eth.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts index 5df1477f..3dca9ae6 100644 --- a/packages/solidity-contracts/integration-tests/transfer_eth.ts +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -162,6 +162,14 @@ describe('Transferring ETH', async function () { // construct relay message proof data const relayMessageParams = createRelayMessageParams(withdrawMessageProof); + const TIME_TO_FINALIZE = await env.eth.fuelChainState.TIME_TO_FINALIZE(); + + // fast forward to the block finalization time + await env.eth.provider.send('evm_increaseTime', [ + Number(TIME_TO_FINALIZE) * 100, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block + // relay message await env.eth.fuelMessagePortal.relayMessage( relayMessageParams.message, From 8768fbb838aff7456965d477ce1b035a2d8ed7d6 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 31 Dec 2024 12:06:44 +0530 Subject: [PATCH 14/36] chore: debug ci failure --- .../integration-tests/transfer_eth.ts | 77 ++++++++++--------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts index 3dca9ae6..d20d388d 100644 --- a/packages/solidity-contracts/integration-tests/transfer_eth.ts +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -450,45 +450,45 @@ describe('Transferring ETH', async function () { ).to.be.true; }); - it('Rate limit parameters are updated when the initial duration is over', async () => { - const deployer = env.eth.deployer; + // it('Rate limit parameters are updated when the initial duration is over', async () => { + // const deployer = env.eth.deployer; - // fast forward time - await env.eth.provider.send('evm_increaseTime', [ - Number(rateLimitDuration) * 2, - ]); - await env.eth.provider.send('evm_mine', []); // Mine a new block + // // fast forward time + // await env.eth.provider.send('evm_increaseTime', [ + // Number(rateLimitDuration) * 2, + // ]); + // await env.eth.provider.send('evm_mine', []); // Mine a new block - const currentPeriodEndBeforeRelay = - await env.eth.fuelMessagePortal.currentPeriodEnd(); + // const currentPeriodEndBeforeRelay = + // await env.eth.fuelMessagePortal.currentPeriodEnd(); - console.log("reset limit") + // console.log("reset limit") - await env.eth.fuelMessagePortal - .connect(deployer) - .resetRateLimitAmount(parseEther(largeRateLimit)); + // await env.eth.fuelMessagePortal + // .connect(deployer) + // .resetRateLimitAmount(parseEther(largeRateLimit)); - console.log("generateWithdrawalMessageProof") + // console.log("generateWithdrawalMessageProof") - withdrawMessageProof = await generateWithdrawalMessageProof( - fuelETHSender, - ethereumETHReceiverAddress, - NUM_ETH - ); + // withdrawMessageProof = await generateWithdrawalMessageProof( + // fuelETHSender, + // ethereumETHReceiverAddress, + // NUM_ETH + // ); - await relayMessage(env, withdrawMessageProof!); + // await relayMessage(env, withdrawMessageProof!); - const currentPeriodEndAfterRelay = - await env.eth.fuelMessagePortal.currentPeriodEnd(); + // const currentPeriodEndAfterRelay = + // await env.eth.fuelMessagePortal.currentPeriodEnd(); - expect(currentPeriodEndAfterRelay > currentPeriodEndBeforeRelay).to.be - .true; + // expect(currentPeriodEndAfterRelay > currentPeriodEndBeforeRelay).to.be + // .true; - const currentPeriodAmount = - await env.eth.fuelMessagePortal.currentPeriodAmount(); + // const currentPeriodAmount = + // await env.eth.fuelMessagePortal.currentPeriodAmount(); - expect(currentPeriodAmount === parseEther(NUM_ETH)).to.be.true; - }); + // expect(currentPeriodAmount === parseEther(NUM_ETH)).to.be.true; + // }); it('Rate limit parameters are updated when new limit is set after the initial duration', async () => { const deployer = await env.eth.deployer; @@ -505,25 +505,30 @@ describe('Transferring ETH', async function () { ]); await env.eth.provider.send('evm_mine', []); // Mine a new block + console.log("reset limit") + await env.eth.fuelMessagePortal .connect(deployer) .resetRateLimitAmount(parseEther(newRateLimit)); + console.log("reset done") + + const currentPeriodEndAfterSettingLimit = await env.eth.fuelMessagePortal.currentPeriodEnd(); const currentWithdrawnAmountAfterSettingLimit = await env.eth.fuelMessagePortal.currentPeriodAmount(); - expect( - currentPeriodEndAfterSettingLimit > currentPeriodEndBeforeSettingLimit - ).to.be.true; + // expect( + // currentPeriodEndAfterSettingLimit > currentPeriodEndBeforeSettingLimit + // ).to.be.true; - expect( - currentWithdrawnAmountBeforeSettingLimit > - currentWithdrawnAmountAfterSettingLimit - ).to.be.true; + // expect( + // currentWithdrawnAmountBeforeSettingLimit > + // currentWithdrawnAmountAfterSettingLimit + // ).to.be.true; - expect(currentWithdrawnAmountAfterSettingLimit == 0n).to.be.true; + // expect(currentWithdrawnAmountAfterSettingLimit == 0n).to.be.true; }); }); }); From 4a8ac6e7ccf92f53eeeb6da1b64a50b14e9401da Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 31 Dec 2024 16:43:27 +0530 Subject: [PATCH 15/36] chore: debug ci failure --- .../integration-tests/transfer_eth.ts | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts index d20d388d..f3cfda10 100644 --- a/packages/solidity-contracts/integration-tests/transfer_eth.ts +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -450,45 +450,45 @@ describe('Transferring ETH', async function () { ).to.be.true; }); - // it('Rate limit parameters are updated when the initial duration is over', async () => { - // const deployer = env.eth.deployer; + it('Rate limit parameters are updated when the initial duration is over', async () => { + const deployer = env.eth.deployer; - // // fast forward time - // await env.eth.provider.send('evm_increaseTime', [ - // Number(rateLimitDuration) * 2, - // ]); - // await env.eth.provider.send('evm_mine', []); // Mine a new block + // fast forward time + await env.eth.provider.send('evm_increaseTime', [ + Number(rateLimitDuration) * 2, + ]); + await env.eth.provider.send('evm_mine', []); // Mine a new block - // const currentPeriodEndBeforeRelay = - // await env.eth.fuelMessagePortal.currentPeriodEnd(); + const currentPeriodEndBeforeRelay = + await env.eth.fuelMessagePortal.currentPeriodEnd(); - // console.log("reset limit") + console.log("reset limit") - // await env.eth.fuelMessagePortal - // .connect(deployer) - // .resetRateLimitAmount(parseEther(largeRateLimit)); + await env.eth.fuelMessagePortal + .connect(deployer) + .resetRateLimitAmount(parseEther(largeRateLimit)); - // console.log("generateWithdrawalMessageProof") + console.log("generateWithdrawalMessageProof") - // withdrawMessageProof = await generateWithdrawalMessageProof( - // fuelETHSender, - // ethereumETHReceiverAddress, - // NUM_ETH - // ); + withdrawMessageProof = await generateWithdrawalMessageProof( + fuelETHSender, + ethereumETHReceiverAddress, + NUM_ETH + ); - // await relayMessage(env, withdrawMessageProof!); + await relayMessage(env, withdrawMessageProof!); - // const currentPeriodEndAfterRelay = - // await env.eth.fuelMessagePortal.currentPeriodEnd(); + // const currentPeriodEndAfterRelay = + // await env.eth.fuelMessagePortal.currentPeriodEnd(); - // expect(currentPeriodEndAfterRelay > currentPeriodEndBeforeRelay).to.be - // .true; + // expect(currentPeriodEndAfterRelay > currentPeriodEndBeforeRelay).to.be + // .true; - // const currentPeriodAmount = - // await env.eth.fuelMessagePortal.currentPeriodAmount(); + // const currentPeriodAmount = + // await env.eth.fuelMessagePortal.currentPeriodAmount(); - // expect(currentPeriodAmount === parseEther(NUM_ETH)).to.be.true; - // }); + // expect(currentPeriodAmount === parseEther(NUM_ETH)).to.be.true; + }); it('Rate limit parameters are updated when new limit is set after the initial duration', async () => { const deployer = await env.eth.deployer; From 3f56a0d707143f0bc654b0a4fe224b35ea85b353 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 31 Dec 2024 17:44:46 +0530 Subject: [PATCH 16/36] chore: update portal upgrade script --- .../deploy/hardhat/010.portal_upgrade.ts | 13 ++++++++++++- .../integration-tests/transfer_eth.ts | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts b/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts index 14682a6a..0b33feb9 100644 --- a/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts +++ b/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts @@ -16,7 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { upgrades: { erc1967 }, } = hre; - const [deployer] = await ethers.getSigners(); + const [deployer, , ,secondaryUser] = await ethers.getSigners(); const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; let address; @@ -73,6 +73,17 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { data: txData, }); + txData = await portal.interface.encodeFunctionData('grantRole', [ + SET_RATE_LIMITER_ROLE, + await secondaryUser.getAddress(), + ]); + + await impersonatedSigner.sendTransaction({ + to: address, + data: txData, + }); + + const implementation = await erc1967.getImplementationAddress(address); console.log('Upgraded FuelMessagePortal to', implementation); diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts index f3cfda10..3063f771 100644 --- a/packages/solidity-contracts/integration-tests/transfer_eth.ts +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -451,7 +451,7 @@ describe('Transferring ETH', async function () { }); it('Rate limit parameters are updated when the initial duration is over', async () => { - const deployer = env.eth.deployer; + const deployer = await env.eth.signers[0]; // fast forward time await env.eth.provider.send('evm_increaseTime', [ From b0e7f059c22b5470d3db91ce64817cc1e2910b81 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 31 Dec 2024 20:18:35 +0530 Subject: [PATCH 17/36] chore: uncomment code --- .../deploy/hardhat/010.portal_upgrade.ts | 13 +----- .../integration-tests/transfer_eth.ts | 44 +++++++------------ 2 files changed, 16 insertions(+), 41 deletions(-) diff --git a/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts b/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts index 0b33feb9..14682a6a 100644 --- a/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts +++ b/packages/solidity-contracts/deploy/hardhat/010.portal_upgrade.ts @@ -16,7 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { upgrades: { erc1967 }, } = hre; - const [deployer, , ,secondaryUser] = await ethers.getSigners(); + const [deployer] = await ethers.getSigners(); const isForking = hre.config.networks[hre.network.name]?.forking?.enabled; let address; @@ -73,17 +73,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { data: txData, }); - txData = await portal.interface.encodeFunctionData('grantRole', [ - SET_RATE_LIMITER_ROLE, - await secondaryUser.getAddress(), - ]); - - await impersonatedSigner.sendTransaction({ - to: address, - data: txData, - }); - - const implementation = await erc1967.getImplementationAddress(address); console.log('Upgraded FuelMessagePortal to', implementation); diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts index 3063f771..73d03caf 100644 --- a/packages/solidity-contracts/integration-tests/transfer_eth.ts +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -430,7 +430,6 @@ describe('Transferring ETH', async function () { await env.eth.fuelMessagePortal.currentPeriodAmount(); // current withdrawn amount doesn't change when rate limit is updated - expect( currentWithdrawnAmountAfterSettingLimit === withdrawnAmountBeforeReset ).to.be.true; @@ -462,14 +461,6 @@ describe('Transferring ETH', async function () { const currentPeriodEndBeforeRelay = await env.eth.fuelMessagePortal.currentPeriodEnd(); - console.log("reset limit") - - await env.eth.fuelMessagePortal - .connect(deployer) - .resetRateLimitAmount(parseEther(largeRateLimit)); - - console.log("generateWithdrawalMessageProof") - withdrawMessageProof = await generateWithdrawalMessageProof( fuelETHSender, ethereumETHReceiverAddress, @@ -478,16 +469,16 @@ describe('Transferring ETH', async function () { await relayMessage(env, withdrawMessageProof!); - // const currentPeriodEndAfterRelay = - // await env.eth.fuelMessagePortal.currentPeriodEnd(); + const currentPeriodEndAfterRelay = + await env.eth.fuelMessagePortal.currentPeriodEnd(); - // expect(currentPeriodEndAfterRelay > currentPeriodEndBeforeRelay).to.be - // .true; + expect(currentPeriodEndAfterRelay > currentPeriodEndBeforeRelay).to.be + .true; - // const currentPeriodAmount = - // await env.eth.fuelMessagePortal.currentPeriodAmount(); + const currentPeriodAmount = + await env.eth.fuelMessagePortal.currentPeriodAmount(); - // expect(currentPeriodAmount === parseEther(NUM_ETH)).to.be.true; + expect(currentPeriodAmount === parseEther(NUM_ETH)).to.be.true; }); it('Rate limit parameters are updated when new limit is set after the initial duration', async () => { @@ -505,30 +496,25 @@ describe('Transferring ETH', async function () { ]); await env.eth.provider.send('evm_mine', []); // Mine a new block - console.log("reset limit") - await env.eth.fuelMessagePortal .connect(deployer) .resetRateLimitAmount(parseEther(newRateLimit)); - console.log("reset done") - - const currentPeriodEndAfterSettingLimit = await env.eth.fuelMessagePortal.currentPeriodEnd(); const currentWithdrawnAmountAfterSettingLimit = await env.eth.fuelMessagePortal.currentPeriodAmount(); - // expect( - // currentPeriodEndAfterSettingLimit > currentPeriodEndBeforeSettingLimit - // ).to.be.true; + expect( + currentPeriodEndAfterSettingLimit > currentPeriodEndBeforeSettingLimit + ).to.be.true; - // expect( - // currentWithdrawnAmountBeforeSettingLimit > - // currentWithdrawnAmountAfterSettingLimit - // ).to.be.true; + expect( + currentWithdrawnAmountBeforeSettingLimit > + currentWithdrawnAmountAfterSettingLimit + ).to.be.true; - // expect(currentWithdrawnAmountAfterSettingLimit == 0n).to.be.true; + expect(currentWithdrawnAmountAfterSettingLimit == 0n).to.be.true; }); }); }); From 98afdf2a341e977410e235c1a9af79a23f27686f Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 31 Dec 2024 21:45:48 +0530 Subject: [PATCH 18/36] chore: add changeset --- .changeset/thin-ways-dress.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/thin-ways-dress.md diff --git a/.changeset/thin-ways-dress.md b/.changeset/thin-ways-dress.md new file mode 100644 index 00000000..33a25e4b --- /dev/null +++ b/.changeset/thin-ways-dress.md @@ -0,0 +1,6 @@ +--- +'@fuel-bridge/solidity-contracts': minor +'@fuel-bridge/test-utils': minor +--- + +ci for contract upgrade test suite From 666ccc6a523b41847c12d3184031d40bbd383b83 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Wed, 1 Jan 2025 11:53:32 +0530 Subject: [PATCH 19/36] chore: formatting --- .../solidity-contracts/integration-tests/bridge_erc20.ts | 6 +++--- .../solidity-contracts/integration-tests/transfer_eth.ts | 2 +- packages/test-utils/src/utils/setup.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/solidity-contracts/integration-tests/bridge_erc20.ts b/packages/solidity-contracts/integration-tests/bridge_erc20.ts index fa6dc64f..c1fe6d66 100644 --- a/packages/solidity-contracts/integration-tests/bridge_erc20.ts +++ b/packages/solidity-contracts/integration-tests/bridge_erc20.ts @@ -146,7 +146,7 @@ describe('Bridging ERC20 tokens', async function () { const commitHeight = new BN(nextBlockHeight).div(blocksPerCommitInterval); let cooldown = await env.eth.fuelChainState.COMMIT_COOLDOWN(); - + // fast forward post the commit cooldown period await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour await env.eth.provider.send('evm_mine', []); // Mine a new block @@ -158,7 +158,7 @@ describe('Bridging ERC20 tokens', async function () { '0x0000000000000000000000000000000000000000000000000000000000000000', commitHeight.toString() ); - + // fast forward to the block finalization time await env.eth.provider.send('evm_increaseTime', [ Number(TIME_TO_FINALIZE) * 2, @@ -170,7 +170,7 @@ describe('Bridging ERC20 tokens', async function () { // fast forward post the commit cooldown period await env.eth.provider.send('evm_increaseTime', [Number(cooldown) * 10]); // Advance 1 hour await env.eth.provider.send('evm_mine', []); // Mine a new block - + // produce more blocks to fetch the block height await forwardFuelChain(env.fuel.provider, blocksPerCommitInterval); diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts index 73d03caf..786a2e56 100644 --- a/packages/solidity-contracts/integration-tests/transfer_eth.ts +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -163,7 +163,7 @@ describe('Transferring ETH', async function () { const relayMessageParams = createRelayMessageParams(withdrawMessageProof); const TIME_TO_FINALIZE = await env.eth.fuelChainState.TIME_TO_FINALIZE(); - + // fast forward to the block finalization time await env.eth.provider.send('evm_increaseTime', [ Number(TIME_TO_FINALIZE) * 100, diff --git a/packages/test-utils/src/utils/setup.ts b/packages/test-utils/src/utils/setup.ts index 3882ef7e..6a1c2adc 100644 --- a/packages/test-utils/src/utils/setup.ts +++ b/packages/test-utils/src/utils/setup.ts @@ -326,4 +326,4 @@ export async function setupEnvironment( signers: [fuel_signer1, fuel_signer2], }, }; -} \ No newline at end of file +} From 51f7a9f9968597173ed6cc2f59ab4f1b5832d85b Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 12:45:04 +0530 Subject: [PATCH 20/36] chore: update forc version --- .github/actions/setup-rust/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index 7fdbe222..87736a64 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -4,7 +4,7 @@ inputs: rust-version: default: 1.81.0 forc-components: - default: 'forc@0.63.4, fuel-core@0.36.0' + default: 'forc@0.66.5, fuel-core@0.36.0' runs: using: 'composite' From 1d537929b25a9f3032b48e17e0feebaafd7917fe Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 13:08:09 +0530 Subject: [PATCH 21/36] chore: debug format check in ci --- .github/actions/setup-rust/action.yml | 2 +- scripts/check.sh | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index 87736a64..7fdbe222 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -4,7 +4,7 @@ inputs: rust-version: default: 1.81.0 forc-components: - default: 'forc@0.66.5, fuel-core@0.36.0' + default: 'forc@0.63.4, fuel-core@0.36.0' runs: using: 'composite' diff --git a/scripts/check.sh b/scripts/check.sh index f2f4be9b..e3690eef 100644 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -1,6 +1,5 @@ #!/bin/bash -pnpm forc fmt --check cargo fmt --check pnpm forc build --release cargo clippy --all-features --all-targets -- -D warnings From a13443550e8d534c858abce7e5404fb3fb4ce76c Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 13:31:31 +0530 Subject: [PATCH 22/36] chore: ts lint fixes --- .../deploy/hardhat/008.set_canonical_token_bytecode.ts | 1 + .../deploy/hardhat/999.serve_deployment_file.ts | 3 +-- packages/solidity-contracts/integration-tests/transfer_eth.ts | 2 -- packages/test-utils/src/utils/setup.ts | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/solidity-contracts/deploy/hardhat/008.set_canonical_token_bytecode.ts b/packages/solidity-contracts/deploy/hardhat/008.set_canonical_token_bytecode.ts index 698cf33d..f7ec8ccb 100644 --- a/packages/solidity-contracts/deploy/hardhat/008.set_canonical_token_bytecode.ts +++ b/packages/solidity-contracts/deploy/hardhat/008.set_canonical_token_bytecode.ts @@ -1,5 +1,6 @@ import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import type { DeployFunction } from 'hardhat-deploy/dist/types'; + import { USDT_ADDRESS, USDC_ADDRESS, diff --git a/packages/solidity-contracts/deploy/hardhat/999.serve_deployment_file.ts b/packages/solidity-contracts/deploy/hardhat/999.serve_deployment_file.ts index 79b4a47b..4a2fbc64 100644 --- a/packages/solidity-contracts/deploy/hardhat/999.serve_deployment_file.ts +++ b/packages/solidity-contracts/deploy/hardhat/999.serve_deployment_file.ts @@ -1,5 +1,4 @@ -import fs from 'fs'; -import { writeFile } from 'fs'; +import fs, { writeFile } from 'fs'; import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import type { DeployFunction } from 'hardhat-deploy/dist/types'; import path from 'path'; diff --git a/packages/solidity-contracts/integration-tests/transfer_eth.ts b/packages/solidity-contracts/integration-tests/transfer_eth.ts index 786a2e56..eed3f7b8 100644 --- a/packages/solidity-contracts/integration-tests/transfer_eth.ts +++ b/packages/solidity-contracts/integration-tests/transfer_eth.ts @@ -450,8 +450,6 @@ describe('Transferring ETH', async function () { }); it('Rate limit parameters are updated when the initial duration is over', async () => { - const deployer = await env.eth.signers[0]; - // fast forward time await env.eth.provider.send('evm_increaseTime', [ Number(rateLimitDuration) * 2, diff --git a/packages/test-utils/src/utils/setup.ts b/packages/test-utils/src/utils/setup.ts index 6a1c2adc..e05d08f8 100644 --- a/packages/test-utils/src/utils/setup.ts +++ b/packages/test-utils/src/utils/setup.ts @@ -13,7 +13,7 @@ import { FuelERC721Gateway__factory, } from '@fuel-bridge/solidity-contracts/typechain'; import * as dotenv from 'dotenv'; -import type { Signer as EthSigner, Provider as EthProvider } from 'ethers'; +import type { Signer as EthSigner } from 'ethers'; import { JsonRpcProvider, ethers, From 417733cbe93e14afc15053882b9cf4461a3a6e6d Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 13:56:08 +0530 Subject: [PATCH 23/36] chore: update check shell script --- scripts/check.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/check.sh b/scripts/check.sh index e3690eef..f2f4be9b 100644 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -1,5 +1,6 @@ #!/bin/bash +pnpm forc fmt --check cargo fmt --check pnpm forc build --release cargo clippy --all-features --all-targets -- -D warnings From 2ada6f56864baa9965299b7fa805218fc95a3ed8 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 15:45:42 +0530 Subject: [PATCH 24/36] chore: update order of commands in check script --- scripts/check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check.sh b/scripts/check.sh index f2f4be9b..fdc25a02 100644 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -1,8 +1,8 @@ #!/bin/bash -pnpm forc fmt --check cargo fmt --check pnpm forc build --release +pnpm forc fmt --check cargo clippy --all-features --all-targets -- -D warnings pnpm prettier:check pnpm lint:check From 430bce2c8d35effdfa26602ce238678dac226293 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 16:29:23 +0530 Subject: [PATCH 25/36] chore: debug forc formatting --- .github/workflows/pr.yml | 3 +++ scripts/check.sh | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7d0bdfd1..21d05c6e 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -73,6 +73,9 @@ jobs: - name: Build projects run: pnpm build + - name: Forc formatting + run: forc fmt --check + - name: Check projects formatting run: pnpm check diff --git a/scripts/check.sh b/scripts/check.sh index fdc25a02..f2f4be9b 100644 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -1,8 +1,8 @@ #!/bin/bash +pnpm forc fmt --check cargo fmt --check pnpm forc build --release -pnpm forc fmt --check cargo clippy --all-features --all-targets -- -D warnings pnpm prettier:check pnpm lint:check From da63952f20b2b588ce1be8e39a19ac0e37a24b2b Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 17:31:02 +0530 Subject: [PATCH 26/36] chore: remove --check --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 21d05c6e..4d42e03f 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -74,7 +74,7 @@ jobs: run: pnpm build - name: Forc formatting - run: forc fmt --check + run: forc fmt - name: Check projects formatting run: pnpm check From e933a2e81f0696f89b809710ec6bf25d36d48265 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 17:48:07 +0530 Subject: [PATCH 27/36] chore: update forc command --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4d42e03f..fc4e8516 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -74,7 +74,7 @@ jobs: run: pnpm build - name: Forc formatting - run: forc fmt + run: forc-fmt --check - name: Check projects formatting run: pnpm check From 08917b8c072dfb66f4b142c1a625d8e920891da2 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 19:48:29 +0530 Subject: [PATCH 28/36] chore: add build command --- .github/workflows/pr.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index fc4e8516..1fe74699 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -69,9 +69,12 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup-rust + + - name: Forc Build + run: forc build --release - name: Build projects - run: pnpm build + run: pnpm build - name: Forc formatting run: forc-fmt --check From 6348e3861e4350e19c9f0e46ba0b97f4cc2ddfd6 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Thu, 2 Jan 2025 21:49:18 +0530 Subject: [PATCH 29/36] chore: remove forc lock files in ci --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 1fe74699..d56559f2 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -77,7 +77,7 @@ jobs: run: pnpm build - name: Forc formatting - run: forc-fmt --check + run: rm -rf ~/.forc/.lsp-locks/ && forc-fmt --check - name: Check projects formatting run: pnpm check From c4d176b2d42a5563233563219080a3741ede5c20 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 3 Jan 2025 11:21:23 +0530 Subject: [PATCH 30/36] chore: update installation for forc-fmt --- .github/actions/setup-rust/action.yml | 10 +++++----- .github/workflows/pr.yml | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index 7fdbe222..472338e8 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -19,8 +19,8 @@ runs: - name: Init cache uses: Swatinem/rust-cache@v2 - - name: Install Fuel toolchain - uses: FuelLabs/action-fuel-toolchain@v0.6.0 - with: - name: fuel-bridge - components: ${{ inputs.forc-components }} + # - name: Install Fuel toolchain + # uses: FuelLabs/action-fuel-toolchain@v0.6.0 + # with: + # name: fuel-bridge + # components: ${{ inputs.forc-components }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index d56559f2..de5bd644 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -69,9 +69,21 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup-rust + + - name: Forc Build + run: | + curl -sSLf https://github.com/FuelLabs/sway/releases/download/v${{ env.FORC_VERSION }}/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz + tar -xvf forc.tar.gz + chmod +x forc-binaries/forc + mv forc-binaries/forc /usr/local/bin/forc + mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt + forc-fmt --check + fi + - name: Forc Build run: forc build --release + - name: Build projects run: pnpm build From 8ff85d20a3ad904225c2337b75ba38350bd676f7 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 3 Jan 2025 11:34:06 +0530 Subject: [PATCH 31/36] chore: test ci --- .github/workflows/upgrade-test-suite.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/upgrade-test-suite.yml b/.github/workflows/upgrade-test-suite.yml index 82ec5a43..dc320a82 100644 --- a/.github/workflows/upgrade-test-suite.yml +++ b/.github/workflows/upgrade-test-suite.yml @@ -29,6 +29,15 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup-rust + - name: Forc Build + run: | + curl -sSLf https://github.com/FuelLabs/sway/releases/download/v${{ env.FORC_VERSION }}/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz + tar -xvf forc.tar.gz + chmod +x forc-binaries/forc + mv forc-binaries/forc /usr/local/bin/forc + mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt + forc-fmt --check + fi - name: Build project run: pnpm build - name: Sets the tenderly rpc endpoint in the L1 docker container env From e31d697d2d1b1caf5e3d8f4e77fe582d5ba5ea91 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 3 Jan 2025 11:52:31 +0530 Subject: [PATCH 32/36] chore: test ci --- .github/actions/setup-rust/action.yml | 8 +++++++- .github/workflows/upgrade-test-suite.yml | 11 ++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index 472338e8..f983c781 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -19,7 +19,13 @@ runs: - name: Init cache uses: Swatinem/rust-cache@v2 - # - name: Install Fuel toolchain + - name: Install Fuel toolchain + run: | + curl -sSLf https://github.com/FuelLabs/sway/releases/download/v${{ env.FORC_VERSION }}/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz + tar -xvf forc.tar.gz + chmod +x forc-binaries/forc + mv forc-binaries/forc /usr/local/bin/forc + mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt # uses: FuelLabs/action-fuel-toolchain@v0.6.0 # with: # name: fuel-bridge diff --git a/.github/workflows/upgrade-test-suite.yml b/.github/workflows/upgrade-test-suite.yml index dc320a82..74cff881 100644 --- a/.github/workflows/upgrade-test-suite.yml +++ b/.github/workflows/upgrade-test-suite.yml @@ -29,15 +29,8 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup-rust - - name: Forc Build - run: | - curl -sSLf https://github.com/FuelLabs/sway/releases/download/v${{ env.FORC_VERSION }}/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz - tar -xvf forc.tar.gz - chmod +x forc-binaries/forc - mv forc-binaries/forc /usr/local/bin/forc - mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt - forc-fmt --check - fi + - name: project + run: forc-fmt --check - name: Build project run: pnpm build - name: Sets the tenderly rpc endpoint in the L1 docker container env From 396622d172e8d8112507b072aaa0417e6db16de4 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 3 Jan 2025 12:06:30 +0530 Subject: [PATCH 33/36] chore: minor update --- .github/actions/setup-rust/action.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index f983c781..da808252 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -16,8 +16,16 @@ runs: components: clippy, rustfmt targets: wasm32-unknown-unknown - - name: Init cache - uses: Swatinem/rust-cache@v2 + # - name: Init cache + # uses: Swatinem/rust-cache@v2 + + - uses: buildjet/cache@v3 + with: + prefix-key: "v1-rust" + + - name: Set git config + run: | + git config --global core.bigfilethreshold 100m - name: Install Fuel toolchain run: | From 537f38a83ae69c540405fadc2ea19c0cd3440de7 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 3 Jan 2025 12:10:35 +0530 Subject: [PATCH 34/36] chore: small touchup in action.yml --- .github/actions/setup-rust/action.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index da808252..f494d981 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -26,14 +26,16 @@ runs: - name: Set git config run: | git config --global core.bigfilethreshold 100m + shell: bash - name: Install Fuel toolchain run: | - curl -sSLf https://github.com/FuelLabs/sway/releases/download/v${{ env.FORC_VERSION }}/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz - tar -xvf forc.tar.gz - chmod +x forc-binaries/forc - mv forc-binaries/forc /usr/local/bin/forc - mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt + curl -sSLf https://github.com/FuelLabs/sway/releases/download/v0.66.5/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz + tar -xvf forc.tar.gz + chmod +x forc-binaries/forc + mv forc-binaries/forc /usr/local/bin/forc + mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt + shell: bash # uses: FuelLabs/action-fuel-toolchain@v0.6.0 # with: # name: fuel-bridge From 861d437a2199b293ac636a2902e194818a975815 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 3 Jan 2025 12:21:26 +0530 Subject: [PATCH 35/36] chore: revert workflow changes --- .github/actions/setup-rust/action.yml | 28 +++++------------------- .github/workflows/pr.yml | 22 ++----------------- .github/workflows/upgrade-test-suite.yml | 2 -- scripts/build.sh | 1 + 4 files changed, 9 insertions(+), 44 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index f494d981..8e2bae1a 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -16,27 +16,11 @@ runs: components: clippy, rustfmt targets: wasm32-unknown-unknown - # - name: Init cache - # uses: Swatinem/rust-cache@v2 - - - uses: buildjet/cache@v3 - with: - prefix-key: "v1-rust" - - - name: Set git config - run: | - git config --global core.bigfilethreshold 100m - shell: bash + - name: Init cache + uses: Swatinem/rust-cache@v2 - name: Install Fuel toolchain - run: | - curl -sSLf https://github.com/FuelLabs/sway/releases/download/v0.66.5/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz - tar -xvf forc.tar.gz - chmod +x forc-binaries/forc - mv forc-binaries/forc /usr/local/bin/forc - mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt - shell: bash - # uses: FuelLabs/action-fuel-toolchain@v0.6.0 - # with: - # name: fuel-bridge - # components: ${{ inputs.forc-components }} + uses: FuelLabs/action-fuel-toolchain@v0.6.0 + with: + name: fuel-bridge + components: ${{ inputs.forc-components }} \ No newline at end of file diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index de5bd644..fa5667e6 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -70,26 +70,8 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup-rust - - name: Forc Build - run: | - curl -sSLf https://github.com/FuelLabs/sway/releases/download/v${{ env.FORC_VERSION }}/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz - tar -xvf forc.tar.gz - chmod +x forc-binaries/forc - mv forc-binaries/forc /usr/local/bin/forc - mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt - forc-fmt --check - fi - - - - name: Forc Build - run: forc build --release - - - name: Build projects - run: pnpm build - - - name: Forc formatting - run: rm -rf ~/.forc/.lsp-locks/ && forc-fmt --check + run: pnpm build - name: Check projects formatting run: pnpm check @@ -100,4 +82,4 @@ jobs: # TODO issue 115: https://github.com/FuelLabs/fuel-bridge/issues/115 # Run test again to ensure it works with node that already has transactions/messages # - name: Test projects Again - # run: pnpm --filter @fuel-bridge/integration-tests test + # run: pnpm --filter @fuel-bridge/integration-tests test \ No newline at end of file diff --git a/.github/workflows/upgrade-test-suite.yml b/.github/workflows/upgrade-test-suite.yml index 74cff881..82ec5a43 100644 --- a/.github/workflows/upgrade-test-suite.yml +++ b/.github/workflows/upgrade-test-suite.yml @@ -29,8 +29,6 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup-rust - - name: project - run: forc-fmt --check - name: Build project run: pnpm build - name: Sets the tenderly rpc endpoint in the L1 docker container env diff --git a/scripts/build.sh b/scripts/build.sh index 4e93b7d2..2642c39a 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -3,3 +3,4 @@ forc build --release cargo run --bin fuel-contract-message-predicate turbo run build +pnpm forc fmt --check From 38ba169230bbc2fbc24fe3799fff8cced13975bb Mon Sep 17 00:00:00 2001 From: viraj124 Date: Fri, 3 Jan 2025 13:04:59 +0530 Subject: [PATCH 36/36] chore: update fmt command --- scripts/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 2642c39a..7fcb21b0 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,6 +1,6 @@ #!/bin/bash forc build --release +pnpm forc fmt --path packages/message-predicates --check cargo run --bin fuel-contract-message-predicate -turbo run build -pnpm forc fmt --check +turbo run build \ No newline at end of file