From 77363a2b3b32ff9acff4a498fc4c67242c359785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAkira-Taniguchi=E2=80=9D?= <“dededededaiou2003@yahoo.co.jp”> Date: Mon, 2 Feb 2026 15:09:05 +0900 Subject: [PATCH] update doc --- .gitignore | 2 ++ AGENTS.md | 25 ++++++++++++-- README.md | 58 +++++++++++++++++++++++++++++++-- deploy/deploy.sh | 85 ++++++++++++++++++++++++++---------------------- 4 files changed, 128 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index dc7dbc9..6790e2c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ out/ # Dotenv file .env + +node_modules/ diff --git a/AGENTS.md b/AGENTS.md index eae1a1e..90d393b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -92,12 +92,33 @@ forge build ### Deploy +**Option 1: Using shell script** + ```bash -# Deploy to a specific network ./deploy/deploy.sh -# Example +# Examples: ./deploy/deploy.sh sepolia +./deploy/deploy.sh arbitrum-sepolia +./deploy/deploy.sh base-sepolia +``` + +**Option 2: Using forge directly** + +```bash +source .env +forge script script/Deploy.s.sol --rpc-url $RPC_URL_SEPOLIA --broadcast -vvv +``` + +### Verify + +After deployment, verify the contract on the block explorer: + +```bash +forge verify-contract src/CREATE3Factory.sol:CREATE3Factory \ + --rpc-url $RPC_URL_SEPOLIA \ + --etherscan-api-key $ETHERSCAN_KEY \ + --watch ``` ## Important Technical Details diff --git a/README.md b/README.md index 8109323..65b9b2e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,22 @@ One could use a `CREATE2` factory that deterministically deploys contracts to an A `CREATE3` factory offers the best solution: the address of the deployed contract is determined by only the deployer address and the salt. This makes it far easier to deploy contracts to multiple chains at the same addresses. +## How This Factory is Deployed + +This factory uses **CREATE2** for deployment to ensure the same factory address across all chains without nonce synchronization: + +```solidity +bytes32 salt = keccak256("intmax"); +factory = new CREATE3Factory{salt: salt}(); +``` + +The factory address is determined by: +- Deployer address (from PRIVATE_KEY) +- Salt ("intmax") +- Factory bytecode (deterministic via `bytecode_hash = "none"` in foundry.toml) + +**Nonce does not affect the address**, so you can deploy to new chains at any time. + ## Supported Chains | Mainnet | Testnet | @@ -62,8 +78,46 @@ forge build ### Deployment -Make sure that the network is defined in foundry.toml, then run: +1. Copy `.env.example` to `.env` and fill in the values: + +```bash +cp .env.example .env +``` + +2. Set up your environment variables: + +```bash +PRIVATE_KEY= +RPC_URL_SEPOLIA= +ETHERSCAN_KEY= +# ... other networks as needed +``` + +3. Deploy using the shell script: + +```bash +./deploy/deploy.sh + +# Examples: +./deploy/deploy.sh sepolia +./deploy/deploy.sh arbitrum-sepolia +./deploy/deploy.sh base-sepolia +``` + +4. Or deploy directly with forge: + +```bash +source .env +forge script script/Deploy.s.sol --rpc-url $RPC_URL_SEPOLIA --broadcast -vvv +``` + +### Verification + +After deployment, verify the contract: ```bash -./deploy/deploy.sh [network] +forge verify-contract src/CREATE3Factory.sol:CREATE3Factory \ + --rpc-url $RPC_URL_SEPOLIA \ + --etherscan-api-key $ETHERSCAN_KEY \ + --watch ``` diff --git a/deploy/deploy.sh b/deploy/deploy.sh index 9e978d5..0ebf3f5 100755 --- a/deploy/deploy.sh +++ b/deploy/deploy.sh @@ -8,53 +8,51 @@ deploy() { # get deployer address DEPLOYER_ADDRESS=$(cast wallet address "$PRIVATE_KEY") - echo "You are deploying from address: $DEPLOYER_ADDRESS (should be 0x11F11121DF7256C40339393b0FB045321022ce44 for 0x123 diamond address)" - - # get balance in given network - RPC_KEY="RPC_URL_$(tr '[:lower:]' '[:upper:]' <<<"$NETWORK")" - BALANCE=$(cast balance "$DEPLOYER_ADDRESS" --rpc-url "${!RPC_KEY}") - - # return formatted balance - echo "Deployer Wallet balance: $(echo "scale=10;$BALANCE / 1000000000000000000" | bc)" - - echo "" - echo "@DEV: You may run into an error about verification (missing Etherscan key for chainId ... or other errors)." - echo " If you cannot fix it, remove the --verify flag and verify the contract manually afterwards. This needs to be fixed." - echo "" - # Ticket for this issue: https://lifi.atlassian.net/browse/LF-12359 - - RAW_RETURN_DATA=$(forge script script/Deploy.s.sol -f $NETWORK -vvvv --json --legacy --broadcast --skip-simulation --gas-limit 2000000) - RETURN_CODE=$? - echo "RAW_RETURN_DATA: $RAW_RETURN_DATA" - CLEAN_RETURN_DATA=$(echo $RAW_RETURN_DATA | sed 's/^.*{\"logs/{\"logs/') - echo "RAW_RETURN_DATA: $RAW_RETURN_DATA" - RETURN_DATA=$(echo $CLEAN_RETURN_DATA | jq -r '.returns' 2>/dev/null) - echo "" - echo "RETURN_DATA: $RETURN_DATA" + echo "Deployer address: $DEPLOYER_ADDRESS" + + # get RPC URL for the network + RPC_KEY="RPC_URL_$(echo "$NETWORK" | tr '[:lower:]' '[:upper:]' | tr '-' '_')" + RPC_URL="${!RPC_KEY}" + + if [[ -z "$RPC_URL" ]]; then + echo "❌ Error: RPC URL not found for network: $NETWORK" + echo " Please set $RPC_KEY in your .env file" + exit 1 + fi + + # get balance + BALANCE=$(cast balance "$DEPLOYER_ADDRESS" --rpc-url "$RPC_URL") + echo "Balance: $(echo "scale=6;$BALANCE / 1000000000000000000" | bc) ETH" echo "" + # deploy + echo "Deploying to $NETWORK..." + RAW_RETURN_DATA=$(forge script script/Deploy.s.sol --rpc-url "$RPC_URL" --broadcast --json 2>&1) + RETURN_CODE=$? + if [[ $RETURN_CODE -ne 0 ]]; then echo "❌ Error: deployment was not successful" + echo "$RAW_RETURN_DATA" exit 1 fi - FACTORY_ADDRESS=$(echo $RETURN_DATA | jq -r '.factory.value') - echo "✅ Successfully deployed to address $FACTORY_ADDRESS" + # extract factory address + CLEAN_RETURN_DATA=$(echo "$RAW_RETURN_DATA" | grep -o '{.*}' | tail -1) + FACTORY_ADDRESS=$(echo "$CLEAN_RETURN_DATA" | jq -r '.returns.factory.value' 2>/dev/null) - # verify contract - API_KEY="$(tr '[:lower:]' '[:upper:]' <<<$NETWORK)_API_KEY" - API_KEY="${!API_KEY}" - echo "" - # not working as intended, we need to fix this - # echo "Trying to verify contract now with API key: $API_KEY" - # forge verify-contract "$FACTORY_ADDRESS" src/CREATE3Factory.sol:CREATE3Factory --watch --etherscan-api-key "$API_KEY" --chain "$NETWORK" - echo "" + if [[ -z "$FACTORY_ADDRESS" || "$FACTORY_ADDRESS" == "null" ]]; then + echo "⚠️ Could not parse factory address from output" + echo "Please check the broadcast folder for the deployed address" + else + echo "✅ Successfully deployed to address: $FACTORY_ADDRESS" - echo "" - echo "Creating deploy log" - saveContract $NETWORK CREATE3Factory $FACTORY_ADDRESS + # save to deployments + saveContract "$NETWORK" "CREATE3Factory" "$FACTORY_ADDRESS" + fi - echo "✅ Deployment successfully completed" + echo "" + echo "To verify the contract, run:" + echo " forge verify-contract $FACTORY_ADDRESS src/CREATE3Factory.sol:CREATE3Factory --rpc-url \$RPC_URL_$(echo "$NETWORK" | tr '[:lower:]' '[:upper:]' | tr '-' '_') --etherscan-api-key --watch" } saveContract() { @@ -70,6 +68,17 @@ saveContract() { fi result=$(cat "$ADDRESSES_FILE" | jq -r ". + {\"$CONTRACT\": \"$ADDRESS\"}") printf %s "$result" >"$ADDRESSES_FILE" + echo "📝 Saved to $ADDRESSES_FILE" } -deploy $1 +# check if network argument is provided +if [[ -z "$1" ]]; then + echo "Usage: ./deploy/deploy.sh " + echo "" + echo "Available networks:" + echo " Mainnet: mainnet, arbitrum, base, bsc, scroll" + echo " Testnet: sepolia, arbitrum-sepolia, base-sepolia, bsc-testnet, scroll-sepolia" + exit 1 +fi + +deploy "$1"