chore: sync submodule state (parent ref update)
Made-with: Cursor
This commit is contained in:
79
scripts/SEND_20M_TOKENS_README.md
Normal file
79
scripts/SEND_20M_TOKENS_README.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Send 20M cUSDT and cUSDC Script
|
||||
|
||||
## Overview
|
||||
|
||||
This script sends 20,000,000 cUSDT and 20,000,000 cUSDC tokens to the specified wallet address.
|
||||
|
||||
**Recipient Address:** `0x4207aA9aC89B8bF4795dbAbBbE17fdd224E7947C`
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
cd /home/intlc/projects/proxmox/smom-dbis-138
|
||||
./scripts/send-20m-tokens.sh
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Checks Deployer Balance**: Verifies if the deployer address has sufficient tokens
|
||||
2. **Smart Minting/Transfer**:
|
||||
- If deployer has sufficient balance: Transfers tokens from deployer to recipient
|
||||
- If deployer has insufficient balance: Mints tokens directly to recipient (requires owner role)
|
||||
3. **Verification**: Confirms the transfers by checking recipient balances
|
||||
|
||||
## Token Details
|
||||
|
||||
- **cUSDT Address**: `0x93E66202A11B1772E55407B32B44e5Cd8eda7f22`
|
||||
- **cUSDC Address**: `0xf22258f57794CC8E06237084b353Ab30fFfa640b`
|
||||
- **Amount**: 20,000,000 tokens each (20000000000000 in base units with 6 decimals)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. `.env` file must exist in the project root with:
|
||||
- `PRIVATE_KEY`: Private key of the deployer/owner
|
||||
- `RPC_URL` or `RPC_URL_138`: RPC endpoint URL
|
||||
- `COMPLIANT_USDT_ADDRESS`: cUSDT contract address (optional, has defaults)
|
||||
- `COMPLIANT_USDC_ADDRESS`: cUSDC contract address (optional, has defaults)
|
||||
|
||||
2. The deployer address must be the owner of both token contracts (for minting)
|
||||
|
||||
3. RPC endpoint must be accessible
|
||||
|
||||
## Expected Output
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ Send 20M cUSDT and cUSDC ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
|
||||
Deployer Address: 0x...
|
||||
Recipient Address: 0x4207aA9aC89B8bF4795dbAbBbE17fdd224E7947C
|
||||
Amount: 20,000,000 tokens (each)
|
||||
|
||||
Checking balances...
|
||||
Deployer cUSDT Balance: X tokens
|
||||
Deployer cUSDC Balance: X tokens
|
||||
|
||||
Minting 20M cUSDT to recipient...
|
||||
✓ cUSDT mint successful
|
||||
Transaction Hash: 0x...
|
||||
|
||||
Minting 20M cUSDC to recipient...
|
||||
✓ cUSDC mint successful
|
||||
Transaction Hash: 0x...
|
||||
|
||||
Verifying transfers...
|
||||
Recipient cUSDT Balance: 20000000.00 tokens
|
||||
Recipient cUSDC Balance: 20000000.00 tokens
|
||||
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ Transfers Complete! ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The script uses `cast` from Foundry
|
||||
- Gas price is set to 20 gwei (20000000000)
|
||||
- Transactions use legacy format
|
||||
- Script will exit on any error
|
||||
@@ -50,6 +50,16 @@ contract InitializeRegistry is Script {
|
||||
address(0x200)
|
||||
);
|
||||
|
||||
// Register Etherlink (Tezos EVM L2)
|
||||
registry.registerDestination(
|
||||
42793,
|
||||
"Etherlink Mainnet",
|
||||
1,
|
||||
1800,
|
||||
10,
|
||||
address(0x200)
|
||||
);
|
||||
|
||||
// Register XRPL
|
||||
registry.registerDestination(
|
||||
0,
|
||||
@@ -60,13 +70,25 @@ contract InitializeRegistry is Script {
|
||||
address(0x200)
|
||||
);
|
||||
|
||||
// Register native ETH token
|
||||
uint256[] memory allDestinations = new uint256[](5);
|
||||
// Register Tezos L1 (non-EVM; chainId 1 in registry for non-EVM slot)
|
||||
registry.registerDestination(
|
||||
1,
|
||||
"Tezos-Mainnet",
|
||||
1,
|
||||
300,
|
||||
20,
|
||||
address(0x200)
|
||||
);
|
||||
|
||||
// Register native ETH token (Polygon, Optimism, Base, Arbitrum, Etherlink, XRPL, Tezos)
|
||||
uint256[] memory allDestinations = new uint256[](7);
|
||||
allDestinations[0] = 137;
|
||||
allDestinations[1] = 10;
|
||||
allDestinations[2] = 8453;
|
||||
allDestinations[3] = 42161;
|
||||
allDestinations[4] = 0;
|
||||
allDestinations[4] = 42793;
|
||||
allDestinations[5] = 0;
|
||||
allDestinations[6] = 1;
|
||||
|
||||
registry.registerToken(
|
||||
address(0), // Native ETH
|
||||
|
||||
15
scripts/bridge/register-iso-deposit-tokens.sh
Executable file
15
scripts/bridge/register-iso-deposit-tokens.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# B7: Register ISO-4217W tokens with BridgeRegistry (BRG-ISO)
|
||||
# Requires: PRIVATE_KEY, RPC_URL_138, USDW_ADDRESS, EURW_ADDRESS, BRIDGE_REGISTRY_ADDRESS
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../.."
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
: "${PRIVATE_KEY:?PRIVATE_KEY required}"
|
||||
: "${RPC_URL_138:?RPC_URL_138 required}"
|
||||
: "${BRIDGE_REGISTRY_ADDRESS:?BRIDGE_REGISTRY_ADDRESS required}"
|
||||
|
||||
echo "Registering ISO-4217W tokens (USDW, EURW, GBPW) with BridgeRegistry..."
|
||||
echo "Use cast send to call bridgeRegistry.registerToken(token, ...)"
|
||||
echo "Note: Include 42793 (Etherlink) and 1 (Tezos L1) in allowedDestinations when registering tokens for Tezos bridging."
|
||||
17
scripts/bridge/register-vault-deposit-tokens.sh
Executable file
17
scripts/bridge/register-vault-deposit-tokens.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# B6: Register Vault deposit tokens with BridgeRegistry (BRG-VLT)
|
||||
# Requires: PRIVATE_KEY, RPC_URL_138, VAULT_BRIDGE_INTEGRATION_ADDRESS, BRIDGE_REGISTRY_ADDRESS
|
||||
# Run after deploying Vault system and VaultBridgeIntegration
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../.."
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
: "${PRIVATE_KEY:?PRIVATE_KEY required}"
|
||||
: "${RPC_URL_138:?RPC_URL_138 required}"
|
||||
: "${VAULT_BRIDGE_INTEGRATION_ADDRESS:?VAULT_BRIDGE_INTEGRATION_ADDRESS required}"
|
||||
|
||||
echo "Registering Vault deposit tokens with BridgeRegistry..."
|
||||
echo "VaultBridgeIntegration: $VAULT_BRIDGE_INTEGRATION_ADDRESS"
|
||||
echo "Use cast send to call registerDepositToken(depositToken, chainIds, min, max, riskLevel, feeBps)"
|
||||
echo "Note: defaultDestinations in VaultBridgeIntegration include 42793 (Etherlink); for Tezos L1 include chainId 1 in allowedDestinations when registering tokens."
|
||||
44
scripts/ccip-deployment/deploy-ccip-logger-multichain.js
Normal file
44
scripts/ccip-deployment/deploy-ccip-logger-multichain.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Deploy CCIPLogger to a configurable network (Mainnet, BSC, Polygon, Gnosis, Cronos).
|
||||
* Usage: NETWORK=bsc npx hardhat run scripts/ccip-deployment/deploy-ccip-logger-multichain.js
|
||||
*
|
||||
* Prerequisites:
|
||||
* - contracts/ccip-integration/CCIPLogger.sol must exist (currently missing - see TASK12_CCIP_LOGGER_STATUS.md)
|
||||
* - PRIVATE_KEY in .env
|
||||
* - Chain-specific RPC and CCIP Router in .env (e.g. CCIP_BSC_ROUTER for BSC)
|
||||
*/
|
||||
require("dotenv").config();
|
||||
const network = process.env.NETWORK || process.env.HARDHAT_NETWORK || "mainnet";
|
||||
|
||||
const ROUTERS = {
|
||||
mainnet: process.env.CCIP_ETH_ROUTER || "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D",
|
||||
bsc: process.env.CCIP_BSC_ROUTER || "",
|
||||
polygon: process.env.CCIP_POLYGON_ROUTER || "",
|
||||
gnosis: process.env.CCIP_GNOSIS_ROUTER || "",
|
||||
cronos: process.env.CCIP_CRONOS_ROUTER || "0xE26B0A098D861d5C7d9434aD471c0572Ca6EAa67",
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const { ethers } = require("hardhat");
|
||||
const routerAddress = ROUTERS[network] || ROUTERS.mainnet;
|
||||
if (!routerAddress) {
|
||||
throw new Error(`CCIP Router not configured for ${network}. Set CCIP_${network.toUpperCase()}_ROUTER in .env`);
|
||||
}
|
||||
const authorizedSigner = process.env.AUTHORIZED_SIGNER || ethers.ZeroAddress;
|
||||
const sourceChainSelector = process.env.CHAIN138_SELECTOR || "0x000000000000008a";
|
||||
|
||||
const [deployer] = await ethers.getSigners();
|
||||
console.log(`Deploying CCIPLogger to ${network}...`);
|
||||
console.log(" Account:", deployer.address);
|
||||
console.log(" Balance:", (await ethers.provider.getBalance(deployer.address)).toString());
|
||||
console.log(" Router:", routerAddress);
|
||||
|
||||
const CCIPLogger = await ethers.getContractFactory("CCIPLogger");
|
||||
const logger = await CCIPLogger.deploy(routerAddress, authorizedSigner, sourceChainSelector);
|
||||
await logger.waitForDeployment();
|
||||
const addr = await logger.getAddress();
|
||||
console.log("\n✅ CCIPLogger deployed:", addr);
|
||||
console.log("\nNext: npx hardhat verify --network", network, addr, `"${routerAddress}"`, `"${authorizedSigner}"`, `"${sourceChainSelector}"`);
|
||||
}
|
||||
|
||||
main().then(() => process.exit(0)).catch((e) => { console.error(e); process.exit(1); });
|
||||
@@ -31,9 +31,12 @@ async function main() {
|
||||
const CCIPTxReporter = await ethers.getContractFactory("CCIPTxReporter");
|
||||
console.log("\nDeploying CCIPTxReporter...");
|
||||
|
||||
const selectorU64 = typeof destChainSelector === "string" && destChainSelector.startsWith("0x")
|
||||
? BigInt(destChainSelector)
|
||||
: BigInt(destChainSelector);
|
||||
const reporter = await CCIPTxReporter.deploy(
|
||||
routerAddress,
|
||||
destChainSelector,
|
||||
selectorU64,
|
||||
destReceiver
|
||||
);
|
||||
|
||||
|
||||
214
scripts/check-ausdt-all-mainnet.sh
Executable file
214
scripts/check-ausdt-all-mainnet.sh
Executable file
@@ -0,0 +1,214 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Complete Checklist for AUSDT on ALL MAINNET (ChainID 651940)
|
||||
# Usage: ./check-ausdt-all-mainnet.sh
|
||||
|
||||
# Don't exit on error - we want to continue checking
|
||||
set +e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Configuration
|
||||
CHAIN_ID=651940
|
||||
AUSDT_ADDRESS="0x015B1897Ed5279930bC2Be46F661894d219292A6"
|
||||
RPC_URL="${RPC_URL_651940:-https://mainnet-rpc.alltra.global}"
|
||||
EXPLORER_URL="https://alltra.global"
|
||||
|
||||
# Counters
|
||||
PASSED=0
|
||||
FAILED=0
|
||||
WARNINGS=0
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[✓]${NC} $1"; ((PASSED++)); }
|
||||
log_error() { echo -e "${RED}[✗]${NC} $1"; ((FAILED++)); }
|
||||
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; ((WARNINGS++)); }
|
||||
log_section() { echo -e "\n${CYAN}══════════════════════════════════════════════════════════════${NC}"; echo -e "${CYAN}$1${NC}"; echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}\n"; }
|
||||
|
||||
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ AUSDT on ALL MAINNET - Complete Checklist ║${NC}"
|
||||
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}Token Address:${NC} $AUSDT_ADDRESS"
|
||||
echo -e "${BLUE}Chain ID:${NC} $CHAIN_ID (ALL Mainnet)"
|
||||
echo -e "${BLUE}RPC URL:${NC} $RPC_URL"
|
||||
echo -e "${BLUE}Explorer:${NC} $EXPLORER_URL"
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# 1. RPC CONNECTIVITY
|
||||
# ============================================================================
|
||||
log_section "1. RPC Connectivity Check"
|
||||
|
||||
log_info "Testing RPC endpoint connectivity..."
|
||||
if curl -s -X POST -H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
|
||||
--max-time 10 "$RPC_URL" > /dev/null 2>&1; then
|
||||
log_success "RPC endpoint is accessible"
|
||||
|
||||
# Verify chain ID (with timeout)
|
||||
CHAIN_ID_RESPONSE=$(timeout 10 curl -s -X POST -H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
|
||||
--max-time 10 "$RPC_URL" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('result', ''))" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$CHAIN_ID_RESPONSE" ] && [ "$CHAIN_ID_RESPONSE" != "" ]; then
|
||||
CHAIN_ID_DEC=$(printf "%d" "$CHAIN_ID_RESPONSE" 2>/dev/null || echo "0")
|
||||
if [ "$CHAIN_ID_DEC" = "$CHAIN_ID" ]; then
|
||||
log_success "Chain ID matches: $CHAIN_ID"
|
||||
else
|
||||
log_warn "Chain ID mismatch: Expected $CHAIN_ID, got $CHAIN_ID_DEC (may be hex format)"
|
||||
fi
|
||||
else
|
||||
log_warn "Could not verify chain ID (RPC may be slow)"
|
||||
fi
|
||||
else
|
||||
log_error "RPC endpoint is not accessible"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# 2. CONTRACT DEPLOYMENT
|
||||
# ============================================================================
|
||||
log_section "2. Contract Deployment Verification"
|
||||
|
||||
log_info "Checking if contract is deployed..."
|
||||
CONTRACT_CODE=$(timeout 15 cast code "$AUSDT_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$CONTRACT_CODE" ] && [ "$CONTRACT_CODE" != "0x" ] && [ "$CONTRACT_CODE" != "" ]; then
|
||||
CODE_SIZE=$(echo "$CONTRACT_CODE" | wc -c)
|
||||
if [ "$CODE_SIZE" -gt 10 ]; then
|
||||
log_success "Contract is deployed (code size: $CODE_SIZE bytes)"
|
||||
else
|
||||
log_error "Contract code is empty or invalid"
|
||||
fi
|
||||
else
|
||||
log_error "Contract is not deployed or not accessible"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# 3. TOKEN METADATA
|
||||
# ============================================================================
|
||||
log_section "3. Token Metadata Verification"
|
||||
|
||||
log_info "Fetching token name..."
|
||||
TOKEN_NAME=$(timeout 15 cast call "$AUSDT_ADDRESS" "name()(string)" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$TOKEN_NAME" ] && [ "$TOKEN_NAME" != "" ]; then
|
||||
log_success "Token Name: $TOKEN_NAME"
|
||||
else
|
||||
log_error "Failed to fetch token name"
|
||||
fi
|
||||
|
||||
log_info "Fetching token symbol..."
|
||||
TOKEN_SYMBOL=$(timeout 15 cast call "$AUSDT_ADDRESS" "symbol()(string)" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$TOKEN_SYMBOL" ] && [ "$TOKEN_SYMBOL" != "" ]; then
|
||||
# Remove quotes if present
|
||||
TOKEN_SYMBOL_CLEAN=$(echo "$TOKEN_SYMBOL" | tr -d '"')
|
||||
log_success "Token Symbol: $TOKEN_SYMBOL_CLEAN"
|
||||
if [ "$TOKEN_SYMBOL_CLEAN" = "AUSDT" ]; then
|
||||
log_success "Symbol matches expected: AUSDT"
|
||||
else
|
||||
log_warn "Symbol mismatch: Expected AUSDT, got $TOKEN_SYMBOL_CLEAN"
|
||||
fi
|
||||
else
|
||||
log_error "Failed to fetch token symbol"
|
||||
fi
|
||||
|
||||
log_info "Fetching token decimals..."
|
||||
TOKEN_DECIMALS=$(timeout 15 cast call "$AUSDT_ADDRESS" "decimals()(uint8)" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$TOKEN_DECIMALS" ]; then
|
||||
DECIMALS_DEC=$(printf "%d" "$TOKEN_DECIMALS" 2>/dev/null || echo "0")
|
||||
log_success "Token Decimals: $DECIMALS_DEC"
|
||||
if [ "$DECIMALS_DEC" = "18" ]; then
|
||||
log_success "Decimals match expected: 18"
|
||||
else
|
||||
log_warn "Decimals mismatch: Expected 18, got $DECIMALS_DEC"
|
||||
fi
|
||||
else
|
||||
log_error "Failed to fetch token decimals"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# 4. TOKEN SUPPLY
|
||||
# ============================================================================
|
||||
log_section "4. Token Supply Information"
|
||||
|
||||
log_info "Fetching total supply..."
|
||||
TOTAL_SUPPLY=$(timeout 15 cast call "$AUSDT_ADDRESS" "totalSupply()(uint256)" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$TOTAL_SUPPLY" ] && [ "$TOTAL_SUPPLY" != "0x0" ] && [ "$TOTAL_SUPPLY" != "0" ]; then
|
||||
SUPPLY_DEC=$(printf "%d" "$TOTAL_SUPPLY" 2>/dev/null || echo "0")
|
||||
if [ "$DECIMALS_DEC" = "18" ]; then
|
||||
SUPPLY_DISPLAY=$(echo "scale=2; $SUPPLY_DEC / 1000000000000000000" | bc 2>/dev/null || echo "$SUPPLY_DEC")
|
||||
log_success "Total Supply: $SUPPLY_DISPLAY AUSDT"
|
||||
else
|
||||
log_success "Total Supply: $SUPPLY_DEC (raw)"
|
||||
fi
|
||||
else
|
||||
log_warn "Total supply is zero or could not be fetched"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# 5. ERC-20 FUNCTIONALITY
|
||||
# ============================================================================
|
||||
log_section "5. ERC-20 Functionality Check"
|
||||
|
||||
log_info "Testing balanceOf function..."
|
||||
BALANCE=$(timeout 15 cast call "$AUSDT_ADDRESS" "balanceOf(address)(uint256)" "0x0000000000000000000000000000000000000000" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$BALANCE" ]; then
|
||||
log_success "balanceOf() function works"
|
||||
else
|
||||
log_error "balanceOf() function failed"
|
||||
fi
|
||||
|
||||
log_info "Testing allowance function..."
|
||||
ALLOWANCE=$(timeout 15 cast call "$AUSDT_ADDRESS" "allowance(address,address)(uint256)" "0x0000000000000000000000000000000000000000" "0x0000000000000000000000000000000000000000" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$ALLOWANCE" ]; then
|
||||
log_success "allowance() function works"
|
||||
else
|
||||
log_error "allowance() function failed"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# 6. TOKEN LIST VERIFICATION
|
||||
# ============================================================================
|
||||
log_section "6. Token List Integration"
|
||||
|
||||
TOKEN_LIST_FILE="token-lists/lists/all-mainnet.tokenlist.json"
|
||||
if [ -f "$TOKEN_LIST_FILE" ]; then
|
||||
log_success "Token list file exists: $TOKEN_LIST_FILE"
|
||||
|
||||
if grep -q "$AUSDT_ADDRESS" "$TOKEN_LIST_FILE"; then
|
||||
log_success "AUSDT address found in token list"
|
||||
else
|
||||
log_error "AUSDT address not found in token list"
|
||||
fi
|
||||
else
|
||||
log_error "Token list file not found: $TOKEN_LIST_FILE"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# SUMMARY
|
||||
# ============================================================================
|
||||
log_section "Checklist Summary"
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}Results:${NC}"
|
||||
echo -e " ${GREEN}✓ Passed:${NC} $PASSED"
|
||||
echo -e " ${RED}✗ Failed:${NC} $FAILED"
|
||||
echo -e " ${YELLOW}⚠ Warnings:${NC} $WARNINGS"
|
||||
echo ""
|
||||
|
||||
if [ $FAILED -eq 0 ]; then
|
||||
echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ All Critical Checks Passed! ║${NC}"
|
||||
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${RED}║ Some Checks Failed - Review Above ║${NC}"
|
||||
echo -e "${RED}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
exit 1
|
||||
fi
|
||||
281
scripts/check-metamask-integration.sh
Executable file
281
scripts/check-metamask-integration.sh
Executable file
@@ -0,0 +1,281 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Complete MetaMask Integration Check
|
||||
# Verifies decimals, balances, pricing, and volumes for MetaMask
|
||||
# Usage: ./check-metamask-integration.sh
|
||||
|
||||
set +e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Configuration
|
||||
CHAIN_ID=138
|
||||
RPC_URL="${RPC_URL:-${RPC_URL_138:-http://192.168.11.211:8545}}"
|
||||
ORACLE_ADDRESS="0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6"
|
||||
|
||||
# Token addresses
|
||||
WETH9="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
||||
WETH10="0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f"
|
||||
CUSDT="0x93E66202A11B1772E55407B32B44e5Cd8eda7f22"
|
||||
CUSDC="0xf22258f57794CC8E06237084b353Ab30fFfa640b"
|
||||
|
||||
# Counters
|
||||
PASSED=0
|
||||
FAILED=0
|
||||
WARNINGS=0
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[✓]${NC} $1"; ((PASSED++)); }
|
||||
log_error() { echo -e "${RED}[✗]${NC} $1"; ((FAILED++)); }
|
||||
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; ((WARNINGS++)); }
|
||||
log_section() { echo -e "\n${CYAN}══════════════════════════════════════════════════════════════${NC}"; echo -e "${CYAN}$1${NC}"; echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}\n"; }
|
||||
|
||||
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ MetaMask Integration - Complete Verification ║${NC}"
|
||||
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}Chain ID:${NC} $CHAIN_ID"
|
||||
echo -e "${BLUE}RPC URL:${NC} $RPC_URL"
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# 1. TOKEN DECIMALS VERIFICATION
|
||||
# ============================================================================
|
||||
log_section "1. Token Decimals Verification"
|
||||
|
||||
declare -A TOKENS=(
|
||||
["WETH9"]="$WETH9:18"
|
||||
["WETH10"]="$WETH10:18"
|
||||
["cUSDT"]="$CUSDT:6"
|
||||
["cUSDC"]="$CUSDC:6"
|
||||
)
|
||||
|
||||
TOKEN_LIST_FILE="token-lists/lists/dbis-138.tokenlist.json"
|
||||
METAMASK_LIST_FILE="docs/04-configuration/metamask/METAMASK_TOKEN_LIST.json"
|
||||
|
||||
for TOKEN_NAME in "${!TOKENS[@]}"; do
|
||||
IFS=':' read -r ADDRESS EXPECTED_DEC <<< "${TOKENS[$TOKEN_NAME]}"
|
||||
|
||||
log_info "Checking $TOKEN_NAME ($ADDRESS)..."
|
||||
|
||||
# Check on-chain decimals
|
||||
ONCHAIN_DEC=$(timeout 15 cast call "$ADDRESS" "decimals()(uint8)" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$ONCHAIN_DEC" ]; then
|
||||
DEC_DEC=$(printf "%d" "$ONCHAIN_DEC" 2>/dev/null || echo "0")
|
||||
if [ "$DEC_DEC" = "$EXPECTED_DEC" ]; then
|
||||
log_success "$TOKEN_NAME: On-chain decimals correct ($DEC_DEC)"
|
||||
else
|
||||
log_warn "$TOKEN_NAME: On-chain decimals mismatch (got $DEC_DEC, expected $EXPECTED_DEC)"
|
||||
fi
|
||||
else
|
||||
log_error "$TOKEN_NAME: Failed to fetch on-chain decimals"
|
||||
fi
|
||||
|
||||
# Check token list decimals
|
||||
if [ -f "$TOKEN_LIST_FILE" ]; then
|
||||
LIST_DEC=$(grep -A 10 "\"$ADDRESS\"" "$TOKEN_LIST_FILE" 2>/dev/null | grep "decimals" | head -1 | grep -oE "[0-9]+" || echo "")
|
||||
if [ -n "$LIST_DEC" ] && [ "$LIST_DEC" = "$EXPECTED_DEC" ]; then
|
||||
log_success "$TOKEN_NAME: Token list decimals correct ($LIST_DEC)"
|
||||
elif [ -n "$LIST_DEC" ]; then
|
||||
log_warn "$TOKEN_NAME: Token list decimals mismatch (got $LIST_DEC, expected $EXPECTED_DEC)"
|
||||
else
|
||||
log_warn "$TOKEN_NAME: Not found in token list"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check MetaMask token list
|
||||
if [ -f "$METAMASK_LIST_FILE" ]; then
|
||||
META_DEC=$(grep -A 10 "\"$ADDRESS\"" "$METAMASK_LIST_FILE" 2>/dev/null | grep "decimals" | head -1 | grep -oE "[0-9]+" || echo "")
|
||||
if [ -n "$META_DEC" ] && [ "$META_DEC" = "$EXPECTED_DEC" ]; then
|
||||
log_success "$TOKEN_NAME: MetaMask list decimals correct ($META_DEC)"
|
||||
elif [ -n "$META_DEC" ]; then
|
||||
log_warn "$TOKEN_NAME: MetaMask list decimals mismatch (got $META_DEC, expected $EXPECTED_DEC)"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
|
||||
# ============================================================================
|
||||
# 2. BALANCE DISPLAY VERIFICATION
|
||||
# ============================================================================
|
||||
log_section "2. Balance Display Verification"
|
||||
|
||||
log_info "Testing balanceOf for sample addresses..."
|
||||
|
||||
# Test with zero address
|
||||
TEST_ADDRESS="0x0000000000000000000000000000000000000000"
|
||||
for TOKEN_NAME in "${!TOKENS[@]}"; do
|
||||
IFS=':' read -r ADDRESS EXPECTED_DEC <<< "${TOKENS[$TOKEN_NAME]}"
|
||||
|
||||
BALANCE=$(timeout 15 cast call "$ADDRESS" "balanceOf(address)(uint256)" "$TEST_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$BALANCE" ]; then
|
||||
log_success "$TOKEN_NAME: balanceOf() function works"
|
||||
else
|
||||
log_error "$TOKEN_NAME: balanceOf() function failed"
|
||||
fi
|
||||
done
|
||||
|
||||
# ============================================================================
|
||||
# 3. ORACLE PRICE FEED VERIFICATION
|
||||
# ============================================================================
|
||||
log_section "3. Oracle Price Feed Verification"
|
||||
|
||||
log_info "Checking oracle contract..."
|
||||
ORACLE_DATA=$(timeout 15 cast call "$ORACLE_ADDRESS" "latestRoundData()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$ORACLE_DATA" ] && [ "$ORACLE_DATA" != "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ]; then
|
||||
# Extract answer (second field)
|
||||
ANSWER_HEX=$(echo "$ORACLE_DATA" | cut -c 131-194)
|
||||
ANSWER_DEC=$(printf "%d" "0x$ANSWER_HEX" 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$ANSWER_DEC" != "0" ] && [ "$ANSWER_DEC" -gt 0 ]; then
|
||||
PRICE=$(echo "scale=2; $ANSWER_DEC / 100000000" | bc 2>/dev/null || echo "0")
|
||||
log_success "Oracle has price data: ETH/USD = \$$PRICE"
|
||||
|
||||
# Check update timestamp
|
||||
UPDATED_AT_HEX=$(echo "$ORACLE_DATA" | cut -c 259-322)
|
||||
UPDATED_AT=$(printf "%d" "0x$UPDATED_AT_HEX" 2>/dev/null || echo "0")
|
||||
if [ "$UPDATED_AT" != "0" ]; then
|
||||
CURRENT_TIME=$(date +%s)
|
||||
AGE=$((CURRENT_TIME - UPDATED_AT))
|
||||
if [ $AGE -lt 300 ]; then
|
||||
log_success "Oracle price is fresh (updated $AGE seconds ago)"
|
||||
else
|
||||
MINUTES=$((AGE / 60))
|
||||
log_warn "Oracle price may be stale (updated $MINUTES minutes ago)"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_error "Oracle price is zero (needs update)"
|
||||
fi
|
||||
else
|
||||
log_error "Oracle contract returns zero or empty data"
|
||||
fi
|
||||
|
||||
log_info ""
|
||||
log_warn "IMPORTANT: MetaMask does NOT automatically query oracle contracts"
|
||||
log_info "MetaMask uses CoinGecko API for USD prices (requires token listing)"
|
||||
|
||||
# ============================================================================
|
||||
# 4. METAMASK PRICE SOURCE VERIFICATION
|
||||
# ============================================================================
|
||||
log_section "4. MetaMask Price Source Verification"
|
||||
|
||||
log_info "MetaMask Price Sources (in order):"
|
||||
echo " 1. CoinGecko API (primary) - requires token listing"
|
||||
echo " 2. Token Lists - limited price metadata support"
|
||||
echo " 3. Oracle Contracts - NOT automatically queried"
|
||||
echo ""
|
||||
|
||||
log_info "Checking CoinGecko listing status..."
|
||||
|
||||
# Check if tokens are likely on CoinGecko
|
||||
TOKENS_TO_CHECK=("ethereum" "tether" "usd-coin")
|
||||
for TOKEN_ID in "${TOKENS_TO_CHECK[@]}"; do
|
||||
COINGECKO_DATA=$(curl -s "https://api.coingecko.com/api/v3/simple/price?ids=$TOKEN_ID&vs_currencies=usd" --max-time 5 2>/dev/null || echo "")
|
||||
if echo "$COINGECKO_DATA" | grep -q "usd"; then
|
||||
log_success "CoinGecko API accessible for $TOKEN_ID"
|
||||
else
|
||||
log_warn "CoinGecko API may not have data for $TOKEN_ID"
|
||||
fi
|
||||
done
|
||||
|
||||
log_info ""
|
||||
log_warn "Note: cUSDT and cUSDC are NOT listed on CoinGecko yet"
|
||||
log_info "See: docs/04-configuration/coingecko/COINGECKO_SUBMISSION_GUIDE.md"
|
||||
|
||||
# ============================================================================
|
||||
# 5. VOLUME DATA VERIFICATION
|
||||
# ============================================================================
|
||||
log_section "5. Volume Data Verification"
|
||||
|
||||
log_info "MetaMask Volume Data Sources:"
|
||||
echo " - CoinGecko API (if token is listed)"
|
||||
echo " - Token Lists (limited support)"
|
||||
echo " - Oracle contracts (NOT used by MetaMask)"
|
||||
echo ""
|
||||
|
||||
log_warn "MetaMask does NOT display volume data from oracles"
|
||||
log_info "Volume data comes from CoinGecko or external APIs"
|
||||
|
||||
# Check if token aggregation service exists
|
||||
TOKEN_AGG_SERVICE="smom-dbis-138/services/token-aggregation"
|
||||
if [ -d "$TOKEN_AGG_SERVICE" ]; then
|
||||
log_success "Token aggregation service exists"
|
||||
log_info " Service can aggregate volume data from multiple sources"
|
||||
log_info " But MetaMask doesn't query this service directly"
|
||||
else
|
||||
log_warn "Token aggregation service not found"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# 6. TOKEN LIST HOSTING VERIFICATION
|
||||
# ============================================================================
|
||||
log_section "6. Token List Hosting Verification"
|
||||
|
||||
TOKEN_LIST_URL="https://raw.githubusercontent.com/Defi-Oracle-Meta-Blockchain/metamask-integration/main/config/token-list.json"
|
||||
log_info "Checking hosted token list..."
|
||||
if curl -s -I "$TOKEN_LIST_URL" --max-time 5 | head -1 | grep -q "200\|301\|302"; then
|
||||
log_success "Token list is hosted and accessible"
|
||||
log_info " URL: $TOKEN_LIST_URL"
|
||||
|
||||
# Check if list has correct decimals
|
||||
LIST_CONTENT=$(curl -s "$TOKEN_LIST_URL" --max-time 5 2>/dev/null || echo "")
|
||||
if echo "$LIST_CONTENT" | grep -q "\"decimals\": 18"; then
|
||||
log_success "Token list includes 18 decimals entries"
|
||||
fi
|
||||
if echo "$LIST_CONTENT" | grep -q "\"decimals\": 6"; then
|
||||
log_success "Token list includes 6 decimals entries"
|
||||
fi
|
||||
else
|
||||
log_warn "Token list may not be accessible at hosted URL"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# SUMMARY
|
||||
# ============================================================================
|
||||
log_section "Verification Summary"
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}Results:${NC}"
|
||||
echo -e " ${GREEN}✓ Passed:${NC} $PASSED"
|
||||
echo -e " ${RED}✗ Failed:${NC} $FAILED"
|
||||
echo -e " ${YELLOW}⚠ Warnings:${NC} $WARNINGS"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Key Findings:${NC}"
|
||||
echo ""
|
||||
echo "1. ${GREEN}Decimals:${NC} Token lists override on-chain decimals"
|
||||
echo " - WETH9: Contract returns 0, but token list has 18 ✅"
|
||||
echo " - cUSDT/cUSDC: Both contract and list have 6 ✅"
|
||||
echo ""
|
||||
echo "2. ${YELLOW}Pricing:${NC} MetaMask uses CoinGecko, NOT oracles"
|
||||
echo " - Oracle exists but MetaMask doesn't query it"
|
||||
echo " - cUSDT/cUSDC need CoinGecko listing for USD display"
|
||||
echo ""
|
||||
echo "3. ${YELLOW}Volumes:${NC} MetaMask doesn't display volume from oracles"
|
||||
echo " - Volume data comes from CoinGecko/external APIs"
|
||||
echo " - Oracle contracts don't provide volume data"
|
||||
echo ""
|
||||
echo "4. ${GREEN}Balances:${NC} ERC-20 functions work correctly"
|
||||
echo " - balanceOf() works for all tokens"
|
||||
echo " - Display depends on correct decimals in token list"
|
||||
echo ""
|
||||
|
||||
if [ $FAILED -eq 0 ]; then
|
||||
echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ All Critical Checks Passed! ║${NC}"
|
||||
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${YELLOW}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${YELLOW}║ Some Checks Need Attention ║${NC}"
|
||||
echo -e "${YELLOW}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
exit 1
|
||||
fi
|
||||
171
scripts/check-oracle-publisher-status.sh
Executable file
171
scripts/check-oracle-publisher-status.sh
Executable file
@@ -0,0 +1,171 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check Oracle Publisher Service Status
|
||||
# Usage: ./check-oracle-publisher-status.sh
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Configuration
|
||||
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}"
|
||||
VMID=3500
|
||||
ORACLE_ADDRESS="0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6"
|
||||
RPC_URL="${RPC_URL:-${RPC_URL_138:-http://192.168.11.211:8545}}"
|
||||
|
||||
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Oracle Publisher Service Status Check ║${NC}"
|
||||
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if container exists
|
||||
echo -e "${YELLOW}1. Checking if container (VMID $VMID) exists...${NC}"
|
||||
if ssh "root@$PROXMOX_HOST" "pct list | grep -q '^[[:space:]]*$VMID'" 2>/dev/null; then
|
||||
CONTAINER_STATUS=$(ssh "root@$PROXMOX_HOST" "pct status $VMID 2>/dev/null | awk '{print \$2}'" || echo "unknown")
|
||||
echo -e "${GREEN}✓ Container exists (Status: $CONTAINER_STATUS)${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ Container VMID $VMID not found${NC}"
|
||||
echo ""
|
||||
echo "Container needs to be created. See documentation:"
|
||||
echo " docs/04-configuration/metamask/ORACLE_PRICE_FEED_SETUP.md"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check service status
|
||||
echo -e "${YELLOW}2. Checking oracle-publisher service status...${NC}"
|
||||
SERVICE_STATUS=$(ssh "root@$PROXMOX_HOST" "pct exec $VMID -- systemctl is-active oracle-publisher.service 2>/dev/null || echo 'inactive'" 2>&1)
|
||||
if [ "$SERVICE_STATUS" = "active" ]; then
|
||||
echo -e "${GREEN}✓ Service is active${NC}"
|
||||
|
||||
# Check if service is enabled
|
||||
ENABLED=$(ssh "root@$PROXMOX_HOST" "pct exec $VMID -- systemctl is-enabled oracle-publisher.service 2>/dev/null || echo 'disabled'" 2>&1)
|
||||
if [ "$ENABLED" = "enabled" ]; then
|
||||
echo -e "${GREEN}✓ Service is enabled (will start on boot)${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠ Service is not enabled (won't start on boot)${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}✗ Service is $SERVICE_STATUS${NC}"
|
||||
echo ""
|
||||
echo "To start the service:"
|
||||
echo " ssh root@$PROXMOX_HOST \"pct exec $VMID -- systemctl start oracle-publisher\""
|
||||
echo " ssh root@$PROXMOX_HOST \"pct exec $VMID -- systemctl enable oracle-publisher\""
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check configuration file
|
||||
echo -e "${YELLOW}3. Checking configuration file...${NC}"
|
||||
if ssh "root@$PROXMOX_HOST" "pct exec $VMID -- test -f /opt/oracle-publisher/.env" 2>/dev/null; then
|
||||
echo -e "${GREEN}✓ Configuration file exists${NC}"
|
||||
|
||||
# Check key configuration variables
|
||||
echo " Checking key variables..."
|
||||
ENV_VARS=("ORACLE_ADDRESS" "AGGREGATOR_ADDRESS" "RPC_URL" "CHAIN_ID" "PRIVATE_KEY" "UPDATE_INTERVAL")
|
||||
for VAR in "${ENV_VARS[@]}"; do
|
||||
VALUE=$(ssh "root@$PROXMOX_HOST" "pct exec $VMID -- grep '^${VAR}=' /opt/oracle-publisher/.env 2>/dev/null | cut -d= -f2-" || echo "")
|
||||
if [ -n "$VALUE" ]; then
|
||||
if [ "$VAR" = "PRIVATE_KEY" ]; then
|
||||
echo -e " ${GREEN}✓${NC} $VAR = [HIDDEN]"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} $VAR = $VALUE"
|
||||
fi
|
||||
else
|
||||
echo -e " ${RED}✗${NC} $VAR not set"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo -e "${RED}✗ Configuration file not found at /opt/oracle-publisher/.env${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check recent logs
|
||||
echo -e "${YELLOW}4. Checking recent service logs (last 10 lines)...${NC}"
|
||||
RECENT_LOGS=$(ssh "root@$PROXMOX_HOST" "pct exec $VMID -- journalctl -u oracle-publisher.service -n 10 --no-pager 2>/dev/null" || echo "")
|
||||
if [ -n "$RECENT_LOGS" ]; then
|
||||
echo "$RECENT_LOGS" | while IFS= read -r line; do
|
||||
if echo "$line" | grep -qiE "(error|failed|exception)"; then
|
||||
echo -e " ${RED}$line${NC}"
|
||||
elif echo "$line" | grep -qiE "(price|update|success)"; then
|
||||
echo -e " ${GREEN}$line${NC}"
|
||||
else
|
||||
echo " $line"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo -e "${YELLOW}⚠ No recent logs found${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check oracle contract price
|
||||
echo -e "${YELLOW}5. Checking oracle contract price data...${NC}"
|
||||
ORACLE_DATA=$(cast call "$ORACLE_ADDRESS" "latestRoundData()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$ORACLE_DATA" ]; then
|
||||
# Parse the response (format: roundId, answer, startedAt, updatedAt, answeredInRound)
|
||||
# Extract answer (second field, bytes 131-194)
|
||||
ANSWER_HEX=$(echo "$ORACLE_DATA" | cut -c 131-194)
|
||||
|
||||
if [ "$ANSWER_HEX" != "00000000000000000000000000000000000000000000000000000000" ]; then
|
||||
# Convert hex to decimal
|
||||
ANSWER_DEC=$(printf "%d" "0x$ANSWER_HEX" 2>/dev/null || echo "0")
|
||||
|
||||
# Handle signed integer (if > 2^255, it's negative)
|
||||
if [ "$ANSWER_DEC" -gt 9223372036854775807 ] 2>/dev/null; then
|
||||
ANSWER_DEC=$((ANSWER_DEC - 18446744073709551616))
|
||||
fi
|
||||
|
||||
# Convert from 8 decimals to USD
|
||||
PRICE=$(echo "scale=2; $ANSWER_DEC / 100000000" | bc 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$PRICE" != "0" ] && [ "$PRICE" != "0.00" ]; then
|
||||
echo -e "${GREEN}✓ Oracle has price data${NC}"
|
||||
echo " ETH/USD Price: \$$PRICE"
|
||||
|
||||
# Extract updatedAt (fourth field)
|
||||
UPDATED_AT_HEX=$(echo "$ORACLE_DATA" | cut -c 259-322)
|
||||
UPDATED_AT=$(printf "%d" "0x$UPDATED_AT_HEX" 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$UPDATED_AT" != "0" ]; then
|
||||
CURRENT_TIME=$(date +%s)
|
||||
AGE=$((CURRENT_TIME - UPDATED_AT))
|
||||
|
||||
if [ $AGE -lt 300 ]; then
|
||||
echo -e "${GREEN}✓ Price updated $AGE seconds ago (fresh)${NC}"
|
||||
elif [ $AGE -lt 3600 ]; then
|
||||
MINUTES=$((AGE / 60))
|
||||
echo -e "${YELLOW}⚠ Price updated $MINUTES minutes ago (may be stale)${NC}"
|
||||
else
|
||||
HOURS=$((AGE / 3600))
|
||||
echo -e "${RED}✗ Price updated $HOURS hours ago (stale)${NC}"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}✗ Oracle price is zero (needs update)${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}✗ Oracle price is zero (needs update)${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}✗ Failed to query oracle contract${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Summary ║${NC}"
|
||||
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo "To view full logs:"
|
||||
echo " ssh root@$PROXMOX_HOST \"pct exec $VMID -- journalctl -u oracle-publisher.service -f\""
|
||||
echo ""
|
||||
echo "To restart service:"
|
||||
echo " ssh root@$PROXMOX_HOST \"pct exec $VMID -- systemctl restart oracle-publisher\""
|
||||
echo ""
|
||||
echo "To update oracle manually:"
|
||||
echo " cd /home/intlc/projects/proxmox/smom-dbis-138"
|
||||
echo " ./scripts/update-oracle-price.sh"
|
||||
@@ -32,7 +32,8 @@ if [ -z "$PRIVATE_KEY" ]; then
|
||||
fi
|
||||
|
||||
CHAIN138_RPC="${RPC_URL_138:-http://192.168.11.211:8545}"
|
||||
LINK_TOKEN="${LINK_TOKEN_138:-0x514910771AF9Ca656af840dff83E8264EcF986CA}"
|
||||
# Chain 138 LINK: 0xb7721d... (deployed on 138). Mainnet canonical is 0x51491077... — do not use mainnet address when checking balance on 138.
|
||||
LINK_TOKEN="${LINK_TOKEN_138:-${LINK_TOKEN_CHAIN138:-0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03}}"
|
||||
|
||||
WALLET_ADDRESS=$(cast wallet address --private-key "$PRIVATE_KEY")
|
||||
|
||||
|
||||
179
scripts/create-all-dodo-pools-from-token-api.sh
Executable file
179
scripts/create-all-dodo-pools-from-token-api.sh
Executable file
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env bash
|
||||
# Create Dodoex PMM pools for all tokens on a chain using Token Aggregation API.
|
||||
# Uses GET /tokens and GET /tokens/:address/pools to discover tokens and skip those already with DODO pools.
|
||||
# Calls DODOPMMIntegration.createPool, EnhancedSwapRouter.setDodoPoolAddress, UniversalAssetRegistry.updatePMMPool.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[✗]${NC} $1"; }
|
||||
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
set -a
|
||||
source "$PROJECT_ROOT/.env"
|
||||
set +a
|
||||
fi
|
||||
|
||||
TOKEN_API_URL="${TOKEN_AGGREGATION_API_URL:-http://localhost:3000}"
|
||||
CHAIN_ID="${CHAIN_ID:-138}"
|
||||
RPC_URL="${RPC_URL:-}"
|
||||
PRIVATE_KEY="${PRIVATE_KEY:-}"
|
||||
DODO_PMM_INTEGRATION="${DODO_PMM_INTEGRATION:-${DODO_PMM_INTEGRATION_ADDRESS:-}}"
|
||||
ENHANCED_SWAP_ROUTER="${ENHANCED_SWAP_ROUTER_ADDRESS:-}"
|
||||
ASSET_REGISTRY="${UNIVERSAL_ASSET_REGISTRY_ADDRESS:-}"
|
||||
QUOTE_TOKEN="${QUOTE_TOKEN_ADDRESS:-}"
|
||||
# Default WETH for chain 138 if not set
|
||||
if [ "$CHAIN_ID" = "138" ]; then
|
||||
QUOTE_TOKEN="${QUOTE_TOKEN:-${WETH_ADDRESS_138:-}}"
|
||||
fi
|
||||
if [ "$CHAIN_ID" = "651940" ]; then
|
||||
QUOTE_TOKEN="${QUOTE_TOKEN:-${WETH_ADDRESS_651940:-}}"
|
||||
fi
|
||||
|
||||
LP_FEE_RATE="${LP_FEE_RATE:-3}"
|
||||
INITIAL_PRICE="${INITIAL_PRICE:-1000000000000000000}"
|
||||
K_FACTOR="${K_FACTOR:-500000000000000000}"
|
||||
ENABLE_TWAP="${ENABLE_TWAP:-true}"
|
||||
TWAP_VALUE="$([ "$ENABLE_TWAP" = "true" ] && echo "true" || echo "false")"
|
||||
|
||||
DRY_RUN="${DRY_RUN:-false}"
|
||||
LIMIT="${TOKEN_PAGE_LIMIT:-500}"
|
||||
|
||||
for var in RPC_URL PRIVATE_KEY DODO_PMM_INTEGRATION QUOTE_TOKEN; do
|
||||
eval "val=\$$var"
|
||||
if [ -z "$val" ]; then
|
||||
log_error "$var is not set"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if ! command -v jq &>/dev/null; then
|
||||
log_error "jq is required. Install with: apt-get install jq / brew install jq"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v cast &>/dev/null; then
|
||||
log_error "cast (foundry) is required for on-chain calls"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "========================================="
|
||||
log_info "Create DODO PMM pools from Token API"
|
||||
log_info "========================================="
|
||||
log_info "Token API: $TOKEN_API_URL"
|
||||
log_info "Chain ID: $CHAIN_ID"
|
||||
log_info "Quote token (WETH/stable): $QUOTE_TOKEN"
|
||||
log_info "DODO PMM Integration: $DODO_PMM_INTEGRATION"
|
||||
log_info "Enhanced Swap Router: ${ENHANCED_SWAP_ROUTER:-not set}"
|
||||
log_info "Asset Registry: ${ASSET_REGISTRY:-not set}"
|
||||
log_info "Dry run: $DRY_RUN"
|
||||
log_info ""
|
||||
|
||||
offset=0
|
||||
total_created=0
|
||||
total_skipped=0
|
||||
|
||||
while true; do
|
||||
url="${TOKEN_API_URL}/tokens?chainId=${CHAIN_ID}&limit=${LIMIT}&offset=${offset}"
|
||||
log_info "Fetching tokens: $url"
|
||||
resp=$(curl -sS --fail "$url" 2>/dev/null || true)
|
||||
if [ -z "$resp" ]; then
|
||||
log_warn "No response or empty from Token API; check TOKEN_AGGREGATION_API_URL and that the service is running"
|
||||
break
|
||||
fi
|
||||
|
||||
count=$(echo "$resp" | jq -r '.tokens | length')
|
||||
if [ -z "$count" ] || [ "$count" = "null" ] || [ "$count" -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
for i in $(seq 0 $((count - 1))); do
|
||||
token_addr=$(echo "$resp" | jq -r ".tokens[$i].address")
|
||||
if [ -z "$token_addr" ] || [ "$token_addr" = "null" ]; then
|
||||
continue
|
||||
fi
|
||||
# Skip quote token itself
|
||||
if [ "$(echo "$token_addr" | tr '[:upper:]' '[:lower:]')" = "$(echo "$QUOTE_TOKEN" | tr '[:upper:]' '[:lower:]')" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if token already has a DODO pool
|
||||
pools_url="${TOKEN_API_URL}/tokens/${token_addr}/pools?chainId=${CHAIN_ID}"
|
||||
pools_resp=$(curl -sS "$pools_url" 2>/dev/null || true)
|
||||
has_dodo=false
|
||||
if [ -n "$pools_resp" ]; then
|
||||
dexes=$(echo "$pools_resp" | jq -r '.pools[].dex' 2>/dev/null || true)
|
||||
if echo "$dexes" | grep -q 'dodo'; then
|
||||
has_dodo=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$has_dodo" = "true" ]; then
|
||||
total_skipped=$((total_skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Create pool: baseToken=token, quoteToken=QUOTE_TOKEN (e.g. WETH)
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
log_info "[DRY RUN] Would createPool base=$token_addr quote=$QUOTE_TOKEN"
|
||||
total_created=$((total_created + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! pool_addr=$(cast call "$DODO_PMM_INTEGRATION" "pools(address,address)(address)" "$token_addr" "$QUOTE_TOKEN" --rpc-url "$RPC_URL" 2>/dev/null | cast --to-addr 2>/dev/null); then
|
||||
pool_addr=""
|
||||
fi
|
||||
if [ -n "$pool_addr" ] && [ "$pool_addr" != "0x0000000000000000000000000000000000000000" ]; then
|
||||
log_warn "Pool already exists for $token_addr / $QUOTE_TOKEN: $pool_addr"
|
||||
total_skipped=$((total_skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
log_info "Creating pool: base=$token_addr quote=$QUOTE_TOKEN"
|
||||
if cast send "$DODO_PMM_INTEGRATION" \
|
||||
"createPool(address,address,uint256,uint256,uint256,bool)" \
|
||||
"$token_addr" \
|
||||
"$QUOTE_TOKEN" \
|
||||
"$LP_FEE_RATE" \
|
||||
"$INITIAL_PRICE" \
|
||||
"$K_FACTOR" \
|
||||
"$TWAP_VALUE" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy \
|
||||
-q 2>/dev/null; then
|
||||
pool_addr=$(cast call "$DODO_PMM_INTEGRATION" "pools(address,address)(address)" "$token_addr" "$QUOTE_TOKEN" --rpc-url "$RPC_URL" | cast --to-addr)
|
||||
log_success "Pool created: $pool_addr"
|
||||
|
||||
if [ -n "$ENHANCED_SWAP_ROUTER" ] && [ "$ENHANCED_SWAP_ROUTER" != "0x0000000000000000000000000000000000000000" ]; then
|
||||
cast send "$ENHANCED_SWAP_ROUTER" "setDodoPoolAddress(address,address,address)" "$QUOTE_TOKEN" "$token_addr" "$pool_addr" --rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" --legacy -q 2>/dev/null && log_success "Router set QUOTE->token" || log_warn "Router set failed"
|
||||
cast send "$ENHANCED_SWAP_ROUTER" "setDodoPoolAddress(address,address,address)" "$token_addr" "$QUOTE_TOKEN" "$pool_addr" --rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" --legacy -q 2>/dev/null && log_success "Router set token->QUOTE" || log_warn "Router set failed"
|
||||
fi
|
||||
if [ -n "$ASSET_REGISTRY" ] && [ "$ASSET_REGISTRY" != "0x0000000000000000000000000000000000000000" ]; then
|
||||
cast send "$ASSET_REGISTRY" "updatePMMPool(address,address)" "$token_addr" "$pool_addr" --rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" --legacy -q 2>/dev/null && log_success "Registry updatePMMPool" || log_warn "Registry updatePMMPool failed"
|
||||
fi
|
||||
total_created=$((total_created + 1))
|
||||
else
|
||||
log_error "Failed to create pool for $token_addr"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$count" -lt "$LIMIT" ]; then
|
||||
break
|
||||
fi
|
||||
offset=$((offset + LIMIT))
|
||||
done
|
||||
|
||||
log_info ""
|
||||
log_info "Done. Pools created: $total_created, skipped (already had DODO): $total_skipped"
|
||||
18
scripts/deploy-iso4217w-system.sh
Executable file
18
scripts/deploy-iso4217w-system.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy ISO-4217W Token System (ISO-009 to ISO-018)
|
||||
# Requires: PRIVATE_KEY, RPC_URL (ChainID 138)
|
||||
# Optional: CUSTODIAN_ADDRESS, RESERVE_MANAGER_ADDRESS, RESERVE_TRANSMITTER_1, RESERVE_TRANSMITTER_2
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
: "${PRIVATE_KEY:?PRIVATE_KEY required}"
|
||||
: "${RPC_URL:?RPC_URL required (e.g. http://192.168.11.250:8545)}"
|
||||
|
||||
echo "Deploying ISO-4217W Token System..."
|
||||
forge script script/deploy/iso4217w/DeployISO4217WSystem.s.sol:DeployISO4217WSystem \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--broadcast \
|
||||
--verify
|
||||
18
scripts/deploy-vault-system.sh
Executable file
18
scripts/deploy-vault-system.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy Vault System (VLT-010 to VLT-018)
|
||||
# Requires: PRIVATE_KEY, RPC_URL (ChainID 138)
|
||||
# Optional: TREASURY_ADDRESS
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
: "${PRIVATE_KEY:?PRIVATE_KEY required}"
|
||||
: "${RPC_URL:?RPC_URL required (e.g. http://192.168.11.250:8545)}"
|
||||
|
||||
echo "Deploying Vault System..."
|
||||
forge script script/deploy/vault/DeployVaultSystem.s.sol:DeployVaultSystem \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--broadcast \
|
||||
--verify
|
||||
288
scripts/deployment/check-balances-gas-and-deploy.sh
Executable file
288
scripts/deployment/check-balances-gas-and-deploy.sh
Executable file
@@ -0,0 +1,288 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check deployer balances on all configured networks, estimate gas costs via gas API,
|
||||
# ensure sufficient network token, then optionally deploy (Chain 138 phased core).
|
||||
# Uses PRIVATE_KEY from .env (smom-dbis-138).
|
||||
#
|
||||
# Balance check: On EVM chains only the NATIVE token can be used for gas. We check that
|
||||
# token for each network (cast balance = native currency). ERC-20 tokens (USDT, LINK, etc.)
|
||||
# cannot be used for gas unless a meta-tx relayer is in use.
|
||||
#
|
||||
# Gas token per network (only these can be used for gas):
|
||||
# Chain 138, Ethereum, Base, Optimism, Sepolia, Base Sepolia, Optimism Sepolia → ETH
|
||||
# Polygon, Polygon Amoy → MATIC
|
||||
# BSC → BNB
|
||||
# Avalanche → AVAX
|
||||
# Cronos → CRO
|
||||
# Gnosis → xDAI
|
||||
# Arbitrum → ETH
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/deployment/check-balances-gas-and-deploy.sh # report only
|
||||
# ./scripts/deployment/check-balances-gas-and-deploy.sh --deploy # deploy on Chain 138 (requires PRIVATE_KEY)
|
||||
#
|
||||
# Uses .env for RPCs and PRIVATE_KEY; --deploy is a tag (not .env).
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
source "$SCRIPT_DIR/../lib/deployment/prompts.sh"
|
||||
load_deployment_env
|
||||
parse_deploy_tag "$@"
|
||||
DO_DEPLOY="${DO_DEPLOY:-0}"
|
||||
|
||||
# Load .env (load_deployment_env already did; keep for any vars set after)
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Infura: use Basic Auth URL when INFURA_PROJECT_SECRET is set (fixes "error sending request" from Infura)
|
||||
SCRIPT_LIB="$SCRIPT_DIR/../lib"
|
||||
[ -f "${SCRIPT_LIB}/infura.sh" ] && source "${SCRIPT_LIB}/infura.sh"
|
||||
|
||||
# Deployer address: use DEPLOYER_ADDRESS if set (matches MetaMask Portfolio), else derive from PRIVATE_KEY
|
||||
if [ -n "${DEPLOYER_ADDRESS:-}" ]; then
|
||||
DEPLOYER="${DEPLOYER_ADDRESS}"
|
||||
[[ "$DEPLOYER" != 0x* ]] && DEPLOYER="0x$DEPLOYER"
|
||||
else
|
||||
if [ -z "${PRIVATE_KEY:-}" ]; then
|
||||
echo "ERROR: Set PRIVATE_KEY in .env or set DEPLOYER_ADDRESS=0x4A666F96fC8764181194447A7dFdb7d471b301C8 for read-only balance check"
|
||||
exit 1
|
||||
fi
|
||||
DEPLOYER=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || true)
|
||||
if [ -z "$DEPLOYER" ]; then
|
||||
echo "ERROR: Could not derive deployer address from PRIVATE_KEY (is 'cast' available?)"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Gas estimate for "full" deploy per chain (conservative)
|
||||
GAS_FULL_DEPLOY_138="${GAS_FULL_DEPLOY_138:-5000000}"
|
||||
GAS_FULL_DEPLOY_MAINNET="${GAS_FULL_DEPLOY_MAINNET:-5000000}"
|
||||
BUFFER_BPS=120 # 20% buffer
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Short form for matching MetaMask Portfolio (0x4A66...b301C8)
|
||||
DEPLOYER_SHORT="${DEPLOYER:0:6}...${DEPLOYER: -6}"
|
||||
|
||||
echo -e "${BLUE}============================================${NC}"
|
||||
echo -e "${BLUE}Deployer balance & gas check (all networks)${NC}"
|
||||
echo -e "${BLUE}============================================${NC}"
|
||||
echo "Deployer: $DEPLOYER_SHORT (full: $DEPLOYER)"
|
||||
echo " (Matches MetaMask Portfolio when RPCs are reachable; use DEPLOYER_ADDRESS=0x... to check a specific wallet)"
|
||||
echo ""
|
||||
|
||||
# Format wei to ether with 8 decimal places (avoids excessive decimals from cast)
|
||||
format_wei_to_ether() {
|
||||
local wei="${1:-0}"
|
||||
local eth
|
||||
eth=$(echo "scale=10; $wei / 1000000000000000000" | bc 2>/dev/null) || eth="0"
|
||||
printf "%.8f" "${eth:-0}"
|
||||
}
|
||||
|
||||
# Infura Gas API: supported chain IDs (EIP-1559 style; API returns suggestedMaxFeePerGas in gwei)
|
||||
INFURA_GAS_API_CHAINS="1 137 10 8453 42161 11155111 84532 11155420 80002 43114 56 100 324 534352"
|
||||
|
||||
# Get gas price in wei from Infura Gas API for a given chain_id (optional).
|
||||
# Returns wei or empty; caller should fallback to cast gas-price.
|
||||
get_gas_price_wei_infura_api() {
|
||||
local chain_id="${1:-1}"
|
||||
local key=""
|
||||
if [ -n "${INFURA_GAS_API:-}" ]; then
|
||||
local url="$INFURA_GAS_API"
|
||||
if [[ "$url" == *"/v3/"* ]]; then
|
||||
key="${url#*v3/}"
|
||||
key="${key%%/*}"
|
||||
else
|
||||
key="$url"
|
||||
fi
|
||||
elif [ -n "${INFURA_PROJECT_ID:-}" ]; then
|
||||
key="${INFURA_PROJECT_ID}"
|
||||
fi
|
||||
if [ -z "$key" ] || ! command -v curl >/dev/null 2>&1 || ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
local api_url="https://gas.api.infura.io/v3/${key}/networks/${chain_id}/suggestedGasFees"
|
||||
local res
|
||||
res=$(curl -sL --connect-timeout 5 "$api_url" 2>/dev/null || true)
|
||||
if [ -z "$res" ] || echo "$res" | grep -qi "error\|required\|private key\|not found"; then
|
||||
return 1
|
||||
fi
|
||||
local gwei
|
||||
gwei=$(echo "$res" | jq -r '.medium.suggestedMaxFeePerGas // .standard.suggestedMaxFeePerGas // .standard.maxFeePerGas // .low.suggestedMaxFeePerGas // empty' 2>/dev/null)
|
||||
if [ -z "$gwei" ] || [ "$gwei" = "null" ]; then
|
||||
return 1
|
||||
fi
|
||||
local wei
|
||||
wei=$(echo "scale=0; ($gwei) * 1000000000 / 1" | bc 2>/dev/null)
|
||||
[ -n "$wei" ] && [ "$wei" != "0" ] && echo "$wei"
|
||||
}
|
||||
|
||||
# Get mainnet gas price from Infura Gas API (preferred) or RPC fallback.
|
||||
get_mainnet_gas_price_wei() {
|
||||
local wei
|
||||
wei=$(get_gas_price_wei_infura_api 1)
|
||||
if [ -z "$wei" ] || [ "$wei" = "0" ]; then
|
||||
[ -n "${ETHEREUM_MAINNET_RPC:-}" ] && command -v cast >/dev/null 2>&1 && wei=$(cast gas-price --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null || true)
|
||||
fi
|
||||
[ -n "$wei" ] && [ "$wei" != "0" ] && echo "$wei" || echo "30000000000"
|
||||
}
|
||||
|
||||
# Resolve gas price for a chain: try Infura Gas API first (if chain supported), else RPC, else default_wei.
|
||||
# Usage: get_gas_price_for_chain chain_id rpc_url default_wei
|
||||
# Output: wei (and sets GAS_SOURCE="Infura Gas API" or "RPC" or "default")
|
||||
get_gas_price_for_chain() {
|
||||
local chain_id="$1"
|
||||
local rpc_url="$2"
|
||||
local default_wei="${3:-30000000000}"
|
||||
local wei=""
|
||||
[ -n "$rpc_url" ] && type ensure_infura_rpc_url &>/dev/null && rpc_url=$(ensure_infura_rpc_url "$rpc_url")
|
||||
if [[ " $INFURA_GAS_API_CHAINS " == *" $chain_id "* ]]; then
|
||||
wei=$(get_gas_price_wei_infura_api "$chain_id")
|
||||
[ -n "$wei" ] && GAS_SOURCE="Infura Gas API" && echo "$wei" && return
|
||||
fi
|
||||
if [ -n "$rpc_url" ] && command -v cast >/dev/null 2>&1; then
|
||||
wei=$(cast gas-price --rpc-url "$rpc_url" 2>/dev/null || true)
|
||||
[ -n "$wei" ] && [ "$wei" != "0" ] && GAS_SOURCE="RPC" && echo "$wei" && return
|
||||
fi
|
||||
GAS_SOURCE="default"
|
||||
echo "$default_wei"
|
||||
}
|
||||
|
||||
mainnet_gas_wei=$(get_mainnet_gas_price_wei)
|
||||
mainnet_gas_gwei=$(printf "%.2f" $(echo "scale=4; $mainnet_gas_wei / 1000000000" | bc 2>/dev/null || echo "30"))
|
||||
echo "Gas prices (verified via Infura Gas API where supported, else RPC or default):"
|
||||
echo " Ethereum Mainnet (1): ${mainnet_gas_gwei} gwei (Infura Gas API)"
|
||||
echo ""
|
||||
|
||||
# Check native (gas) token balance for one network. Only this token can be used for gas on EVM.
|
||||
check_network() {
|
||||
local name="$1"
|
||||
local rpc="$2"
|
||||
local chain_id="${3:-}"
|
||||
local gas_token="${4:-ETH}"
|
||||
local gas_limit="${5:-$GAS_FULL_DEPLOY_MAINNET}"
|
||||
local gas_price_wei="${6:-$mainnet_gas_wei}"
|
||||
|
||||
if [ -z "$rpc" ]; then
|
||||
echo -e " ${YELLOW}$name (chain $chain_id): no RPC — gas token = $gas_token (not checked)${NC}"
|
||||
return 0
|
||||
fi
|
||||
type ensure_infura_rpc_url &>/dev/null && rpc=$(ensure_infura_rpc_url "$rpc")
|
||||
local balance_wei
|
||||
balance_wei=$(cast balance "$DEPLOYER" --rpc-url "$rpc" 2>/dev/null) || balance_wei=""
|
||||
local rpc_ok=1
|
||||
if [ -z "$balance_wei" ] || ! [[ "$balance_wei" =~ ^[0-9]+$ ]]; then
|
||||
rpc_ok=0
|
||||
balance_wei="0"
|
||||
fi
|
||||
local balance_display
|
||||
if [ "$rpc_ok" = "0" ]; then
|
||||
balance_display="(unable to fetch — RPC unreachable?)"
|
||||
else
|
||||
balance_display=$(format_wei_to_ether "$balance_wei")
|
||||
fi
|
||||
local cost_wei
|
||||
cost_wei=$(echo "$gas_limit * $gas_price_wei" | bc 2>/dev/null || echo "0")
|
||||
local cost_with_buffer
|
||||
cost_with_buffer=$(echo "$cost_wei * $BUFFER_BPS / 100" | bc 2>/dev/null || echo "$cost_wei")
|
||||
local cost_display
|
||||
cost_display=$(format_wei_to_ether "$cost_with_buffer")
|
||||
local ok=0
|
||||
[ "$rpc_ok" = "1" ] && [ "$(echo "$balance_wei >= $cost_with_buffer" | bc 2>/dev/null)" = "1" ] && ok=1
|
||||
if [ "$ok" = "1" ]; then
|
||||
echo -e " ${GREEN}$name (chain $chain_id): gas token $gas_token — balance ${balance_display}, required ~${cost_display} — OK for deploy${NC}"
|
||||
elif [ "$rpc_ok" = "0" ]; then
|
||||
echo -e " ${YELLOW}$name (chain $chain_id): gas token $gas_token — balance ${balance_display}, required ~${cost_display} — check RPC / run from network with access${NC}"
|
||||
else
|
||||
echo -e " ${RED}$name (chain $chain_id): gas token $gas_token — balance ${balance_display}, required ~${cost_display} — INSUFFICIENT for deploy${NC}"
|
||||
fi
|
||||
return $((1 - ok))
|
||||
}
|
||||
|
||||
# All networks: order matches MetaMask Portfolio (Ethereum, BSC, Arbitrum, Optimism, Polygon, Cronos, …)
|
||||
# Gas needed from Infura Gas API or RPC. Native gas token only (ETH, BNB, POL, CRO, etc.).
|
||||
echo "Checking gas token balance (same order as MetaMask Portfolio where applicable):"
|
||||
echo ""
|
||||
any_insufficient=0
|
||||
# --- Portfolio main networks (Ethereum, BSC, Arbitrum, Optimism, Polygon, Cronos) ---
|
||||
check_network "Ethereum Mainnet" "${ETHEREUM_MAINNET_RPC:-}" "1" "ETH" "$GAS_FULL_DEPLOY_MAINNET" "$mainnet_gas_wei" || any_insufficient=1
|
||||
check_network "BSC" "${BSC_RPC_URL:-${BSC_MAINNET_RPC:-https://bsc-dataseed.binance.org}}" "56" "BNB" "5000000" "$(get_gas_price_for_chain 56 "${BSC_RPC_URL:-${BSC_MAINNET_RPC:-}}" "5000000000")" || true
|
||||
check_network "Arbitrum" "${ARBITRUM_MAINNET_RPC:-https://arbitrum-one.publicnode.com}" "42161" "ETH" "5000000" "$(get_gas_price_for_chain 42161 "${ARBITRUM_MAINNET_RPC:-}" "100000000")" || true
|
||||
check_network "Optimism" "${OPTIMISM_MAINNET_RPC:-}" "10" "ETH" "5000000" "$(get_gas_price_for_chain 10 "${OPTIMISM_MAINNET_RPC:-}" "1000000")" || true
|
||||
check_network "Polygon" "${POLYGON_MAINNET_RPC:-}" "137" "POL" "5000000" "$(get_gas_price_for_chain 137 "${POLYGON_MAINNET_RPC:-}" "50000000000")" || any_insufficient=1
|
||||
check_network "Cronos" "${CRONOS_RPC_URL:-https://evm.cronos.org}" "25" "CRO" "5000000" "$(get_gas_price_for_chain 25 "${CRONOS_RPC_URL:-}" "1000000000")" || true
|
||||
# --- Chain 138 (project chain) ---
|
||||
check_network "Chain 138" "${RPC_URL_138:-}" "138" "ETH" "$GAS_FULL_DEPLOY_138" "$(cast gas-price --rpc-url "${RPC_URL_138:-http://192.168.11.211:8545}" 2>/dev/null || echo "1000000000")" || any_insufficient=1
|
||||
# --- Other mainnets ---
|
||||
check_network "Base" "${BASE_MAINNET_RPC:-}" "8453" "ETH" "5000000" "$(get_gas_price_for_chain 8453 "${BASE_MAINNET_RPC:-}" "100000000")" || true
|
||||
check_network "Avalanche" "${AVALANCHE_RPC_URL:-${AVALANCHE_MAINNET_RPC:-https://avalanche-c-chain.publicnode.com}}" "43114" "AVAX" "5000000" "$(get_gas_price_for_chain 43114 "${AVALANCHE_RPC_URL:-${AVALANCHE_MAINNET_RPC:-}}" "25000000000")" || true
|
||||
check_network "Gnosis" "${GNOSIS_MAINNET_RPC:-${GNOSIS_RPC:-https://rpc.gnosischain.com}}" "100" "xDAI" "5000000" "$(get_gas_price_for_chain 100 "${GNOSIS_MAINNET_RPC:-${GNOSIS_RPC:-}}" "1000000000")" || true
|
||||
# --- Testnets ---
|
||||
check_network "Ethereum Sepolia" "${ETHEREUM_SEPOLIA_RPC:-}" "11155111" "ETH" "5000000" "$(get_gas_price_for_chain 11155111 "${ETHEREUM_SEPOLIA_RPC:-}" "20000000000")" || true
|
||||
check_network "Polygon Amoy" "${POLYGON_AMOY_RPC:-}" "80002" "MATIC" "5000000" "$(get_gas_price_for_chain 80002 "${POLYGON_AMOY_RPC:-}" "30000000000")" || true
|
||||
check_network "Base Sepolia" "${BASE_SEPOLIA_RPC:-}" "84532" "ETH" "5000000" "$(get_gas_price_for_chain 84532 "${BASE_SEPOLIA_RPC:-}" "100000000")" || true
|
||||
check_network "Optimism Sepolia" "${OPTIMISM_SEPOLIA_RPC:-}" "11155420" "ETH" "5000000" "$(get_gas_price_for_chain 11155420 "${OPTIMISM_SEPOLIA_RPC:-}" "1000000")" || true
|
||||
|
||||
echo ""
|
||||
echo "Gas token summary: each chain uses only its native token for gas. ERC-20 (USDT, LINK, etc.) cannot pay gas."
|
||||
echo "Gas needed above was computed from: Infura Gas API (chains 1, 10, 56, 100, 137, 42161, 43114, 8453, 84532, 80002, 11155111, 11155420) or RPC eth_gasPrice when API unavailable."
|
||||
|
||||
echo ""
|
||||
if [ "${DO_DEPLOY:-0}" = "1" ]; then
|
||||
if [ -n "${DEPLOYER_ADDRESS:-}" ]; then
|
||||
echo -e "${RED}ERROR: --deploy requires PRIVATE_KEY in .env (unset DEPLOYER_ADDRESS to use key-derived deployer).${NC}"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${PRIVATE_KEY:-}" ]; then
|
||||
echo -e "${RED}ERROR: PRIVATE_KEY required for --deploy.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${BLUE}Deploy phase (Chain 138 only; other chains need CCIP_* env)${NC}"
|
||||
RPC_138="${RPC_URL_138:-http://192.168.11.211:8545}"
|
||||
balance_138=$(cast balance "$DEPLOYER" --rpc-url "$RPC_138" 2>/dev/null || echo "0")
|
||||
need_138=$(echo "5000000 * 1000000000 * $BUFFER_BPS / 100" | bc 2>/dev/null || echo "6000000000000000000")
|
||||
if [ -n "$balance_138" ] && [ "$(echo "$balance_138 >= $need_138" | bc 2>/dev/null)" = "1" ]; then
|
||||
echo "Deploying phased core (01_DeployCore, 02_DeployBridges) on Chain 138..."
|
||||
export PRIVATE_KEY
|
||||
out_01=$(mktemp)
|
||||
trap "rm -f $out_01" EXIT
|
||||
# Chain 138 often requires minimum gas price (e.g. 1 gwei)
|
||||
GAS_PRICE_138="${GAS_PRICE_138:-1000000000}"
|
||||
if forge script script/deploy/01_DeployCore.s.sol:DeployCore \
|
||||
--rpc-url "$RPC_138" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--broadcast \
|
||||
--with-gas-price "$GAS_PRICE_138" \
|
||||
-vvv 2>&1 | tee "$out_01"; then
|
||||
reg=$(grep "UNIVERSAL_ASSET_REGISTRY" "$out_01" | tail -1 | grep -oE "0x[a-fA-F0-9]{40}" | head -1)
|
||||
if [ -n "$reg" ] && [ -n "${CCIP_ROUTER:-}" ]; then
|
||||
export UNIVERSAL_ASSET_REGISTRY="$reg"
|
||||
forge script script/deploy/02_DeployBridges.s.sol:DeployBridges \
|
||||
--rpc-url "$RPC_138" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--broadcast \
|
||||
--with-gas-price "$GAS_PRICE_138" \
|
||||
-vvv 2>&1 || echo "02_DeployBridges failed or skipped."
|
||||
fi
|
||||
else
|
||||
echo "01_DeployCore failed or skipped (may already be deployed)."
|
||||
fi
|
||||
echo -e "${GREEN}Chain 138 deploy phase finished.${NC}"
|
||||
else
|
||||
echo -e "${RED}Chain 138 balance insufficient for deploy (need more native ETH on 138). Fund deployer and re-run.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Run with --deploy to run deployment on Chain 138 (phased core)."
|
||||
echo "Other chains: fund deployer with that chain's native token (MATIC, BNB, etc.) and set CCIP_* in .env for DeployAll."
|
||||
fi
|
||||
61
scripts/deployment/check-cronos-api.sh
Executable file
61
scripts/deployment/check-cronos-api.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
# Confirm Cronos deployments: test CRONOSCAN_API_KEY, verify contracts on-chain.
|
||||
# See docs/04-configuration/CRONOS_EXPLORER_OPERATIONS.md
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
RPC="${CRONOS_RPC_URL:-https://evm.cronos.org}"
|
||||
CONTRACTS=(
|
||||
"0x99B3511A2d315A497C8112C1fdd8D508d4B1E506:WETH9"
|
||||
"0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6:WETH10"
|
||||
"0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e:CCIPWETH9Bridge"
|
||||
"0x105F8A15b819948a89153505762444Ee9f324684:CCIPWETH10Bridge"
|
||||
)
|
||||
|
||||
echo "=== Cronos (Chain 25) deployment confirmation ==="
|
||||
echo ""
|
||||
|
||||
# 1. On-chain confirmation via RPC (eth_getCode)
|
||||
echo "1. On-chain bytecode check (RPC: $RPC):"
|
||||
ok=0 missing=0
|
||||
for entry in "${CONTRACTS[@]}"; do
|
||||
addr="${entry%%:*}"
|
||||
name="${entry##*:}"
|
||||
code=$(cast code "$addr" --rpc-url "$RPC" 2>/dev/null || echo "0x")
|
||||
if [ "${#code}" -gt 10 ]; then
|
||||
echo " ✓ $name ($addr)"
|
||||
((ok++)) || true
|
||||
else
|
||||
echo " ✗ $name ($addr) — no bytecode"
|
||||
((missing++)) || true
|
||||
fi
|
||||
done
|
||||
echo " Summary: $ok confirmed, $missing missing"
|
||||
echo ""
|
||||
|
||||
# 2. Explorer API (if key set)
|
||||
if [ -n "${CRONOSCAN_API_KEY:-}" ]; then
|
||||
echo "2. Cronos Explorer API (CRONOSCAN_API_KEY):"
|
||||
BLOCK=$(curl -s "https://explorer-api.cronos.org/mainnet/api/v1/ethproxy/getBlockNumber?apikey=${CRONOSCAN_API_KEY}")
|
||||
if echo "$BLOCK" | grep -q '"result"'; then
|
||||
NUM=$(echo "$BLOCK" | jq -r '.result')
|
||||
echo " ✓ Block number: $NUM (dec: $((NUM)))"
|
||||
else
|
||||
echo " ✗ API error: $BLOCK"
|
||||
fi
|
||||
echo ""
|
||||
else
|
||||
echo "2. Cronos Explorer API: SKIP (set CRONOSCAN_API_KEY for block/explorer data)"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 3. Verification instructions
|
||||
echo "3. Contract verification:"
|
||||
echo " Manual: https://explorer.cronos.org/verifyContract"
|
||||
echo " Per-address: https://explorer.cronos.org/address/<ADDR>"
|
||||
echo ""
|
||||
echo "Full reference: docs/04-configuration/CRONOS_EXPLORER_OPERATIONS.md"
|
||||
44
scripts/deployment/check-cronos-verification-status.sh
Executable file
44
scripts/deployment/check-cronos-verification-status.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check Cronos contract deployment and verification status.
|
||||
# Verification status must be checked manually by visiting each explorer URL;
|
||||
# this script confirms on-chain deployment and prints links.
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
RPC="${CRONOS_RPC_URL:-https://evm.cronos.org}"
|
||||
CONTRACTS=(
|
||||
"0x99B3511A2d315A497C8112C1fdd8D508d4B1E506:WETH9"
|
||||
"0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6:WETH10"
|
||||
"0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e:CCIPWETH9Bridge"
|
||||
"0x105F8A15b819948a89153505762444Ee9f324684:CCIPWETH10Bridge"
|
||||
)
|
||||
|
||||
echo "=== Cronos (Chain 25) contract status ==="
|
||||
echo ""
|
||||
echo "On-chain deployment:"
|
||||
for entry in "${CONTRACTS[@]}"; do
|
||||
addr="${entry%%:*}"
|
||||
name="${entry##*:}"
|
||||
code=$(cast code "$addr" --rpc-url "$RPC" 2>/dev/null || echo "0x")
|
||||
if [ "${#code}" -gt 10 ]; then
|
||||
echo " ✓ $name — DEPLOYED"
|
||||
else
|
||||
echo " ✗ $name — MISSING"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Verification status (check each link manually):"
|
||||
echo " Verified contracts show 'Contract Source Code Verified' or display source."
|
||||
echo ""
|
||||
for entry in "${CONTRACTS[@]}"; do
|
||||
addr="${entry%%:*}"
|
||||
name="${entry##*:}"
|
||||
echo " $name: https://explorer.cronos.org/address/$addr"
|
||||
done
|
||||
echo ""
|
||||
echo "Run ./scripts/deployment/export-cronos-verification-sources.sh and follow"
|
||||
echo "docs/deployment/CRONOS_VERIFICATION_RUNBOOK.md to verify unverified contracts."
|
||||
59
scripts/deployment/check-dapp-env.sh
Executable file
59
scripts/deployment/check-dapp-env.sh
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check that .env has the VITE_* (and related) vars needed for frontend-dapp production build.
|
||||
# Usage: ./scripts/deployment/check-dapp-env.sh [path-to-.env]
|
||||
# Exit 0 if all required are set; exit 1 and list missing if not.
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
ENV_FILE="${1:-$REPO_ROOT/.env}"
|
||||
|
||||
get_var() {
|
||||
local name="$1"
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
local line
|
||||
line="$(grep -E "^(export[[:space:]]+)?${name}=" "$ENV_FILE" 2>/dev/null | head -1)"
|
||||
if [[ -n "$line" ]]; then
|
||||
echo "$line" | sed -E 's/^(export[[:space:]]+)?[^=]+=//' | sed 's/^["'\'' ]//;s/["'\'' ]$//' | xargs
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
REQUIRED_FOR_BUILD=(
|
||||
"VITE_RPC_URL_138"
|
||||
)
|
||||
OPTIONAL_BUT_RECOMMENDED=(
|
||||
"VITE_LOCKBOX_138"
|
||||
"VITE_INBOX_ETH_MAINNET"
|
||||
"VITE_LIQUIDITY_POOL_ETH_MAINNET"
|
||||
"VITE_DUAL_ROUTER_BRIDGE_SWAP_COORDINATOR"
|
||||
"VITE_CHALLENGE_MANAGER_MAINNET"
|
||||
"VITE_WALLETCONNECT_PROJECT_ID"
|
||||
"VITE_THIRDWEB_CLIENT_ID"
|
||||
)
|
||||
|
||||
missing=()
|
||||
for v in "${REQUIRED_FOR_BUILD[@]}"; do
|
||||
val="$(get_var "$v")"
|
||||
if [[ -z "$val" || "$val" == "0x..." || "$val" == "your-"* ]]; then
|
||||
missing+=("$v")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
echo "Missing or placeholder required for DApp build: ${missing[*]}"
|
||||
echo "Set them in $ENV_FILE (or copy from .env.example and fill)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Required VITE_* for DApp build are set."
|
||||
for v in "${OPTIONAL_BUT_RECOMMENDED[@]}"; do
|
||||
val="$(get_var "$v")"
|
||||
if [[ -z "$val" || "$val" == "0x..." || "$val" == "your-"* ]]; then
|
||||
echo "Optional (recommended): $v"
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
65
scripts/deployment/check-env-required.sh
Executable file
65
scripts/deployment/check-env-required.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check smom-dbis-138/.env for required and optional variable names (no values printed).
|
||||
# Usage: ./scripts/deployment/check-env-required.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
ENV_FILE="${PROJECT_ROOT}/.env"
|
||||
|
||||
echo "=== .env check (keys only, no values) ==="
|
||||
echo ""
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo " .env: MISSING"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build list of key names (strip values; never print values)
|
||||
keys_file=$(mktemp)
|
||||
trap 'rm -f "$keys_file"' EXIT
|
||||
grep -E '^[A-Za-z_][A-Za-z0-9_]*=' "$ENV_FILE" 2>/dev/null | sed 's/=.*//' > "$keys_file" || true
|
||||
grep -E '^export [A-Za-z_][A-Za-z0-9_]*=' "$ENV_FILE" 2>/dev/null | sed 's/^export //; s/=.*//' >> "$keys_file" || true
|
||||
sort -u "$keys_file" -o "$keys_file"
|
||||
|
||||
check() { grep -qx "$1" "$keys_file" 2>/dev/null; }
|
||||
total=$(wc -l < "$keys_file")
|
||||
echo " .env: EXISTS ($total keys)"
|
||||
echo ""
|
||||
|
||||
# Required for deploy-contracts-unified.sh and most Chain 138 scripts
|
||||
echo "--- Required (deploy / Chain 138) ---"
|
||||
for k in PRIVATE_KEY RPC_URL RPC_URL_138; do
|
||||
check "$k" && echo " OK $k" || echo " MISS $k"
|
||||
done
|
||||
|
||||
# PRIVATE_KEY format: 64 hex chars (no value printed)
|
||||
if check "PRIVATE_KEY"; then
|
||||
len=$(awk -F= '/^PRIVATE_KEY=/ { v=$2; gsub(/^0x/,"",v); print length(v) }' "$ENV_FILE" 2>/dev/null || echo "0")
|
||||
[ "$len" = "64" ] && echo " PRIVATE_KEY format: 64-char hex" || echo " PRIVATE_KEY format: WARN (length=$len, expected 64)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Optional for PMM pool script (create-all-dodo-pools-from-token-api.sh)
|
||||
echo "--- Optional (PMM pools: DODO_PMM_INTEGRATION or DODO_PMM_INTEGRATION_ADDRESS, QUOTE_TOKEN or QUOTE_TOKEN_ADDRESS / WETH_ADDRESS_138) ---"
|
||||
for k in DODO_PMM_INTEGRATION DODO_PMM_INTEGRATION_ADDRESS QUOTE_TOKEN QUOTE_TOKEN_ADDRESS WETH_ADDRESS_138; do
|
||||
check "$k" && echo " OK $k" || echo " -- $k"
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Optional for mainnet dry-run
|
||||
echo "--- Optional (mainnet dry-run) ---"
|
||||
for k in ETHEREUM_MAINNET_RPC; do
|
||||
check "$k" && echo " OK $k" || echo " -- $k"
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Common CCIP / bridge
|
||||
echo "--- Optional (CCIP / bridge) ---"
|
||||
for k in CCIP_ROUTER LINK_TOKEN CCIPWETH9_BRIDGE_CHAIN138 CCIPWETH10_BRIDGE_CHAIN138; do
|
||||
check "$k" && echo " OK $k" || echo " -- $k"
|
||||
done
|
||||
echo ""
|
||||
|
||||
echo "Done. Fix any MISS above; -- means optional and can be set when needed."
|
||||
86
scripts/deployment/check-link-balance-config-ready-chains.sh
Executable file
86
scripts/deployment/check-link-balance-config-ready-chains.sh
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check deployer LINK balance on Gnosis, Cronos, Celo (config-ready chains).
|
||||
# Required before fund-ccip-bridges-with-link.sh: 20 LINK per chain (10 per bridge).
|
||||
#
|
||||
# Usage: ./scripts/deployment/check-link-balance-config-ready-chains.sh [gnosis|cronos|celo|all]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
[[ -f "$PROJECT_ROOT/.env" ]] && set -a && source "$PROJECT_ROOT/.env" && set +a
|
||||
|
||||
CHAIN="${1:-all}"
|
||||
REQUIRED_LINK="20" # 10 per WETH9 bridge + 10 per WETH10 bridge
|
||||
|
||||
# LINK token addresses (from CCIP directory)
|
||||
LINK_TOKEN_GNOSIS="${LINK_TOKEN_GNOSIS:-${CCIP_GNOSIS_LINK_TOKEN:-0xE2e73A1c69ecF83F464EFCE6A5be353a37cA09b2}}"
|
||||
LINK_TOKEN_CRONOS="${LINK_TOKEN_CRONOS:-${CCIP_CRONOS_LINK_TOKEN:-0x8c80A01F461f297Df7F9DA3A4f740D7297C8Ac85}}"
|
||||
LINK_TOKEN_CELO="${LINK_TOKEN_CELO:-${CCIP_CELO_LINK_TOKEN:-0xd07294e6E917e07dfDcee882dd1e2565085C2ae0}}"
|
||||
|
||||
GNOSIS_RPC="${GNOSIS_RPC:-https://rpc.gnosischain.com}"
|
||||
CRONOS_RPC="${CRONOS_RPC:-https://evm.cronos.org}"
|
||||
CELO_RPC="${CELO_RPC:-https://forno.celo.org}"
|
||||
|
||||
if [[ -z "${PRIVATE_KEY:-}" ]]; then
|
||||
echo "Error: Set PRIVATE_KEY in .env" >&2
|
||||
exit 1
|
||||
fi
|
||||
DEPLOYER=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || true)
|
||||
[[ -z "$DEPLOYER" ]] && { echo "Error: Could not derive deployer from PRIVATE_KEY" >&2; exit 1; }
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
check_link() {
|
||||
local name="$1" rpc="$2" link_token="$3"
|
||||
[[ -z "$rpc" || -z "$link_token" ]] && return 1
|
||||
local raw
|
||||
raw=$(cast call "$link_token" "balanceOf(address)(uint256)" "$DEPLOYER" --rpc-url "$rpc" 2>/dev/null || echo "0")
|
||||
local link_val
|
||||
link_val=$(echo "scale=4; $raw / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
||||
if [[ -z "$link_val" || "$link_val" == "0" ]]; then
|
||||
echo -e " ${RED}✗${NC} $name: 0 LINK (need $REQUIRED_LINK LINK)"
|
||||
return 1
|
||||
fi
|
||||
if [[ "$(echo "$link_val >= $REQUIRED_LINK" | bc 2>/dev/null)" == "1" ]]; then
|
||||
echo -e " ${GREEN}✓${NC} $name: $link_val LINK"
|
||||
return 0
|
||||
fi
|
||||
echo -e " ${YELLOW}⚠${NC} $name: $link_val LINK (need $REQUIRED_LINK LINK)"
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "=== LINK Balance Check (Config-Ready Chains) ==="
|
||||
echo "Deployer: ${DEPLOYER:0:10}...${DEPLOYER: -8}"
|
||||
echo "Required: $REQUIRED_LINK LINK per chain (10 per WETH9 + 10 per WETH10 bridge)"
|
||||
echo ""
|
||||
|
||||
failed=0
|
||||
case "$CHAIN" in
|
||||
gnosis) check_link "Gnosis" "$GNOSIS_RPC" "$LINK_TOKEN_GNOSIS" || failed=1 ;;
|
||||
cronos) check_link "Cronos" "$CRONOS_RPC" "$LINK_TOKEN_CRONOS" || failed=1 ;;
|
||||
celo) check_link "Celo" "$CELO_RPC" "$LINK_TOKEN_CELO" || failed=1 ;;
|
||||
all)
|
||||
check_link "Gnosis" "$GNOSIS_RPC" "$LINK_TOKEN_GNOSIS" || failed=1
|
||||
check_link "Cronos" "$CRONOS_RPC" "$LINK_TOKEN_CRONOS" || failed=1
|
||||
check_link "Celo" "$CELO_RPC" "$LINK_TOKEN_CELO" || failed=1
|
||||
;;
|
||||
*) echo "Usage: $0 [gnosis|cronos|celo|all]"; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
if [[ $failed -eq 0 ]]; then
|
||||
echo "LINK balance OK. Run: ./scripts/deployment/fund-ccip-bridges-with-link.sh"
|
||||
exit 0
|
||||
else
|
||||
echo "Acquire LINK on each chain (bridge from mainnet or DEX), then re-run this check."
|
||||
echo " Gnosis: $LINK_TOKEN_GNOSIS"
|
||||
echo " Cronos: $LINK_TOKEN_CRONOS"
|
||||
echo " Celo: $LINK_TOKEN_CELO"
|
||||
exit 1
|
||||
fi
|
||||
38
scripts/deployment/check-syntax.sh
Executable file
38
scripts/deployment/check-syntax.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check bash syntax of deployment scripts and lib (bash -n). Run from anywhere.
|
||||
# Usage: ./scripts/deployment/check-syntax.sh or bash scripts/deployment/check-syntax.sh
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
FAIL=0
|
||||
|
||||
check() {
|
||||
if bash -n "$1" 2>/dev/null; then
|
||||
echo " OK $1"
|
||||
else
|
||||
echo " FAIL $1"
|
||||
FAIL=1
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Checking deployment scripts and lib..."
|
||||
check scripts/lib/deployment/prompts.sh
|
||||
check scripts/lib/deployment/dotenv.sh
|
||||
check scripts/deployment/fund-mainnet-lp.sh
|
||||
check scripts/deployment/run-all-four-gaps.sh
|
||||
check scripts/deployment/deploy-pmm-all-l2s.sh
|
||||
check scripts/deployment/deploy-trustless-l2s.sh
|
||||
check scripts/deployment/fund-ccip-bridges-with-link.sh
|
||||
check scripts/deployment/fix-nonce-and-retry.sh
|
||||
check scripts/deployment/run-remaining-g2g3-with-nonce-fix.sh
|
||||
check scripts/deployment/run-pmm-and-pools.sh
|
||||
check scripts/deployment/check-balances-gas-and-deploy.sh
|
||||
|
||||
if [[ "$FAIL" -eq 0 ]]; then
|
||||
echo "All passed."
|
||||
else
|
||||
echo "Some checks failed."
|
||||
exit 1
|
||||
fi
|
||||
136
scripts/deployment/complete-config-ready-chains.sh
Executable file
136
scripts/deployment/complete-config-ready-chains.sh
Executable file
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env bash
|
||||
# Complete CCIP bridge configuration for Config-Ready chains (Gnosis, Celo, Wemix).
|
||||
# - Adds each chain as destination on Chain 138 bridges (138 → Gnosis/Celo/Wemix).
|
||||
# - Adds Chain 138 as destination on each chain's bridges (Gnosis/Celo/Wemix → 138).
|
||||
# Requires: bridge addresses and RPCs in .env; PRIVATE_KEY; CHAIN138_SELECTOR for step 2.
|
||||
# Usage: ./scripts/deployment/complete-config-ready-chains.sh
|
||||
# DRY_RUN=1 ./scripts/deployment/complete-config-ready-chains.sh # print commands only
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
[[ -f "$SCRIPT_DIR/../lib/init.sh" ]] && source "$SCRIPT_DIR/../lib/init.sh" 2>/dev/null || true
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
if [[ -f "$PROJECT_ROOT/.env" ]]; then
|
||||
set -a
|
||||
source "$PROJECT_ROOT/.env"
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Chain selectors (decimal, for addDestination(uint64,address))
|
||||
ETH_MAINNET_SELECTOR="${ETH_MAINNET_SELECTOR:-5009297550715157269}"
|
||||
GNOSIS_SELECTOR="${GNOSIS_SELECTOR:-465200170687744372}"
|
||||
CRONOS_SELECTOR="${CRONOS_SELECTOR:-1456215246176062136}"
|
||||
CELO_SELECTOR="${CELO_SELECTOR:-1346049177634351622}"
|
||||
WEMIX_SELECTOR="${WEMIX_SELECTOR:-5142893604156789321}"
|
||||
CHAIN138_SELECTOR="${CHAIN138_SELECTOR:-}"
|
||||
|
||||
CHAIN138_RPC="${CHAIN138_RPC:-${RPC_URL:-https://rpc-core.d-bis.org}}"
|
||||
GNOSIS_RPC="${GNOSIS_RPC:-https://rpc.gnosischain.com}"
|
||||
CRONOS_RPC="${CRONOS_RPC:-https://evm.cronos.org}"
|
||||
CELO_RPC="${CELO_RPC:-https://forno.celo.org}"
|
||||
WEMIX_RPC="${WEMIX_RPC:-https://api.wemix.com}"
|
||||
|
||||
PRIVATE_KEY="${PRIVATE_KEY:-}"
|
||||
if [[ -n "$PRIVATE_KEY" && ! "$PRIVATE_KEY" =~ ^0x ]]; then
|
||||
PRIVATE_KEY="0x$PRIVATE_KEY"
|
||||
fi
|
||||
|
||||
# Chain 138 bridge addresses (required)
|
||||
WETH9_138=$(grep "CCIPWETH9_BRIDGE_CHAIN138=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH9_BRIDGE_CHAIN138:-}")
|
||||
WETH10_138=$(grep "CCIPWETH10_BRIDGE_CHAIN138=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH10_BRIDGE_CHAIN138:-}")
|
||||
|
||||
# Config-ready chain bridge addresses (optional; if set, we configure them)
|
||||
WETH9_GNOSIS=$(grep "CCIPWETH9_BRIDGE_GNOSIS=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH9_BRIDGE_GNOSIS:-}")
|
||||
WETH10_GNOSIS=$(grep "CCIPWETH10_BRIDGE_GNOSIS=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH10_BRIDGE_GNOSIS:-}")
|
||||
WETH9_CRONOS=$(grep "CCIPWETH9_BRIDGE_CRONOS=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH9_BRIDGE_CRONOS:-}")
|
||||
WETH10_CRONOS=$(grep "CCIPWETH10_BRIDGE_CRONOS=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH10_BRIDGE_CRONOS:-}")
|
||||
WETH9_CELO=$(grep "CCIPWETH9_BRIDGE_CELO=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH9_BRIDGE_CELO:-}")
|
||||
WETH10_CELO=$(grep "CCIPWETH10_BRIDGE_CELO=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH10_BRIDGE_CELO:-}")
|
||||
WETH9_WEMIX=$(grep "CCIPWETH9_BRIDGE_WEMIX=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH9_BRIDGE_WEMIX:-}")
|
||||
WETH10_WEMIX=$(grep "CCIPWETH10_BRIDGE_WEMIX=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "${CCIPWETH10_BRIDGE_WEMIX:-}")
|
||||
|
||||
DRY_RUN="${DRY_RUN:-0}"
|
||||
|
||||
log_info "=== Config-Ready Chains Completion (Gnosis, Cronos, Celo, Wemix) ==="
|
||||
|
||||
if [[ -z "$WETH9_138" || -z "$WETH10_138" ]]; then
|
||||
echo "Error: Chain 138 bridge addresses not set. Set in .env: CCIPWETH9_BRIDGE_CHAIN138, CCIPWETH10_BRIDGE_CHAIN138" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$PRIVATE_KEY" ]]; then
|
||||
echo "Error: PRIVATE_KEY not set in .env" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run_or_echo() {
|
||||
if [[ "$DRY_RUN" = "1" ]]; then
|
||||
echo " [DRY RUN] $*"
|
||||
else
|
||||
if eval "$*" >/dev/null 2>&1; then
|
||||
log_success " OK"
|
||||
else
|
||||
log_warn " Failed (non-fatal) - run manually to see error"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# ---- Step A: On Chain 138, add Gnosis/Cronos/Celo/Wemix as destinations ----
|
||||
echo ""
|
||||
echo "Step A: Chain 138 bridges → add Gnosis, Cronos, Celo, Wemix as destinations"
|
||||
|
||||
while IFS= read -r line; do
|
||||
read -r label selector addr9 addr10 rpc <<< "$line"
|
||||
if [[ -z "$addr9" && -z "$addr10" ]]; then
|
||||
echo " Skip $label (no bridge addresses in .env)"
|
||||
continue
|
||||
fi
|
||||
echo " Configuring Chain 138 → $label..."
|
||||
if [[ -n "$addr9" ]]; then
|
||||
run_or_echo "cast send $WETH9_138 \"addDestination(uint64,address)\" $selector $addr9 --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy --gas-limit 200000"
|
||||
fi
|
||||
if [[ -n "$addr10" ]]; then
|
||||
run_or_echo "cast send $WETH10_138 \"addDestination(uint64,address)\" $selector $addr10 --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy --gas-limit 200000"
|
||||
fi
|
||||
done << EOF
|
||||
Gnosis $GNOSIS_SELECTOR $WETH9_GNOSIS $WETH10_GNOSIS $GNOSIS_RPC
|
||||
Cronos $CRONOS_SELECTOR $WETH9_CRONOS $WETH10_CRONOS $CRONOS_RPC
|
||||
Celo $CELO_SELECTOR $WETH9_CELO $WETH10_CELO $CELO_RPC
|
||||
Wemix $WEMIX_SELECTOR $WETH9_WEMIX $WETH10_WEMIX $WEMIX_RPC
|
||||
EOF
|
||||
|
||||
# ---- Step B: On Gnosis/Cronos/Celo/Wemix, add Chain 138 as destination ----
|
||||
if [[ -z "$CHAIN138_SELECTOR" ]]; then
|
||||
echo ""
|
||||
echo "Step B: Skipped (CHAIN138_SELECTOR not set in .env). Set it to configure remote chains → Chain 138."
|
||||
echo " Example: CHAIN138_SELECTOR=<decimal from CCIP Router getChainSelector()>"
|
||||
else
|
||||
echo ""
|
||||
echo "Step B: Gnosis/Cronos/Celo/Wemix bridges → add Chain 138 as destination"
|
||||
|
||||
while IFS= read -r line; do
|
||||
read -r label rpc addr9 addr10 <<< "$line"
|
||||
if [[ -z "$addr9" && -z "$addr10" ]]; then
|
||||
echo " Skip $label (no bridge addresses)"
|
||||
continue
|
||||
fi
|
||||
echo " Configuring $label → Chain 138..."
|
||||
if [[ -n "$addr9" ]]; then
|
||||
run_or_echo "cast send $addr9 \"addDestination(uint64,address)\" $CHAIN138_SELECTOR $WETH9_138 --rpc-url $rpc --private-key \$PRIVATE_KEY --legacy"
|
||||
fi
|
||||
if [[ -n "$addr10" ]]; then
|
||||
run_or_echo "cast send $addr10 \"addDestination(uint64,address)\" $CHAIN138_SELECTOR $WETH10_138 --rpc-url $rpc --private-key \$PRIVATE_KEY --legacy"
|
||||
fi
|
||||
done << EOF
|
||||
Gnosis $GNOSIS_RPC $WETH9_GNOSIS $WETH10_GNOSIS
|
||||
Cronos $CRONOS_RPC $WETH9_CRONOS $WETH10_CRONOS
|
||||
Celo $CELO_RPC $WETH9_CELO $WETH10_CELO
|
||||
Wemix $WEMIX_RPC $WETH9_WEMIX $WETH10_WEMIX
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_success "Config-ready chains script finished."
|
||||
echo " Next: Fund each remote bridge with LINK (see docs/07-ccip/CONFIG_READY_CHAINS_COMPLETION_RUNBOOK.md)."
|
||||
130
scripts/deployment/configure-avalanche-arbitrum-cronos-bridges.sh
Executable file
130
scripts/deployment/configure-avalanche-arbitrum-cronos-bridges.sh
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env bash
|
||||
# Configure CCIP bridge destinations for Avalanche, Arbitrum, Cronos ↔ Chain 138.
|
||||
# Step A: On Chain 138, add Avalanche/Arbitrum/Cronos as destinations
|
||||
# Step B: On Avalanche/Arbitrum/Cronos, add Chain 138 as destination
|
||||
# Requires: bridge addresses and CHAIN138_SELECTOR in .env; PRIVATE_KEY; Chain 138 RPC reachable for Step A.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if [[ -f .env ]]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
[[ -f "$SCRIPT_DIR/../lib/infura.sh" ]] && source "$SCRIPT_DIR/../lib/infura.sh"
|
||||
|
||||
# Chain selectors (decimal)
|
||||
AVALANCHE_SELECTOR="${AVALANCHE_SELECTOR:-6433500567565415381}"
|
||||
ARBITRUM_SELECTOR="${ARBITRUM_SELECTOR:-4949039107694359620}"
|
||||
CRONOS_SELECTOR="${CRONOS_SELECTOR:-1456215246176062136}"
|
||||
CHAIN138_SELECTOR="${CHAIN138_SELECTOR:-138}"
|
||||
|
||||
CHAIN138_RPC="${RPC_URL_138:-${CHAIN138_RPC:-http://192.168.11.211:8545}}"
|
||||
# Prefer explicit RPC; else Infura (INFURA_PROJECT_ID + optional INFURA_PROJECT_SECRET); else public
|
||||
_avalanche_infura=$(build_infura_rpc "avalanche-mainnet" 2>/dev/null || true)
|
||||
_arbitrum_infura=$(build_infura_rpc "arbitrum-mainnet" 2>/dev/null || true)
|
||||
AVALANCHE_RPC="${AVALANCHE_RPC_URL:-${AVALANCHE_RPC:-${_avalanche_infura:-https://avalanche-c-chain.publicnode.com}}}"
|
||||
ARBITRUM_RPC="${ARBITRUM_MAINNET_RPC:-${ARBITRUM_RPC:-${_arbitrum_infura:-https://arbitrum-one.publicnode.com}}}"
|
||||
CRONOS_RPC="${CRONOS_RPC_URL:-${CRONOS_RPC:-https://evm.cronos.org}}"
|
||||
|
||||
WETH9_138="${CCIPWETH9_BRIDGE_CHAIN138:-}"
|
||||
WETH10_138="${CCIPWETH10_BRIDGE_CHAIN138:-}"
|
||||
WETH9_AVALANCHE="${CCIPWETH9_BRIDGE_AVALANCHE:-}"
|
||||
WETH10_AVALANCHE="${CCIPWETH10_BRIDGE_AVALANCHE:-}"
|
||||
WETH9_ARBITRUM="${CCIPWETH9_BRIDGE_ARBITRUM:-}"
|
||||
WETH10_ARBITRUM="${CCIPWETH10_BRIDGE_ARBITRUM:-}"
|
||||
WETH9_CRONOS="${CCIPWETH9_BRIDGE_CRONOS:-}"
|
||||
WETH10_CRONOS="${CCIPWETH10_BRIDGE_CRONOS:-}"
|
||||
|
||||
PRIVATE_KEY="${PRIVATE_KEY:-}"
|
||||
[[ -n "$PRIVATE_KEY" && ! "$PRIVATE_KEY" =~ ^0x ]] && PRIVATE_KEY="0x$PRIVATE_KEY"
|
||||
|
||||
DRY_RUN="${DRY_RUN:-0}"
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
run_or_echo() {
|
||||
if [[ "$DRY_RUN" = "1" ]]; then
|
||||
echo " [DRY RUN] $*"
|
||||
else
|
||||
if eval "$*"; then
|
||||
echo -e " ${GREEN}OK${NC}"
|
||||
else
|
||||
echo -e " ${RED}Failed${NC}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
echo -e "${GREEN}=== Avalanche/Arbitrum/Cronos ↔ Chain 138 Bridge Configuration ===${NC}"
|
||||
echo ""
|
||||
|
||||
if [[ -z "$PRIVATE_KEY" ]]; then
|
||||
echo -e "${RED}ERROR: PRIVATE_KEY not set${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$WETH9_138" ]]; then
|
||||
echo -e "${RED}ERROR: CCIPWETH9_BRIDGE_CHAIN138 must be set in .env${NC}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "$WETH10_138" ]]; then
|
||||
echo -e "${YELLOW}NOTE: CCIPWETH10_BRIDGE_CHAIN138 not set; skipping WETH10 bridge configuration${NC}"
|
||||
fi
|
||||
|
||||
echo "Step A: Chain 138 → add Avalanche, Arbitrum, Cronos as destinations"
|
||||
echo " (Requires Chain 138 RPC reachable: $CHAIN138_RPC)"
|
||||
echo ""
|
||||
|
||||
# Step A: Chain 138 → Avalanche
|
||||
if [[ -n "$WETH9_AVALANCHE" || -n "$WETH10_AVALANCHE" ]]; then
|
||||
echo " Chain 138 → Avalanche:"
|
||||
[[ -n "$WETH9_AVALANCHE" ]] && run_or_echo "cast send $WETH9_138 'addDestination(uint64,address)' $AVALANCHE_SELECTOR $WETH9_AVALANCHE --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
[[ -n "$WETH10_AVALANCHE" ]] && run_or_echo "cast send $WETH10_138 'addDestination(uint64,address)' $AVALANCHE_SELECTOR $WETH10_AVALANCHE --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
fi
|
||||
# Step A: Chain 138 → Arbitrum
|
||||
if [[ -n "$WETH9_ARBITRUM" || -n "$WETH10_ARBITRUM" ]]; then
|
||||
echo " Chain 138 → Arbitrum:"
|
||||
[[ -n "$WETH9_ARBITRUM" ]] && run_or_echo "cast send $WETH9_138 'addDestination(uint64,address)' $ARBITRUM_SELECTOR $WETH9_ARBITRUM --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
[[ -n "$WETH10_ARBITRUM" ]] && run_or_echo "cast send $WETH10_138 'addDestination(uint64,address)' $ARBITRUM_SELECTOR $WETH10_ARBITRUM --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
fi
|
||||
# Step A: Chain 138 → Cronos
|
||||
if [[ -n "$WETH9_CRONOS" || -n "$WETH10_CRONOS" ]]; then
|
||||
echo " Chain 138 → Cronos:"
|
||||
[[ -n "$WETH9_CRONOS" ]] && run_or_echo "cast send $WETH9_138 'addDestination(uint64,address)' $CRONOS_SELECTOR $WETH9_CRONOS --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
[[ -n "$WETH10_CRONOS" ]] && run_or_echo "cast send $WETH10_138 'addDestination(uint64,address)' $CRONOS_SELECTOR $WETH10_CRONOS --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Step B: Avalanche/Arbitrum/Cronos → add Chain 138 as destination"
|
||||
echo ""
|
||||
|
||||
# Step B: Avalanche → Chain 138
|
||||
if [[ -n "$WETH9_AVALANCHE" || -n "$WETH10_AVALANCHE" ]]; then
|
||||
echo " Avalanche → Chain 138:"
|
||||
[[ -n "$WETH9_AVALANCHE" ]] && run_or_echo "cast send $WETH9_AVALANCHE 'addDestination(uint64,address)' $CHAIN138_SELECTOR $WETH9_138 --rpc-url $AVALANCHE_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
[[ -n "$WETH10_AVALANCHE" ]] && run_or_echo "cast send $WETH10_AVALANCHE 'addDestination(uint64,address)' $CHAIN138_SELECTOR $WETH10_138 --rpc-url $AVALANCHE_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
fi
|
||||
# Step B: Arbitrum → Chain 138
|
||||
if [[ -n "$WETH9_ARBITRUM" || -n "$WETH10_ARBITRUM" ]]; then
|
||||
echo " Arbitrum → Chain 138:"
|
||||
[[ -n "$WETH9_ARBITRUM" ]] && run_or_echo "cast send $WETH9_ARBITRUM 'addDestination(uint64,address)' $CHAIN138_SELECTOR $WETH9_138 --rpc-url $ARBITRUM_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
[[ -n "$WETH10_ARBITRUM" ]] && run_or_echo "cast send $WETH10_ARBITRUM 'addDestination(uint64,address)' $CHAIN138_SELECTOR $WETH10_138 --rpc-url $ARBITRUM_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
fi
|
||||
# Step B: Cronos → Chain 138
|
||||
if [[ -n "$WETH9_CRONOS" || -n "$WETH10_CRONOS" ]]; then
|
||||
echo " Cronos → Chain 138:"
|
||||
[[ -n "$WETH9_CRONOS" ]] && run_or_echo "cast send $WETH9_CRONOS 'addDestination(uint64,address)' $CHAIN138_SELECTOR $WETH9_138 --rpc-url $CRONOS_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
[[ -n "$WETH10_CRONOS" ]] && run_or_echo "cast send $WETH10_CRONOS 'addDestination(uint64,address)' $CHAIN138_SELECTOR $WETH10_138 --rpc-url $CRONOS_RPC --private-key \$PRIVATE_KEY --legacy" || true
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Bridge configuration complete.${NC}"
|
||||
echo "Next: Fund each bridge with LINK for CCIP fees if not already done."
|
||||
@@ -1,57 +1,107 @@
|
||||
#!/usr/bin/env bash
|
||||
# Configure bridge destinations for cross-chain functionality
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/../lib/init.sh"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
# Configure Bridge Destinations Script
|
||||
# Configures ChainID 138 ↔ Mainnet bidirectional bridge destinations
|
||||
|
||||
set -e
|
||||
|
||||
log_info "=== Configuring Bridge Destinations ==="
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Load environment
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
source "$PROJECT_ROOT/.env"
|
||||
fi
|
||||
# Configuration
|
||||
PRIVATE_KEY="${PRIVATE_KEY:-}"
|
||||
RPC_URL_138="${RPC_URL_138:-http://192.168.11.175:8545}"
|
||||
RPC_URL_MAINNET="${RPC_URL_MAINNET:-https://eth.llamarpc.com}"
|
||||
|
||||
MAINNET_RPC="${ETHEREUM_MAINNET_RPC:-https://eth.llamarpc.com}"
|
||||
CHAIN138_RPC="${RPC_URL:-https://rpc.d-bis.org}"
|
||||
PRIVATE_KEY="${PRIVATE_KEY}"
|
||||
if [[ ! "$PRIVATE_KEY" =~ ^0x ]]; then
|
||||
PRIVATE_KEY="0x$PRIVATE_KEY"
|
||||
fi
|
||||
# Chain Selectors
|
||||
MAINNET_CHAIN_SELECTOR="5009297550715157269"
|
||||
CHAIN138_CHAIN_SELECTOR="${CHAIN138_CHAIN_SELECTOR:-}" # To be determined
|
||||
|
||||
# Get deployed addresses
|
||||
WETH9_BRIDGE_MAINNET=$(grep "CCIPWETH9_BRIDGE_MAINNET=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "")
|
||||
WETH10_BRIDGE_MAINNET=$(grep "CCIPWETH10_BRIDGE_MAINNET=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "")
|
||||
WETH9_BRIDGE_CHAIN138=$(grep "CCIPWETH9_BRIDGE_CHAIN138=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "")
|
||||
WETH10_BRIDGE_CHAIN138=$(grep "CCIPWETH10_BRIDGE_CHAIN138=" "$PROJECT_ROOT/.env" 2>/dev/null | cut -d'=' -f2 | tr -d ' "' || echo "")
|
||||
# Contract Addresses (set these after deployment)
|
||||
WETH9_BRIDGE_138="${WETH9_BRIDGE_138:-}"
|
||||
WETH10_BRIDGE_138="${WETH10_BRIDGE_138:-}"
|
||||
WETH9_MAINNET="${WETH9_MAINNET:-0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2}"
|
||||
WETH10_MAINNET="${WETH10_MAINNET:-0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f}"
|
||||
|
||||
# Chain selectors
|
||||
ETH_SELECTOR="${ETH_MAINNET_SELECTOR:-0x500147}" # Ethereum Mainnet
|
||||
CHAIN138_SELECTOR="${CHAIN138_SELECTOR:-0x000000000000008a}" # Chain-138
|
||||
echo -e "${GREEN}=== Bridge Destination Configuration ===${NC}\n"
|
||||
|
||||
echo "Configuration:"
|
||||
echo " Ethereum Mainnet Selector: $ETH_SELECTOR"
|
||||
echo " Chain-138 Selector: $CHAIN138_SELECTOR"
|
||||
|
||||
if [ -z "$WETH9_BRIDGE_MAINNET" ] || [ -z "$WETH9_BRIDGE_CHAIN138" ]; then
|
||||
log_warn "⚠️ Bridge addresses not found in .env"
|
||||
echo "Please ensure bridges are deployed on both chains"
|
||||
# Check prerequisites
|
||||
if [ -z "$PRIVATE_KEY" ]; then
|
||||
echo -e "${RED}ERROR: PRIVATE_KEY environment variable not set${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Bridge Addresses:"
|
||||
echo " WETH9 Mainnet: $WETH9_BRIDGE_MAINNET"
|
||||
echo " WETH9 Chain-138: $WETH9_BRIDGE_CHAIN138"
|
||||
echo " WETH10 Mainnet: $WETH10_BRIDGE_MAINNET"
|
||||
echo " WETH10 Chain-138: $WETH10_BRIDGE_CHAIN138"
|
||||
if [ -z "$WETH9_BRIDGE_138" ] || [ -z "$WETH10_BRIDGE_138" ]; then
|
||||
echo -e "${YELLOW}WARNING: Bridge addresses not set. Please set WETH9_BRIDGE_138 and WETH10_BRIDGE_138${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Note: Bridge destination configuration requires:"
|
||||
echo " 1. Calling addDestination() on each bridge contract"
|
||||
echo " 2. Setting the corresponding bridge address on the destination chain"
|
||||
echo " 3. Enabling the destination"
|
||||
echo "This can be done via:"
|
||||
echo " • cast send (for Foundry)"
|
||||
echo " • Hardhat scripts"
|
||||
echo " • Direct contract interaction"
|
||||
log_warn "⚠️ Manual configuration required"
|
||||
# Function to add destination
|
||||
add_destination() {
|
||||
local bridge_address=$1
|
||||
local chain_selector=$2
|
||||
local destination_token=$3
|
||||
local rpc_url=$4
|
||||
local network_name=$5
|
||||
|
||||
echo -e "${GREEN}Adding destination to $network_name bridge...${NC}"
|
||||
|
||||
cast send "$bridge_address" \
|
||||
"addDestination(uint64,address,address)" \
|
||||
"$chain_selector" \
|
||||
"$destination_token" \
|
||||
"0x0000000000000000000000000000000000000000" \
|
||||
--rpc-url "$rpc_url" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy
|
||||
|
||||
echo -e "${GREEN}✓ Destination added${NC}\n"
|
||||
}
|
||||
|
||||
# Function to verify destinations
|
||||
verify_destinations() {
|
||||
local bridge_address=$1
|
||||
local rpc_url=$2
|
||||
local network_name=$3
|
||||
|
||||
echo -e "${GREEN}Verifying destinations on $network_name...${NC}"
|
||||
|
||||
local chains=$(cast call "$bridge_address" \
|
||||
"getDestinationChains()(uint64[])" \
|
||||
--rpc-url "$rpc_url")
|
||||
|
||||
echo -e "${GREEN}Destination chains: $chains${NC}\n"
|
||||
}
|
||||
|
||||
# Configure ChainID 138 → Mainnet
|
||||
echo -e "${YELLOW}=== Configuring ChainID 138 → Mainnet ===${NC}\n"
|
||||
|
||||
echo -e "${GREEN}1. Configuring WETH9 Bridge (ChainID 138 → Mainnet)${NC}"
|
||||
add_destination "$WETH9_BRIDGE_138" "$MAINNET_CHAIN_SELECTOR" "$WETH9_MAINNET" "$RPC_URL_138" "ChainID 138"
|
||||
|
||||
echo -e "${GREEN}2. Configuring WETH10 Bridge (ChainID 138 → Mainnet)${NC}"
|
||||
add_destination "$WETH10_BRIDGE_138" "$MAINNET_CHAIN_SELECTOR" "$WETH10_MAINNET" "$RPC_URL_138" "ChainID 138"
|
||||
|
||||
# Verify ChainID 138 bridges
|
||||
echo -e "${YELLOW}=== Verifying ChainID 138 Bridges ===${NC}\n"
|
||||
verify_destinations "$WETH9_BRIDGE_138" "$RPC_URL_138" "WETH9 Bridge"
|
||||
verify_destinations "$WETH10_BRIDGE_138" "$RPC_URL_138" "WETH10 Bridge"
|
||||
|
||||
# Note: Mainnet → ChainID 138 requires ChainID 138 selector
|
||||
if [ -z "$CHAIN138_CHAIN_SELECTOR" ]; then
|
||||
echo -e "${YELLOW}NOTE: ChainID 138 chain selector not set.${NC}"
|
||||
echo -e "${YELLOW}To configure Mainnet → ChainID 138, first determine the ChainID 138 selector.${NC}"
|
||||
echo -e "${YELLOW}You can find it using: cast call <CCIP_ROUTER> 'getChainSelector()(uint64)' --rpc-url $RPC_URL_138${NC}\n"
|
||||
else
|
||||
echo -e "${YELLOW}=== Configuring Mainnet → ChainID 138 ===${NC}\n"
|
||||
echo -e "${YELLOW}NOTE: This requires deploying bridges on Mainnet first.${NC}\n"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}=== Configuration Complete ===${NC}\n"
|
||||
echo -e "Next Steps:"
|
||||
echo -e " 1. Test bidirectional transfers"
|
||||
echo -e " 2. Monitor bridge activity"
|
||||
echo -e " 3. Verify LINK token balances for CCIP fees"
|
||||
|
||||
50
scripts/deployment/create-uniswap-v3-pool-cusdt-cusdc.sh
Executable file
50
scripts/deployment/create-uniswap-v3-pool-cusdt-cusdc.sh
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# Create a Uniswap V3 pool for cUSDT/cUSDC (or two token addresses) on a given chain.
|
||||
# Requires: cast (foundry), RPC for the chain, PRIVATE_KEY with gas.
|
||||
# Usage:
|
||||
# CUSDT=0x... CUSDC=0x... RPC_URL=$POLYGON_MAINNET_RPC ./scripts/deployment/create-uniswap-v3-pool-cusdt-cusdc.sh
|
||||
# Or: TOKEN_A=0x... TOKEN_B=0x... FEE=500 RPC_URL=... ./scripts/deployment/create-uniswap-v3-pool-cusdt-cusdc.sh
|
||||
# Fee: 500 = 0.05% (typical for stables), 3000 = 0.3%, 10000 = 1%.
|
||||
# Uniswap V3 factory (mainnet, Polygon, BSC, Base, Arbitrum, Optimism): 0x1F98431c8aD98523631AE4a59f267346ea31F984
|
||||
# See docs/deployment/CUSDT_CUSDC_MULTICHAIN_LIQUIDITY_RUNBOOK.md
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
DOTENV="$REPO_ROOT/.env"
|
||||
if [[ -f "$DOTENV" ]]; then set -a; source "$DOTENV"; set +a; fi
|
||||
|
||||
UNISWAP_V3_FACTORY="${UNISWAP_V3_FACTORY:-0x1F98431c8aD98523631AE4a59f267346ea31F984}"
|
||||
FEE="${FEE:-500}"
|
||||
TOKEN_A="${TOKEN_A:-${CUSDT_ADDRESS:-}}"
|
||||
TOKEN_B="${TOKEN_B:-${CUSDC_ADDRESS:-}}"
|
||||
if [[ -z "$TOKEN_A" ]] && [[ -n "${CUSDT_ADDRESS_137:-}" ]]; then
|
||||
TOKEN_A="${CUSDT_ADDRESS_137}"
|
||||
TOKEN_B="${CUSDC_ADDRESS_137}"
|
||||
fi
|
||||
if [[ -z "$TOKEN_A" ]]; then
|
||||
echo "Set TOKEN_A and TOKEN_B (or CUSDT_ADDRESS and CUSDC_ADDRESS, or CUSDT_ADDRESS_<chainId> and CUSDC_ADDRESS_<chainId>)"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "$TOKEN_B" ]]; then
|
||||
echo "Set TOKEN_B (or CUSDC_ADDRESS)"
|
||||
exit 1
|
||||
fi
|
||||
RPC_URL="${RPC_URL:-${POLYGON_MAINNET_RPC:-${ETHEREUM_MAINNET_RPC:-}}}"
|
||||
if [[ -z "$RPC_URL" ]]; then
|
||||
echo "Set RPC_URL (or POLYGON_MAINNET_RPC / ETHEREUM_MAINNET_RPC)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Creating Uniswap V3 pool: tokenA=$TOKEN_A tokenB=$TOKEN_B fee=$FEE"
|
||||
echo "Factory=$UNISWAP_V3_FACTORY RPC=$RPC_URL"
|
||||
POOL=$(cast call "$UNISWAP_V3_FACTORY" "getPool(address,address,uint24)(address)" "$TOKEN_A" "$TOKEN_B" "$FEE" --rpc-url "$RPC_URL" 2>/dev/null || true)
|
||||
if [[ -n "$POOL" ]] && [[ "$POOL" != "0x0000000000000000000000000000000000000000" ]]; then
|
||||
echo "Pool already exists: $POOL"
|
||||
exit 0
|
||||
fi
|
||||
cast send "$UNISWAP_V3_FACTORY" "createPool(address,address,uint24)" "$TOKEN_A" "$TOKEN_B" "$FEE" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "${PRIVATE_KEY:?PRIVATE_KEY required}"
|
||||
POOL=$(cast call "$UNISWAP_V3_FACTORY" "getPool(address,address,uint24)(address)" "$TOKEN_A" "$TOKEN_B" "$FEE" --rpc-url "$RPC_URL")
|
||||
echo "Pool created: $POOL"
|
||||
echo "Next: initialize the pool with sqrtPriceX96 and add liquidity via Uniswap UI or NonfungiblePositionManager."
|
||||
@@ -8,7 +8,8 @@ cd "$PROJECT_ROOT"
|
||||
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
RPC_URL="${RPC_URL:-http://localhost:8545}"
|
||||
RPC_URL="${RPC_URL_138:-http://localhost:8545}"
|
||||
GAS_PRICE="${GAS_PRICE:-1000000000}"
|
||||
PRIVATE_KEY="${PRIVATE_KEY:-}"
|
||||
|
||||
if [ -z "$PRIVATE_KEY" ]; then
|
||||
@@ -41,6 +42,7 @@ forge script script/DeployMulticall.s.sol:DeployMulticall \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--broadcast \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--with-gas-price "$GAS_PRICE" \
|
||||
--legacy -vvv 2>&1 | tail -30
|
||||
|
||||
# Phase 3: Oracle Contracts
|
||||
@@ -51,6 +53,7 @@ forge script script/DeployOracle.s.sol:DeployOracle \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--broadcast \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--with-gas-price "$GAS_PRICE" \
|
||||
--legacy -vvv 2>&1 | tail -30
|
||||
|
||||
# Phase 4: Governance Contracts
|
||||
@@ -61,6 +64,7 @@ forge script script/DeployMultiSig.s.sol:DeployMultiSig \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--broadcast \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--with-gas-price "$GAS_PRICE" \
|
||||
--legacy -vvv 2>&1 | tail -30
|
||||
|
||||
echo ""
|
||||
|
||||
@@ -31,11 +31,13 @@ else
|
||||
fi
|
||||
|
||||
# Configuration
|
||||
# Use public RPC for broadcasting (Infura doesn't support private key transactions)
|
||||
MAINNET_RPC="${MAINNET_RPC_URL:-https://eth.llamarpc.com}"
|
||||
if [[ "$ETHEREUM_MAINNET_RPC" == *"infura.io"* ]]; then
|
||||
log_warn "Note: Infura RPC doesn't support private key transactions, using public RPC"
|
||||
MAINNET_RPC="https://eth.llamarpc.com"
|
||||
# Use ETHEREUM_MAINNET_RPC; when Infura + INFURA_PROJECT_SECRET set, use Basic Auth URL for private key transactions
|
||||
MAINNET_RPC="${MAINNET_RPC_URL:-${ETHEREUM_MAINNET_RPC:-https://eth.llamarpc.com}}"
|
||||
if [[ "$MAINNET_RPC" == *"infura.io"* ]] && [[ -n "${INFURA_PROJECT_SECRET:-}" ]] && [[ ! "${INFURA_PROJECT_SECRET}" =~ \$\{ ]]; then
|
||||
# Build Infura URL with Basic Auth so cast/forge can send transactions
|
||||
[[ -f "$SCRIPT_DIR/../lib/infura.sh" ]] && source "$SCRIPT_DIR/../lib/infura.sh"
|
||||
_with_auth=$(build_infura_rpc "mainnet" 2>/dev/null || true)
|
||||
[[ -n "$_with_auth" ]] && MAINNET_RPC="$_with_auth" && log_info "Using Infura Mainnet RPC with Basic Auth"
|
||||
fi
|
||||
MAINNET_PRIVATE_KEY="${PRIVATE_KEY}"
|
||||
MAINNET_CCIP_ROUTER="${MAINNET_CCIP_ROUTER:-0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D}" # Official Chainlink CCIP Router
|
||||
|
||||
157
scripts/deployment/deploy-all-mainnets-with-mapper-oracle-pmm.sh
Executable file
157
scripts/deployment/deploy-all-mainnets-with-mapper-oracle-pmm.sh
Executable file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy to all mainnets: CCIP Bridge, Trustless Bridge, Oracle, Mapper, PMM (anchored to ChainID 138).
|
||||
# Run after check-balances-gas-and-deploy.sh. Requires .env with PRIVATE_KEY and per-chain RPC/CCIP vars.
|
||||
# Usage: bash scripts/deployment/deploy-all-mainnets-with-mapper-oracle-pmm.sh [phase]
|
||||
# phase: ccip | trustless | oracle | mapper | pmm | all (default: all)
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Load .env without strict unset (avoid init.sh pipefail on .env)
|
||||
set +u
|
||||
[ -f .env ] && source .env
|
||||
set -u
|
||||
[ -f "$SCRIPT_DIR/../lib/infura.sh" ] && source "$SCRIPT_DIR/../lib/infura.sh"
|
||||
|
||||
PHASE="${1:-all}"
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
require_env() {
|
||||
local var="$1"
|
||||
if [ -z "${!var:-}" ]; then
|
||||
echo -e "${RED}ERROR: $var not set in .env${NC}" >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
ensure_rpc() {
|
||||
local rpc="$1"
|
||||
type ensure_infura_rpc_url &>/dev/null && [ -n "$rpc" ] && rpc=$(ensure_infura_rpc_url "$rpc")
|
||||
echo "$rpc"
|
||||
}
|
||||
|
||||
# --- CCIP: DeployAll to BSC, Polygon, Base, Optimism, Gnosis ---
|
||||
run_ccip_remaining_mainnets() {
|
||||
echo -e "${YELLOW}=== CCIP Bridges (DeployAll) to BSC, Polygon, Base, Optimism, Gnosis ===${NC}"
|
||||
require_env PRIVATE_KEY || return 1
|
||||
local chains="BSC:56:BSC_RPC_URL POLYGON:137:POLYGON_MAINNET_RPC BASE:8453:BASE_MAINNET_RPC OPTIMISM:10:OPTIMISM_MAINNET_RPC GNOSIS:100:GNOSIS_MAINNET_RPC"
|
||||
for entry in $chains; do
|
||||
local name="${entry%%:*}"; entry="${entry#*:}"
|
||||
local chain_id="${entry%%:*}"; entry="${entry#*:}"
|
||||
local rpc_var="$entry"
|
||||
local rpc="${!rpc_var:-}"
|
||||
rpc=$(ensure_rpc "$rpc")
|
||||
if [ -z "$rpc" ]; then
|
||||
echo " Skip $name (no RPC)"
|
||||
continue
|
||||
fi
|
||||
echo -e "${YELLOW}DeployAll to $name (chain $chain_id)...${NC}"
|
||||
forge script script/DeployAll.s.sol:DeployAll \
|
||||
--rpc-url "$rpc" --chain-id "$chain_id" --private-key "$PRIVATE_KEY" \
|
||||
--broadcast --slow -vvv || echo -e "${RED}$name DeployAll failed${NC}"
|
||||
echo ""
|
||||
done
|
||||
echo -e "${GREEN}CCIP phase done.${NC}"
|
||||
}
|
||||
|
||||
# --- Trustless Bridge: Chain 138 (Lockbox) + Ethereum (BondManager, etc.) ---
|
||||
run_trustless() {
|
||||
echo -e "${YELLOW}=== Trustless Bridge (Chain 138 + Ethereum) ===${NC}"
|
||||
require_env PRIVATE_KEY RPC_URL_138 || return 1
|
||||
echo "Deploying Trustless (Lockbox) on Chain 138..."
|
||||
forge script script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge \
|
||||
--rpc-url "$RPC_URL_138" --broadcast --via-ir --private-key "$PRIVATE_KEY" -vvv || true
|
||||
require_env ETHEREUM_MAINNET_RPC || return 1
|
||||
MAINNET_RPC=$(ensure_rpc "$ETHEREUM_MAINNET_RPC")
|
||||
echo "Deploying Trustless (BondManager, ChallengeManager, LP, Inbox, SwapRouter, Coordinator) on Ethereum..."
|
||||
forge script script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge \
|
||||
--rpc-url "$MAINNET_RPC" --broadcast --via-ir --private-key "$PRIVATE_KEY" \
|
||||
${ETHERSCAN_API_KEY:+--verify --etherscan-api-key "$ETHERSCAN_API_KEY"} -vvv || true
|
||||
echo -e "${GREEN}Trustless phase done.${NC}"
|
||||
}
|
||||
|
||||
# --- Oracle: Chain 138 ---
|
||||
run_oracle() {
|
||||
echo -e "${YELLOW}=== Oracle (Chain 138) ===${NC}"
|
||||
require_env PRIVATE_KEY RPC_URL_138 || return 1
|
||||
forge script script/DeployOracle.s.sol:DeployOracle \
|
||||
--rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" \
|
||||
--with-gas-price "${GAS_PRICE_138:-1000000000}" --legacy -vvv || true
|
||||
echo -e "${GREEN}Oracle phase done.${NC}"
|
||||
}
|
||||
|
||||
# --- Mapper: Chain 138 (full) + others (empty) ---
|
||||
run_mapper() {
|
||||
echo -e "${YELLOW}=== Mapper (Chain 138 = AddressMapper; others = AddressMapperEmpty) ===${NC}"
|
||||
require_env PRIVATE_KEY || return 1
|
||||
if [ -n "${RPC_URL_138:-}" ]; then
|
||||
echo "Deploying AddressMapper on Chain 138..."
|
||||
forge script script/DeployAddressMapper.s.sol:DeployAddressMapper \
|
||||
--rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" \
|
||||
--with-gas-price "${GAS_PRICE_138:-1000000000}" --legacy -vvv || true
|
||||
fi
|
||||
local chains="ETHEREUM_MAINNET_RPC:1 BSC_RPC_URL:56 POLYGON_MAINNET_RPC:137 BASE_MAINNET_RPC:8453 ARBITRUM_MAINNET_RPC:42161 OPTIMISM_MAINNET_RPC:10 AVALANCHE_RPC_URL:43114 CRONOS_RPC_URL:25 GNOSIS_MAINNET_RPC:100"
|
||||
for entry in $chains; do
|
||||
local rpc_var="${entry%%:*}"; local chain_id="${entry#*:}"
|
||||
local rpc="${!rpc_var:-}"
|
||||
[ -z "$rpc" ] && continue
|
||||
rpc=$(ensure_rpc "$rpc")
|
||||
echo "Deploying AddressMapperEmpty on chain $chain_id..."
|
||||
forge script script/DeployAddressMapperOtherChain.s.sol:DeployAddressMapperOtherChain \
|
||||
--rpc-url "$rpc" --chain-id "$chain_id" --broadcast --private-key "$PRIVATE_KEY" -vvv || true
|
||||
done
|
||||
echo -e "${GREEN}Mapper phase done.${NC}"
|
||||
}
|
||||
|
||||
# --- PMM (DODO) on Chain 138 ---
|
||||
run_pmm() {
|
||||
echo -e "${YELLOW}=== PMM Liquidity Pools (Chain 138) ===${NC}"
|
||||
require_env PRIVATE_KEY RPC_URL_138 || return 1
|
||||
if [ -z "${DODO_PMM_INTEGRATION:-}" ] && [ -n "${DODO_VENDING_MACHINE_ADDRESS:-}" ]; then
|
||||
echo "Deploying DODOPMMIntegration on Chain 138..."
|
||||
forge script script/dex/DeployDODOPMMIntegration.s.sol:DeployDODOPMMIntegration \
|
||||
--rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" \
|
||||
--with-gas-price "${GAS_PRICE_138:-1000000000}" --legacy -vvv || true
|
||||
else
|
||||
echo " DODOPMMIntegration already set or DODO_VENDING_MACHINE_ADDRESS not set; skip deploy."
|
||||
fi
|
||||
if [ -n "${DODO_PMM_INTEGRATION:-}" ] && [ -n "${XAU_ADDRESS:-}" ]; then
|
||||
echo "Creating XAU-anchored pools..."
|
||||
forge script script/dex/DeployPrivatePoolRegistryAndPools.s.sol:DeployPrivatePoolRegistryAndPools \
|
||||
--rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" \
|
||||
--with-gas-price "${GAS_PRICE_138:-1000000000}" --legacy -vvv || true
|
||||
fi
|
||||
echo -e "${GREEN}PMM phase done.${NC}"
|
||||
}
|
||||
|
||||
# --- Main ---
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}All Mainnets: CCIP, Trustless, Oracle, Mapper, PMM${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo "Phase: $PHASE"
|
||||
echo ""
|
||||
|
||||
case "$PHASE" in
|
||||
ccip) run_ccip_remaining_mainnets ;;
|
||||
trustless) run_trustless ;;
|
||||
oracle) run_oracle ;;
|
||||
mapper) run_mapper ;;
|
||||
pmm) run_pmm ;;
|
||||
all)
|
||||
run_ccip_remaining_mainnets
|
||||
run_trustless
|
||||
run_oracle
|
||||
run_mapper
|
||||
run_pmm
|
||||
;;
|
||||
*) echo "Usage: $0 [ccip|trustless|oracle|mapper|pmm|all]"; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Done. Update .env and config/smart-contracts-master.json with any new addresses.${NC}"
|
||||
@@ -1,135 +1,115 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# Phased deployment for Chain 138: run each phase in order.
|
||||
# Break-up of "deploy all" into discrete steps; skip phases that are already deployed (env set).
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/deployment/deploy-all-phases.sh # run all phases (skip when env indicates done)
|
||||
# ./scripts/deployment/deploy-all-phases.sh --all # run every phase (no skip)
|
||||
# ./scripts/deployment/deploy-all-phases.sh --phase 5 # run only phase 5
|
||||
# ./scripts/deployment/deploy-all-phases.sh --dry-run # print what would run
|
||||
#
|
||||
# Requires: .env with PRIVATE_KEY, RPC_URL_138 (Chain 138 Core). Uses --with-gas-price 1000000000 for Chain 138.
|
||||
|
||||
# Deploy All Phases
|
||||
# This script orchestrates the complete deployment process
|
||||
|
||||
set -e
|
||||
|
||||
echo "=========================================="
|
||||
echo " Trustless Bridge Complete Deployment"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Load environment variables
|
||||
if [ -f .env ]; then
|
||||
export $(cat .env | grep -v '^#' | grep -v '^$' | xargs)
|
||||
else
|
||||
echo "Error: .env file not found"
|
||||
echo "Please run phase1-env-setup.sh first"
|
||||
exit 1
|
||||
fi
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
echo "This will deploy all phases of the trustless bridge system."
|
||||
echo ""
|
||||
read -p "Continue? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Deployment cancelled"
|
||||
exit 1
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Starting deployment..."
|
||||
echo ""
|
||||
RPC="${RPC_URL_138:-http://192.168.11.211:8545}"
|
||||
GAS_PRICE="${GAS_PRICE_138:-1000000000}"
|
||||
DRY_RUN=""
|
||||
RUN_ALL="" # if set, do not skip any phase
|
||||
PHASE_ONLY="" # if set, run only this phase number (e.g. 5)
|
||||
|
||||
# Phase 1: Environment Setup
|
||||
echo ">>> Phase 1: Environment Setup"
|
||||
"$SCRIPT_DIR/phase1-env-setup.sh" || exit 1
|
||||
echo ""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=1 ;;
|
||||
--all) RUN_ALL=1 ;;
|
||||
--phase)
|
||||
shift
|
||||
[ $# -gt 0 ] && PHASE_ONLY="$1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Phase 2: Deploy Core Contracts
|
||||
echo ">>> Phase 2: Deploy Core Bridge Contracts"
|
||||
read -p "Deploy core contracts? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
"$SCRIPT_DIR/phase2-deploy-core.sh" || exit 1
|
||||
echo ""
|
||||
read -p "Press Enter after updating .env with contract addresses..."
|
||||
if [ -z "${PRIVATE_KEY:-}" ]; then
|
||||
echo "ERROR: PRIVATE_KEY not set in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run_phase() {
|
||||
local num="$1"
|
||||
local name="$2"
|
||||
local skip_var="$3" # optional: if set in env, skip (unless --all)
|
||||
local cmd="$4"
|
||||
if [ -n "$PHASE_ONLY" ] && [ "$PHASE_ONLY" != "$num" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ -n "$skip_var" ] && [ -z "$RUN_ALL" ]; then
|
||||
local val=""
|
||||
eval "val=\"\${${skip_var}:-}\""
|
||||
if [ -n "$val" ]; then
|
||||
echo "[Phase $num] $name — SKIP (${skip_var} already set)"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
echo "[Phase $num] $name — RUNNING"
|
||||
if [ -n "$DRY_RUN" ]; then
|
||||
echo " would run: $(echo "$cmd" | sed 's/--private-key "[^"]*"/--private-key ***REDACTED***/g')"
|
||||
return 0
|
||||
fi
|
||||
eval "$cmd" || { echo "Phase $num failed."; exit 1; }
|
||||
echo "[Phase $num] $name — DONE"
|
||||
}
|
||||
|
||||
echo "============================================"
|
||||
echo "Chain 138 — Phased deployment"
|
||||
echo "RPC: $RPC"
|
||||
echo "Gas price: $GAS_PRICE wei"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
# Phase 3: Deploy Enhanced Router
|
||||
echo ">>> Phase 3: Deploy EnhancedSwapRouter"
|
||||
read -p "Deploy EnhancedSwapRouter? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
"$SCRIPT_DIR/phase3-deploy-router.sh" || exit 1
|
||||
echo ""
|
||||
read -p "Press Enter after updating .env with ENHANCED_SWAP_ROUTER address..."
|
||||
fi
|
||||
echo ""
|
||||
# Phase 1: Phased core (registry + governance)
|
||||
run_phase 1 "Phased core (01_DeployCore)" "UNIVERSAL_ASSET_REGISTRY" \
|
||||
"forge script script/deploy/01_DeployCore.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 4: Deploy Integration Contracts
|
||||
echo ">>> Phase 4: Deploy Integration Contracts"
|
||||
read -p "Deploy integration contracts? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
"$SCRIPT_DIR/phase4-deploy-integration.sh" || exit 1
|
||||
echo ""
|
||||
read -p "Press Enter after updating .env with integration contract addresses..."
|
||||
fi
|
||||
echo ""
|
||||
# Phase 2: Phased bridges (CCIP bridge + orchestrator)
|
||||
run_phase 2 "Phased bridges (02_DeployBridges)" "UNIVERSAL_CCIP_BRIDGE" \
|
||||
"forge script script/deploy/02_DeployBridges.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 5: Initialize System
|
||||
echo ">>> Phase 5: Initialize System"
|
||||
read -p "Initialize system? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
"$SCRIPT_DIR/phase5-initialize.sh" || exit 1
|
||||
fi
|
||||
echo ""
|
||||
# Phase 3: Channel managers
|
||||
run_phase 3 "PaymentChannelManager" "PAYMENT_CHANNEL_MANAGER" \
|
||||
"forge script script/DeployPaymentChannelManager.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 6: Provide Liquidity
|
||||
echo ">>> Phase 6: Provide Initial Liquidity"
|
||||
read -p "Provide initial liquidity? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
"$SCRIPT_DIR/phase6-provide-liquidity.sh" || exit 1
|
||||
fi
|
||||
echo ""
|
||||
run_phase 3 "GenericStateChannelManager" "GENERIC_STATE_CHANNEL_MANAGER" \
|
||||
"forge script script/DeployGenericStateChannelManager.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 7: Configure
|
||||
echo ">>> Phase 7: Configure Access Control and Routing"
|
||||
read -p "Configure access control and routing? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
"$SCRIPT_DIR/phase7-configure.sh" || exit 1
|
||||
fi
|
||||
echo ""
|
||||
# Phase 4: Deterministic core (CREATE2)
|
||||
run_phase 4 "Deterministic core (DeployDeterministicCore)" "CREATE2_FACTORY" \
|
||||
"forge script script/deploy/DeployDeterministicCore.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 8: Deploy Services
|
||||
echo ">>> Phase 8: Deploy Backend Services"
|
||||
read -p "Deploy backend services? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
"$SCRIPT_DIR/phase8-deploy-services.sh" || exit 1
|
||||
fi
|
||||
echo ""
|
||||
# Phase 5: Vault system
|
||||
run_phase 5 "Vault system (DeployVaultSystem)" "VAULT_FACTORY" \
|
||||
"forge script script/deploy/vault/DeployVaultSystem.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 9: Deploy Frontend
|
||||
echo ">>> Phase 9: Deploy Frontend Applications"
|
||||
read -p "Build frontend applications? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
"$SCRIPT_DIR/phase9-deploy-frontend.sh" || exit 1
|
||||
fi
|
||||
echo ""
|
||||
# Phase 6: Reserve system (requires TOKEN_FACTORY in .env)
|
||||
run_phase 6 "Reserve system (DeployReserveSystem)" "RESERVE_SYSTEM" \
|
||||
"forge script script/reserve/DeployReserveSystem.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 10: Verify
|
||||
echo ">>> Phase 10: Verification"
|
||||
"$SCRIPT_DIR/phase10-verify.sh" || exit 1
|
||||
# Phase 7: Trustless bridge (Lockbox138 on Chain 138)
|
||||
run_phase 7 "Trustless bridge (Lockbox138)" "LOCKBOX_138" \
|
||||
"forge script script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " Deployment Complete!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Review deployment status"
|
||||
echo "2. Set up monitoring dashboards"
|
||||
echo "3. Configure alerts"
|
||||
echo "4. Train operations team"
|
||||
echo "5. Begin bridge operations"
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Phased deployment finished."
|
||||
echo "Update .env with any new addresses and run setCCIPRouter on deterministic bridge if Phase 4 ran."
|
||||
echo "============================================"
|
||||
|
||||
104
scripts/deployment/deploy-bridges-config-ready-chains.sh
Executable file
104
scripts/deployment/deploy-bridges-config-ready-chains.sh
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy CCIP WETH9/WETH10 bridges on Gnosis, Cronos, Celo, Wemix (config-ready chains).
|
||||
# Requires: PRIVATE_KEY in .env; per-chain RPC and gas (xDAI, CRO, CELO, WEMIX).
|
||||
# Set CCIP_ROUTER_<CHAIN>, LINK_TOKEN_<CHAIN>; set WETH9_<CHAIN> and WETH10_<CHAIN> (native wrapped token on each chain, or deployment will fail).
|
||||
# See docs/deployment/ENV_CONFIG_READY_CHAINS.example and docs/07-ccip/CONFIG_READY_CHAINS_COMPLETION_RUNBOOK.md.
|
||||
#
|
||||
# Usage: cd smom-dbis-138 && ./scripts/deployment/deploy-bridges-config-ready-chains.sh [gnosis|cronos|celo|wemix|all]
|
||||
# PREFLIGHT=1 ... # run preflight first (default: 1)
|
||||
# DRY_RUN=1 ... # print forge commands only, no deploy
|
||||
# SIMULATE=1 ... # run forge without --broadcast (test script, no on-chain tx)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
[[ -f "$PROJECT_ROOT/.env" ]] && set -a && source "$PROJECT_ROOT/.env" && set +a
|
||||
|
||||
DRY_RUN="${DRY_RUN:-0}"
|
||||
SIMULATE="${SIMULATE:-0}"
|
||||
PREFLIGHT="${PREFLIGHT:-1}"
|
||||
CHAIN="${1:-all}"
|
||||
|
||||
# Per-chain env for DeployWETHBridges: RPC_URL, CCIP_ROUTER_ADDRESS, LINK_TOKEN_ADDRESS, WETH9_ADDRESS, WETH10_ADDRESS (0x0 to skip)
|
||||
run_deploy() {
|
||||
local chain_name="$1"
|
||||
local rpc_var="$2"
|
||||
local router_var="$3"
|
||||
local link_var="$4"
|
||||
local weth9_var="$5"
|
||||
local weth10_var="$6"
|
||||
local rpc="${!rpc_var:-}"
|
||||
local router="${!router_var:-}"
|
||||
local link="${!link_var:-}"
|
||||
local weth9="${!weth9_var:-}"
|
||||
local weth10="${!weth10_var:-}"
|
||||
|
||||
if [[ -z "$rpc" || -z "$router" ]]; then
|
||||
echo " Skip $chain_name: set ${rpc_var} and ${router_var} in .env"
|
||||
return 0
|
||||
fi
|
||||
if [[ -z "${PRIVATE_KEY:-}" ]]; then
|
||||
echo " Skip $chain_name: PRIVATE_KEY not set"
|
||||
return 0
|
||||
fi
|
||||
if [[ -z "$weth9" || -z "$weth10" ]]; then
|
||||
echo " Skip $chain_name: set ${weth9_var} and ${weth10_var} in .env (native wrapped token addresses from chain)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
export RPC_URL="$rpc"
|
||||
export CCIP_ROUTER_ADDRESS="$router"
|
||||
export LINK_TOKEN_ADDRESS="${link:-0x0000000000000000000000000000000000000000}"
|
||||
export WETH9_ADDRESS="$weth9"
|
||||
export WETH10_ADDRESS="$weth10"
|
||||
|
||||
local broadcast="--broadcast"
|
||||
[[ "$SIMULATE" == "1" ]] && broadcast=""
|
||||
local cmd="forge script script/deploy/bridge/DeployWETHBridges.s.sol:DeployWETHBridges --rpc-url \"$RPC_URL\" $broadcast --legacy -vvvv"
|
||||
if [[ "$DRY_RUN" == "1" ]]; then
|
||||
echo " [DRY RUN] $chain_name: $cmd"
|
||||
return 0
|
||||
fi
|
||||
if [[ "$SIMULATE" == "1" ]]; then
|
||||
echo " Simulating deploy on $chain_name (no broadcast)..."
|
||||
else
|
||||
echo " Deploying bridges on $chain_name..."
|
||||
fi
|
||||
eval "$cmd" || { echo " Failed (non-fatal)"; return 0; }
|
||||
echo " Set CCIPWETH9_BRIDGE_${chain_name^^} and CCIPWETH10_BRIDGE_${chain_name^^} in .env from script output."
|
||||
}
|
||||
|
||||
# Preflight (RPC + gas balance check)
|
||||
if [[ "$PREFLIGHT" == "1" && "$DRY_RUN" != "1" ]]; then
|
||||
if ! "$SCRIPT_DIR/preflight-config-ready-chains.sh" "$CHAIN" 2>/dev/null; then
|
||||
echo ""
|
||||
echo "Preflight failed. Fix RPCs and gas balances, or run with PREFLIGHT=0 to skip."
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "=== Deploy CCIP bridges (Gnosis, Cronos, Celo, Wemix) ==="
|
||||
echo " DRY_RUN=$DRY_RUN SIMULATE=$SIMULATE PREFLIGHT=$PREFLIGHT CHAIN=$CHAIN"
|
||||
echo " Gas tokens: Gnosis=xDAI, Cronos=CRO, Celo=CELO, Wemix=WEMIX"
|
||||
echo ""
|
||||
|
||||
case "$CHAIN" in
|
||||
gnosis) run_deploy "GNOSIS" "GNOSIS_RPC" "CCIP_ROUTER_GNOSIS" "LINK_TOKEN_GNOSIS" "WETH9_GNOSIS" "WETH10_GNOSIS" ;;
|
||||
cronos) run_deploy "CRONOS" "CRONOS_RPC" "CCIP_ROUTER_CRONOS" "LINK_TOKEN_CRONOS" "WETH9_CRONOS" "WETH10_CRONOS" ;;
|
||||
celo) run_deploy "CELO" "CELO_RPC" "CCIP_ROUTER_CELO" "LINK_TOKEN_CELO" "WETH9_CELO" "WETH10_CELO" ;;
|
||||
wemix) run_deploy "WEMIX" "WEMIX_RPC" "CCIP_ROUTER_WEMIX" "LINK_TOKEN_WEMIX" "WETH9_WEMIX" "WETH10_WEMIX" ;;
|
||||
all)
|
||||
run_deploy "GNOSIS" "GNOSIS_RPC" "CCIP_ROUTER_GNOSIS" "LINK_TOKEN_GNOSIS" "WETH9_GNOSIS" "WETH10_GNOSIS"
|
||||
run_deploy "CRONOS" "CRONOS_RPC" "CCIP_ROUTER_CRONOS" "LINK_TOKEN_CRONOS" "WETH9_CRONOS" "WETH10_CRONOS"
|
||||
run_deploy "CELO" "CELO_RPC" "CCIP_ROUTER_CELO" "LINK_TOKEN_CELO" "WETH9_CELO" "WETH10_CELO"
|
||||
run_deploy "WEMIX" "WEMIX_RPC" "CCIP_ROUTER_WEMIX" "LINK_TOKEN_WEMIX" "WETH9_WEMIX" "WETH10_WEMIX"
|
||||
;;
|
||||
*) echo "Usage: $0 [gnosis|cronos|celo|wemix|all]"; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "Next: Add deployed bridge addresses to .env (CCIPWETH9_BRIDGE_*, CCIPWETH10_BRIDGE_*), then run complete-config-ready-chains.sh"
|
||||
41
scripts/deployment/deploy-ccip-logger-all-chains.sh
Executable file
41
scripts/deployment/deploy-ccip-logger-all-chains.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy CCIPLogger to all configured chains (mainnet, BSC, Polygon, Gnosis, Cronos) via Hardhat.
|
||||
# Requires: from smom-dbis-138 run `pnpm install` or `npm install` so Hardhat resolves locally; .env with PRIVATE_KEY and per-chain RPC.
|
||||
# Usage: cd smom-dbis-138 && ./scripts/deployment/deploy-ccip-logger-all-chains.sh
|
||||
# CHAINS="mainnet bsc" ./scripts/deployment/deploy-ccip-logger-all-chains.sh # only mainnet and bsc
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if [[ -f .env ]]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
CHAINS="${CHAINS:-mainnet bsc polygon gnosis cronos}"
|
||||
|
||||
if ! command -v npx &>/dev/null; then
|
||||
echo "npx not found. Install Node/npm and run: npm install" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Deploying CCIPLogger to: $CHAINS"
|
||||
for net in $CHAINS; do
|
||||
echo ""
|
||||
echo "=== $net ==="
|
||||
case "$net" in
|
||||
mainnet) npm run deploy:logger:mainnet 2>&1 || echo " Failed (non-fatal)" ;;
|
||||
bsc) NETWORK=bsc npx hardhat run scripts/ccip-deployment/deploy-ccip-logger-multichain.js --network bsc 2>&1 || echo " Failed (non-fatal)" ;;
|
||||
polygon) npm run deploy:logger:polygon 2>&1 || echo " Failed (non-fatal)" ;;
|
||||
gnosis) npm run deploy:logger:gnosis 2>&1 || echo " Failed (non-fatal)" ;;
|
||||
cronos) npm run deploy:logger:cronos 2>&1 || echo " Failed (non-fatal)" ;;
|
||||
*) echo " Unknown network: $net" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Done. Update .env with CCIP_LOGGER_* addresses per chain if deployed."
|
||||
@@ -87,8 +87,8 @@ fi
|
||||
|
||||
# Verify RPC endpoint
|
||||
log_info "Verifying RPC endpoint..."
|
||||
if ! curl -s -X POST "$RPC_URL" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' > /dev/null 2>&1; then
|
||||
log_error "Error: RPC endpoint is not accessible"
|
||||
if ! curl -s -m 10 -X POST "$RPC_URL" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' > /dev/null 2>&1; then
|
||||
log_error "Error: RPC endpoint is not accessible at $RPC_URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
84
scripts/deployment/deploy-cusdt-cusdc-all-chains.sh
Executable file
84
scripts/deployment/deploy-cusdt-cusdc-all-chains.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy CompliantUSDT and CompliantUSDC to each target chain (Ethereum, BSC, Polygon, Base, etc.).
|
||||
# Uses smom-dbis-138/.env. Requires per-chain RPC and PRIVATE_KEY with gas on each chain.
|
||||
# Output: suggested .env lines for CUSDT_ADDRESS_<chainId> and CUSDC_ADDRESS_<chainId>.
|
||||
# See docs/deployment/CUSDT_CUSDC_MULTICHAIN_LIQUIDITY_RUNBOOK.md
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
DOTENV="$REPO_ROOT/.env"
|
||||
cd "$REPO_ROOT"
|
||||
if [[ -f "$DOTENV" ]]; then set -a; source "$DOTENV"; set +a; fi
|
||||
|
||||
# Chain name : chain_id : RPC env var name
|
||||
CHAINS=(
|
||||
"ETHEREUM:1:ETHEREUM_MAINNET_RPC"
|
||||
"BSC:56:BSC_RPC_URL"
|
||||
"POLYGON:137:POLYGON_MAINNET_RPC"
|
||||
"BASE:8453:BASE_MAINNET_RPC"
|
||||
"OPTIMISM:10:OPTIMISM_MAINNET_RPC"
|
||||
"ARBITRUM:42161:ARBITRUM_MAINNET_RPC"
|
||||
"AVALANCHE:43114:AVALANCHE_RPC_URL"
|
||||
"CRONOS:25:CRONOS_RPC_URL"
|
||||
"GNOSIS:100:GNOSIS_MAINNET_RPC"
|
||||
"CELO:42220:CELO_MAINNET_RPC"
|
||||
"WEMIX:1111:WEMIX_MAINNET_RPC"
|
||||
)
|
||||
|
||||
FILTER="${DEPLOY_CUSDT_CUSDC_FILTER:-}"
|
||||
DRY_RUN="${DEPLOY_CUSDT_CUSDC_DRY_RUN:-}"
|
||||
|
||||
for entry in "${CHAINS[@]}"; do
|
||||
IFS=: read -r name chain_id rpc_var <<< "$entry"
|
||||
if [[ -n "$FILTER" ]] && [[ " $FILTER " != *" $name "* ]]; then continue; fi
|
||||
|
||||
rpc="${!rpc_var:-}"
|
||||
if [[ -z "$rpc" ]]; then
|
||||
echo "Skip $name (chain $chain_id): $rpc_var not set"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "=== $name (chain $chain_id) ==="
|
||||
if [[ -n "$DRY_RUN" ]]; then
|
||||
echo "[DRY RUN] Would deploy CompliantUSDT and CompliantUSDC on $name via $rpc_var"
|
||||
continue
|
||||
fi
|
||||
|
||||
CUSDT=""
|
||||
CUSDC=""
|
||||
log_usdt="/tmp/cusdt-deploy-$chain_id.log"
|
||||
log_usdc="/tmp/cusdc-deploy-$chain_id.log"
|
||||
|
||||
if forge script script/DeployCompliantUSDT.s.sol:DeployCompliantUSDT \
|
||||
--rpc-url "$rpc" \
|
||||
--chain-id "$chain_id" \
|
||||
--broadcast \
|
||||
--private-key "${PRIVATE_KEY:?PRIVATE_KEY required}" \
|
||||
-vv 2>&1 | tee "$log_usdt"; then
|
||||
CUSDT=$(grep -oE "CompliantUSDT deployed at: 0x[a-fA-F0-9]{40}" "$log_usdt" | tail -1 | awk '{print $NF}')
|
||||
fi
|
||||
if [[ -z "$CUSDT" ]]; then
|
||||
echo "Warning: CompliantUSDT deploy failed or address not found on $name"
|
||||
else
|
||||
echo "CUSDT_ADDRESS_${chain_id}=$CUSDT"
|
||||
fi
|
||||
|
||||
if forge script script/DeployCompliantUSDC.s.sol:DeployCompliantUSDC \
|
||||
--rpc-url "$rpc" \
|
||||
--chain-id "$chain_id" \
|
||||
--broadcast \
|
||||
--private-key "${PRIVATE_KEY:?PRIVATE_KEY required}" \
|
||||
-vv 2>&1 | tee "$log_usdc"; then
|
||||
CUSDC=$(grep -oE "CompliantUSDC deployed at: 0x[a-fA-F0-9]{40}" "$log_usdc" | tail -1 | awk '{print $NF}')
|
||||
fi
|
||||
if [[ -z "$CUSDC" ]]; then
|
||||
echo "Warning: CompliantUSDC deploy failed or address not found on $name"
|
||||
else
|
||||
echo "CUSDC_ADDRESS_${chain_id}=$CUSDC"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "Done. Add the printed CUSDT_ADDRESS_<id> and CUSDC_ADDRESS_<id> lines to .env."
|
||||
echo "See docs/deployment/CUSDT_CUSDC_MULTICHAIN_LIQUIDITY_RUNBOOK.md for next steps (PMM, Uniswap, Balancer, Curve)."
|
||||
182
scripts/deployment/deploy-dapp-lxc.sh
Executable file
182
scripts/deployment/deploy-dapp-lxc.sh
Executable file
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env bash
|
||||
# Create LXC 5801 (dapp-smom): frontend-dapp build served by nginx.
|
||||
# Usage: ./scripts/deployment/deploy-dapp-lxc.sh [--dry-run] [--skip-create]
|
||||
# --dry-run Print commands only.
|
||||
# --skip-create Use existing container 5801 (only install/build/serve).
|
||||
# Env: PROXMOX_HOST (optional; if unset, run pct on current host), NODE (optional; pct --node),
|
||||
# VMID, HOSTNAME, IP_DAPP_LXC, TEMPLATE, STORAGE, NETWORK, MEMORY_MB, CORES, DISK_GB,
|
||||
# REPO_URL (git URL to clone) or REPO_PATH (local path to copy; no git in container),
|
||||
# ENV_FILE (path to .env for VITE_*).
|
||||
# See: docs/03-deployment/DAPP_LXC_DEPLOYMENT.md
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SMOM_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
# Robust ip-addresses.conf path: override, or proxmox repo layout, or smom-dbis-138-only layout
|
||||
IP_CONFIG_PATH="${IP_CONFIG_PATH:-}"
|
||||
if [[ -n "$IP_CONFIG_PATH" && -f "$IP_CONFIG_PATH" ]]; then
|
||||
source "$IP_CONFIG_PATH" 2>/dev/null || true
|
||||
elif [[ -f "${SMOM_ROOT}/../../config/ip-addresses.conf" ]]; then
|
||||
source "${SMOM_ROOT}/../../config/ip-addresses.conf" 2>/dev/null || true
|
||||
elif [[ -f "${SCRIPT_DIR}/../../../config/ip-addresses.conf" ]]; then
|
||||
source "${SCRIPT_DIR}/../../../config/ip-addresses.conf" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
VMID="${VMID:-5801}"
|
||||
HOSTNAME="${HOSTNAME:-dapp-smom}"
|
||||
IP="${IP_DAPP_LXC:-192.168.11.58}"
|
||||
GATEWAY="${NETWORK_GATEWAY:-192.168.11.1}"
|
||||
NETWORK="${NETWORK:-vmbr0}"
|
||||
STORAGE="${STORAGE:-local-lvm}"
|
||||
TEMPLATE="${TEMPLATE:-local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst}"
|
||||
MEMORY_MB="${MEMORY_MB:-6144}"
|
||||
CORES="${CORES:-4}"
|
||||
DISK_GB="${DISK_GB:-40}"
|
||||
REPO_URL="${REPO_URL:-}"
|
||||
REPO_PATH="${REPO_PATH:-}"
|
||||
ENV_FILE="${ENV_FILE:-}"
|
||||
|
||||
PROXMOX_HOST="${PROXMOX_HOST:-}"
|
||||
NODE="${NODE:-}"
|
||||
SSH_OPTS="-o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new"
|
||||
|
||||
DRY_RUN=false
|
||||
SKIP_CREATE=false
|
||||
for a in "$@"; do
|
||||
[[ "$a" == "--dry-run" ]] && DRY_RUN=true
|
||||
[[ "$a" == "--skip-create" ]] && SKIP_CREATE=true
|
||||
done
|
||||
|
||||
run_cmd() {
|
||||
if [[ -n "$PROXMOX_HOST" ]]; then
|
||||
ssh $SSH_OPTS root@"$PROXMOX_HOST" "$@"
|
||||
else
|
||||
bash -c "$*"
|
||||
fi
|
||||
}
|
||||
|
||||
run_pct() {
|
||||
local node_opt=""
|
||||
[[ -n "$NODE" && -z "$PROXMOX_HOST" ]] && node_opt="--node $NODE"
|
||||
if [[ -n "$PROXMOX_HOST" ]]; then
|
||||
ssh $SSH_OPTS root@"$PROXMOX_HOST" "pct $node_opt $*"
|
||||
else
|
||||
pct $node_opt "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
pct_exec() {
|
||||
run_pct "exec $VMID -- $*"
|
||||
}
|
||||
|
||||
echo "=== DApp LXC ($VMID) — $HOSTNAME ==="
|
||||
echo "IP: $IP | Memory: ${MEMORY_MB}MB | Cores: $CORES | Disk: ${DISK_GB}G"
|
||||
echo ""
|
||||
|
||||
if ! $SKIP_CREATE; then
|
||||
if $DRY_RUN; then
|
||||
echo "[DRY-RUN] Would create LXC $VMID on ${PROXMOX_HOST:-local} with hostname=$HOSTNAME, ip=$IP/24"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if run_pct list 2>/dev/null | grep -q " $VMID "; then
|
||||
echo "Container $VMID already exists. Use --skip-create to only install/build/serve."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Creating CT $VMID ($HOSTNAME)..."
|
||||
# When PROXMOX_HOST is set we SSH to that host; do not pass --node (pct runs on that node).
|
||||
node_opt=""
|
||||
[[ -n "$NODE" && -z "$PROXMOX_HOST" ]] && node_opt="--node $NODE"
|
||||
run_cmd "pct create $VMID $TEMPLATE \
|
||||
--hostname $HOSTNAME \
|
||||
--memory $MEMORY_MB \
|
||||
--cores $CORES \
|
||||
--rootfs $STORAGE:${DISK_GB} \
|
||||
--net0 name=eth0,bridge=$NETWORK,ip=$IP/24,gw=$GATEWAY \
|
||||
--nameserver ${DNS_PRIMARY:-1.1.1.1} \
|
||||
--description 'DApp (frontend-dapp) for Chain 138 bridge. See docs/03-deployment/DAPP_LXC_DEPLOYMENT.md' \
|
||||
--start 1 \
|
||||
--onboot 1 \
|
||||
--unprivileged 0 \
|
||||
--features nesting=1 \
|
||||
$node_opt"
|
||||
|
||||
echo "Waiting for container to boot..."
|
||||
sleep 20
|
||||
fi
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo "[DRY-RUN] Would install Node, nginx, clone repo, build, configure nginx."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Installing Node 20, nginx, git, curl..."
|
||||
pct_exec "bash -c 'export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq curl git ca-certificates'"
|
||||
pct_exec "bash -c 'curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y -qq nodejs'"
|
||||
pct_exec "apt-get install -y -qq nginx"
|
||||
|
||||
if [[ -z "$REPO_URL" && -z "$REPO_PATH" ]]; then
|
||||
echo "Neither REPO_URL nor REPO_PATH set. Skipping clone/copy and build."
|
||||
echo "Example: REPO_URL=https://github.com/your-org/smom-dbis-138.git ... or REPO_PATH=/path/to/smom-dbis-138 ... ./scripts/deployment/deploy-dapp-lxc.sh --skip-create"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
APP_DIR="/srv/smom-dbis-138"
|
||||
pct_exec "mkdir -p $APP_DIR"
|
||||
|
||||
if [[ -n "$REPO_PATH" && -d "$REPO_PATH" ]]; then
|
||||
echo "Copying repo from host ($REPO_PATH)..."
|
||||
PARENT="$(cd "$(dirname "$REPO_PATH")" && pwd)"
|
||||
BARE="$(basename "$REPO_PATH")"
|
||||
TARNAME="smom-dbis-138-deploy.tar.gz"
|
||||
TARBALL="/tmp/$TARNAME"
|
||||
(cd "$PARENT" && tar czf "$TARBALL" --exclude="$BARE/node_modules" --exclude="$BARE/.git" --exclude="$BARE/frontend-dapp/node_modules" --exclude="$BARE/frontend-dapp/dist" "$BARE") || { echo "Failed to create tarball"; exit 1; }
|
||||
if [[ -n "$PROXMOX_HOST" ]]; then
|
||||
scp $SSH_OPTS "$TARBALL" root@"$PROXMOX_HOST":/tmp/
|
||||
run_cmd "pct push $VMID /tmp/$TARNAME /tmp/$TARNAME"
|
||||
pct_exec "bash -c 'rm -rf $APP_DIR && mkdir -p /srv && tar xzf /tmp/$TARNAME -C /srv && rm /tmp/$TARNAME'"
|
||||
run_cmd "rm -f /tmp/$TARNAME"
|
||||
else
|
||||
run_pct push "$VMID" "$TARBALL" "/tmp/$TARNAME"
|
||||
pct_exec "bash -c 'rm -rf $APP_DIR && mkdir -p /srv && tar xzf /tmp/$TARNAME -C /srv && rm /tmp/$TARNAME'"
|
||||
fi
|
||||
rm -f "$TARBALL"
|
||||
elif [[ -n "$REPO_URL" ]]; then
|
||||
echo "Cloning repo..."
|
||||
pct_exec "bash -c 'if [ -d $APP_DIR/.git ]; then (cd $APP_DIR && git fetch && git reset --hard origin/HEAD); else git clone --depth 1 $REPO_URL $APP_DIR; fi'"
|
||||
fi
|
||||
if [[ -n "$ENV_FILE" && -f "$ENV_FILE" ]]; then
|
||||
if [[ -n "$PROXMOX_HOST" ]]; then
|
||||
REMOTE_ENV="/tmp/dapp-deploy-$$.env"
|
||||
echo "Copying .env to Proxmox host and pushing into container..."
|
||||
scp $SSH_OPTS "$ENV_FILE" root@"$PROXMOX_HOST":"$REMOTE_ENV" && \
|
||||
run_pct push "$VMID" "$REMOTE_ENV" "$APP_DIR/.env" 2>/dev/null || true
|
||||
run_cmd "rm -f $REMOTE_ENV" 2>/dev/null || true
|
||||
else
|
||||
run_pct push "$VMID" "$ENV_FILE" "$APP_DIR/.env" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Building frontend-dapp..."
|
||||
pct_exec "bash -c 'cd $APP_DIR/frontend-dapp && (test -f package-lock.json && npm ci || npm install) && npm run build'"
|
||||
|
||||
echo "Configuring nginx to serve dist..."
|
||||
pct_exec "bash -c 'cat > /etc/nginx/sites-available/dapp <<\"NGINXEOF\"
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
root /srv/smom-dbis-138/frontend-dapp/dist;
|
||||
index index.html;
|
||||
server_name _;
|
||||
include /srv/smom-dbis-138/frontend-dapp/nginx-dapp-snippet.conf;
|
||||
location / {
|
||||
try_files \$uri \$uri/ /index.html;
|
||||
}
|
||||
}
|
||||
NGINXEOF
|
||||
rm -f /etc/nginx/sites-enabled/default && ln -sf /etc/nginx/sites-available/dapp /etc/nginx/sites-enabled/dapp && nginx -t && systemctl reload nginx'"
|
||||
|
||||
echo "Done. DApp LXC $VMID ($HOSTNAME) is serving at http://$IP"
|
||||
echo "Add NPMplus proxy host (e.g. dapp.d-bis.org) pointing to $IP:80. See docs/03-deployment/DAPP_LXC_DEPLOYMENT.md"
|
||||
110
scripts/deployment/deploy-full-parity-all-chains.sh
Normal file
110
scripts/deployment/deploy-full-parity-all-chains.sh
Normal file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env bash
|
||||
# Full parity: Mapper + Oracle on ALL bridge networks.
|
||||
# Extends deploy-all-mainnets-with-mapper-oracle-pmm.sh with Celo, Wemix, and Oracle-on-all-chains.
|
||||
# Usage: bash scripts/deployment/deploy-full-parity-all-chains.sh [phase] [--dry-run]
|
||||
# phase: mapper | oracle | bridges | all (default: all)
|
||||
# --dry-run Print commands only
|
||||
# Requires: .env with PRIVATE_KEY and per-chain RPC vars (GNOSIS_RPC, CELO_RPC, WEMIX_RPC, etc.)
|
||||
# See: docs/07-ccip/FULL_PARITY_RUNBOOK.md
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
set +u
|
||||
[ -f .env ] && source .env
|
||||
set -u
|
||||
[ -f "$SCRIPT_DIR/../lib/infura.sh" ] && source "$SCRIPT_DIR/../lib/infura.sh"
|
||||
|
||||
PHASE="${1:-all}"
|
||||
DRY_RUN=false
|
||||
for a in "$@"; do [[ "$a" == "--dry-run" ]] && DRY_RUN=true; done
|
||||
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
ensure_rpc() {
|
||||
local rpc="$1"
|
||||
type ensure_infura_rpc_url &>/dev/null && [ -n "$rpc" ] && rpc=$(ensure_infura_rpc_url "$rpc")
|
||||
echo "$rpc"
|
||||
}
|
||||
|
||||
run_or_echo() {
|
||||
if $DRY_RUN; then
|
||||
echo " [DRY RUN] $*"
|
||||
else
|
||||
eval "$@" || echo -e "${RED} Failed${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Mapper: all chains including Celo, Wemix ---
|
||||
run_mapper() {
|
||||
echo -e "${YELLOW}=== Full Parity: Mapper (AddressMapperEmpty) on ALL bridge chains ===${NC}"
|
||||
[ -z "${PRIVATE_KEY:-}" ] && { echo -e "${RED}PRIVATE_KEY not set${NC}"; return 1; }
|
||||
# RPC_VAR:CHAIN_ID — include Celo, Wemix
|
||||
local chains="ETHEREUM_MAINNET_RPC:1 BSC_RPC_URL:56 POLYGON_MAINNET_RPC:137 BASE_MAINNET_RPC:8453 ARBITRUM_MAINNET_RPC:42161 OPTIMISM_MAINNET_RPC:10 AVALANCHE_RPC_URL:43114 CRONOS_RPC_URL:25 GNOSIS_RPC:100 CELO_RPC:42220 WEMIX_RPC:1111"
|
||||
for entry in $chains; do
|
||||
local rpc_var="${entry%%:*}"; local chain_id="${entry#*:}"
|
||||
local rpc="${!rpc_var:-}"
|
||||
[ -z "$rpc" ] && echo " Skip chain $chain_id ($rpc_var not set)" && continue
|
||||
rpc=$(ensure_rpc "$rpc")
|
||||
echo " Deploying AddressMapperEmpty on chain $chain_id ($rpc_var)..."
|
||||
local gas_opts=""
|
||||
[ "$chain_id" = "138" ] && gas_opts="--with-gas-price ${GAS_PRICE_138:-1000000000} --legacy"
|
||||
run_or_echo "forge script script/DeployAddressMapperOtherChain.s.sol:DeployAddressMapperOtherChain --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" $gas_opts -vvv"
|
||||
done
|
||||
echo -e "${GREEN}Mapper phase done. Record addresses in config.${NC}"
|
||||
}
|
||||
|
||||
# --- Oracle: all chains ---
|
||||
run_oracle() {
|
||||
echo -e "${YELLOW}=== Full Parity: Oracle (Aggregator+Proxy) on ALL bridge chains ===${NC}"
|
||||
[ -z "${PRIVATE_KEY:-}" ] && { echo -e "${RED}PRIVATE_KEY not set${NC}"; return 1; }
|
||||
local chains="RPC_URL_138:138 ETHEREUM_MAINNET_RPC:1 BSC_RPC_URL:56 POLYGON_MAINNET_RPC:137 BASE_MAINNET_RPC:8453 ARBITRUM_MAINNET_RPC:42161 OPTIMISM_MAINNET_RPC:10 AVALANCHE_RPC_URL:43114 CRONOS_RPC_URL:25 GNOSIS_RPC:100 CELO_RPC:42220 WEMIX_RPC:1111"
|
||||
for entry in $chains; do
|
||||
local rpc_var="${entry%%:*}"; local chain_id="${entry#*:}"
|
||||
local rpc="${!rpc_var:-}"
|
||||
[ -z "$rpc" ] && echo " Skip chain $chain_id ($rpc_var not set)" && continue
|
||||
rpc=$(ensure_rpc "$rpc")
|
||||
echo " Deploying Oracle on chain $chain_id ($rpc_var)..."
|
||||
local gas_opts=""
|
||||
[ "$chain_id" = "138" ] && gas_opts="--with-gas-price ${GAS_PRICE_138:-1000000000} --legacy"
|
||||
run_or_echo "forge script script/DeployOracle.s.sol:DeployOracle --rpc-url \"$rpc\" --broadcast --private-key \"\$PRIVATE_KEY\" $gas_opts -vvv"
|
||||
done
|
||||
echo -e "${GREEN}Oracle phase done. Record Aggregator+Proxy addresses in config.${NC}"
|
||||
}
|
||||
|
||||
# --- Bridges: Celo, Wemix (when funded) ---
|
||||
run_bridges() {
|
||||
echo -e "${YELLOW}=== Full Parity: CCIP Bridges on Celo, Wemix ===${NC}"
|
||||
[ -z "${PRIVATE_KEY:-}" ] && { echo -e "${RED}PRIVATE_KEY not set${NC}"; return 1; }
|
||||
run_or_echo "bash scripts/deployment/deploy-bridges-config-ready-chains.sh celo"
|
||||
run_or_echo "bash scripts/deployment/deploy-bridges-config-ready-chains.sh wemix"
|
||||
echo " Run complete-config-ready-chains.sh after recording bridge addresses in .env"
|
||||
echo -e "${GREEN}Bridges phase done.${NC}"
|
||||
}
|
||||
|
||||
# --- Main ---
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}Full Parity: Mapper, Oracle, AMB on All Bridge Networks${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo "Phase: $PHASE Dry-run: $DRY_RUN"
|
||||
echo ""
|
||||
|
||||
case "$PHASE" in
|
||||
mapper) run_mapper ;;
|
||||
oracle) run_oracle ;;
|
||||
bridges) run_bridges ;;
|
||||
all)
|
||||
run_bridges
|
||||
run_mapper
|
||||
run_oracle
|
||||
;;
|
||||
*) echo "Usage: $0 [mapper|oracle|bridges|all] [--dry-run]"; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Done. Update .env and config with new addresses. See docs/07-ccip/FULL_PARITY_RUNBOOK.md${NC}"
|
||||
@@ -49,7 +49,7 @@ if ! cast block-number --rpc-url "$ETHEREUM_MAINNET_RPC" >/dev/null 2>&1; then
|
||||
echo ""
|
||||
echo "Please fix the Infura RPC configuration:"
|
||||
echo " 1. Go to https://infura.io/"
|
||||
echo " 2. Project ID: 43b945b33d58463a9246cf5ca8aa6286"
|
||||
echo " 2. Project ID: (set in .env as INFURA_PROJECT_ID; use INFURA_PROJECT_SECRET for Basic Auth)"
|
||||
echo " 3. Settings → Disable 'Private Key Only'"
|
||||
echo " 4. Save and run this script again"
|
||||
echo ""
|
||||
|
||||
84
scripts/deployment/deploy-official-dvm-chain138.sh
Normal file
84
scripts/deployment/deploy-official-dvm-chain138.sh
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy official DODO DVM (DVMFactory + deps) to Chain 138 via DODOEX/contractV2 Truffle,
|
||||
# then deploy DVMFactoryAdapter (createDVM -> createDODOVendingMachine) via Forge and update .env.
|
||||
# Requires: smom-dbis-138/.env with PRIVATE_KEY, RPC_URL_138
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
DODO_DIR="$PROJECT_ROOT/lib/dodo-contractV2"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if [[ ! -f .env ]]; then
|
||||
echo "ERROR: .env not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
|
||||
if [[ -z "${PRIVATE_KEY:-}" ]]; then
|
||||
echo "ERROR: PRIVATE_KEY not set" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "${RPC_URL_138:-}" ]]; then
|
||||
echo "ERROR: RPC_URL_138 not set" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure DODO submodule has deps and compiles
|
||||
if [[ ! -d "$DODO_DIR/node_modules" ]]; then
|
||||
echo "Installing DODO contractV2 dependencies..."
|
||||
(cd "$DODO_DIR" && npm install)
|
||||
fi
|
||||
|
||||
# Export for Truffle (privKey without 0x for HDWalletProvider if needed)
|
||||
export privKey="${PRIVATE_KEY#0x}"
|
||||
export RPC_URL_138
|
||||
export GAS_PRICE_138="${GAS_PRICE_138:-1000000000}"
|
||||
|
||||
# Deploy Migrations (required for Truffle), then DVM stack only
|
||||
echo "=== Running Truffle migration 1 (Migrations) on Chain 138 ==="
|
||||
(cd "$DODO_DIR" && npx truffle migrate -f 1 --to 1 --network chain138) || true
|
||||
|
||||
echo "=== Running Truffle migration 9 (DVM stack) on Chain 138 ==="
|
||||
(cd "$DODO_DIR" && npx truffle migrate -f 9 --to 9 --network chain138)
|
||||
|
||||
# Parse DVMFactory address from Truffle build (network id 138 as string or number)
|
||||
DVM_FACTORY_ADDRESS=$(cd "$DODO_DIR" && node -e "
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const buildPath = path.join(__dirname, 'build', 'contracts', 'DVMFactory.json');
|
||||
if (!fs.existsSync(buildPath)) process.exit(1);
|
||||
const j = JSON.parse(fs.readFileSync(buildPath, 'utf8'));
|
||||
const n = j.networks || {};
|
||||
const addr = n['138']?.address || n[138]?.address;
|
||||
if (!addr) process.exit(1);
|
||||
console.log(addr);
|
||||
" 2>/dev/null) || true
|
||||
if [[ -z "$DVM_FACTORY_ADDRESS" ]]; then
|
||||
echo "Could not read DVMFactory from build. If you already deployed, set DODO_DVM_FACTORY and run:" >&2
|
||||
echo " DODO_DVM_FACTORY=<dvm_factory_address> forge script script/dex/DeployDVMFactoryAdapter.s.sol:DeployDVMFactoryAdapter --rpc-url \$RPC_URL_138 --broadcast --private-key \$PRIVATE_KEY --legacy" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "DVMFactory deployed at: $DVM_FACTORY_ADDRESS"
|
||||
echo "=== Deploying DVMFactoryAdapter (createDVM wrapper) via Forge ==="
|
||||
export DODO_DVM_FACTORY="$DVM_FACTORY_ADDRESS"
|
||||
forge script script/dex/DeployDVMFactoryAdapter.s.sol:DeployDVMFactoryAdapter \
|
||||
--rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" --legacy
|
||||
|
||||
# Extract adapter address from broadcast (or script output)
|
||||
ADAPTER_ADDRESS=$(grep -o '"contractAddress":"0x[^"]*"' "$PROJECT_ROOT/broadcast/DeployDVMFactoryAdapter.s.sol/138/"*run-latest.json 2>/dev/null | tail -1 | sed 's/.*"0x/0x/;s/".*//') || true
|
||||
if [[ -z "$ADAPTER_ADDRESS" ]]; then
|
||||
echo "Set DODO_VENDING_MACHINE_ADDRESS to the DVMFactoryAdapter address printed above."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "DVMFactoryAdapter at: $ADAPTER_ADDRESS"
|
||||
echo "Updating .env DODO_VENDING_MACHINE_ADDRESS=$ADAPTER_ADDRESS"
|
||||
if grep -q '^DODO_VENDING_MACHINE_ADDRESS=' .env; then
|
||||
sed -i "s|^DODO_VENDING_MACHINE_ADDRESS=.*|DODO_VENDING_MACHINE_ADDRESS=$ADAPTER_ADDRESS|" .env
|
||||
else
|
||||
echo "DODO_VENDING_MACHINE_ADDRESS=$ADAPTER_ADDRESS" >> .env
|
||||
fi
|
||||
echo "Done. Run scripts/deployment/run-pmm-and-pools.sh to deploy DODOPMMIntegration with the official DVM."
|
||||
141
scripts/deployment/deploy-optional-future-all.sh
Executable file
141
scripts/deployment/deploy-optional-future-all.sh
Executable file
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deployments — Chain 138 and multichain (nothing optional nor future; these are planned deployments).
|
||||
# Usage:
|
||||
# ./scripts/deployment/deploy-optional-future-all.sh # run all phases
|
||||
# ./scripts/deployment/deploy-optional-future-all.sh --dry-run # print only
|
||||
# ./scripts/deployment/deploy-optional-future-all.sh --phases 1,3,5 # run phases 1,3,5
|
||||
#
|
||||
# Requires: .env with PRIVATE_KEY, RPC_URL_138. Chain 138: --with-gas-price (default 2 gwei).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
RPC="${RPC_URL_138:-http://192.168.11.211:8545}"
|
||||
# Default 2 gwei to reduce "Replacement transaction underpriced"; override with GAS_PRICE_138.
|
||||
GAS_PRICE="${GAS_PRICE_138:-2000000000}"
|
||||
DRY_RUN=""
|
||||
PHASES="" # comma-separated, e.g. 1,3,5
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=1 ;;
|
||||
--phases)
|
||||
shift
|
||||
[ $# -gt 0 ] && PHASES="$1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z "${PRIVATE_KEY:-}" ]; then
|
||||
echo "ERROR: PRIVATE_KEY not set in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# run_phase num name skip_var cmd [required_var]
|
||||
# If required_var is set and skip_var is not set, requires that required_var is non-empty in env; else skips with message.
|
||||
run_phase() {
|
||||
local num="$1"
|
||||
local name="$2"
|
||||
local skip_var="$3"
|
||||
local cmd="$4"
|
||||
local required_var="${5:-}"
|
||||
|
||||
if [ -n "$PHASES" ]; then
|
||||
if ! echo ",$PHASES," | grep -q ",$num,"; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$skip_var" ]; then
|
||||
local val=""
|
||||
eval "val=\"\${${skip_var}:-}\""
|
||||
if [ -n "$val" ]; then
|
||||
echo "[Phase $num] $name — SKIP (${skip_var} already set)"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$required_var" ]; then
|
||||
local req_val=""
|
||||
eval "req_val=\"\${${required_var}:-}\""
|
||||
if [ -z "$req_val" ]; then
|
||||
echo "[Phase $num] $name — SKIP (set ${required_var} in .env to run; or set ${skip_var} to skip)"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "[Phase $num] $name — RUNNING"
|
||||
if [ -n "$DRY_RUN" ]; then
|
||||
echo " would run: $(echo "$cmd" | sed 's/--private-key "[^"]*"/--private-key ***REDACTED***/g')"
|
||||
return 0
|
||||
fi
|
||||
eval "$cmd" || { echo "Phase $num failed."; exit 1; }
|
||||
echo "[Phase $num] $name — DONE"
|
||||
}
|
||||
|
||||
echo "============================================"
|
||||
echo "Deployments — Chain 138 and multichain"
|
||||
echo "RPC: $RPC"
|
||||
echo "Gas price: $GAS_PRICE wei"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
# Phase 1: CREATE2 / Deterministic core
|
||||
run_phase 1 "Deterministic core (DeployDeterministicCore)" "CREATE2_FACTORY" \
|
||||
"forge script script/deploy/DeployDeterministicCore.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 2: Vault system
|
||||
run_phase 2 "Vault system (DeployVaultSystem)" "VAULT_FACTORY" \
|
||||
"forge script script/deploy/vault/DeployVaultSystem.s.sol:DeployVaultSystem --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 3: Reserve system (requires TOKEN_FACTORY)
|
||||
run_phase 3 "Reserve system (DeployReserveSystem)" "RESERVE_SYSTEM" \
|
||||
"forge script script/reserve/DeployReserveSystem.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 4: Reserve Keeper (requires ORACLE_PRICE_FEED unless RESERVE_KEEPER already set)
|
||||
run_phase 4 "Reserve Keeper (DeployKeeper)" "RESERVE_KEEPER" \
|
||||
"forge script script/reserve/DeployKeeper.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\"" \
|
||||
"ORACLE_PRICE_FEED"
|
||||
|
||||
# Phase 5: PaymentChannelManager + GenericStateChannelManager
|
||||
run_phase 5a "PaymentChannelManager" "PAYMENT_CHANNEL_MANAGER" \
|
||||
"forge script script/DeployPaymentChannelManager.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
run_phase 5b "GenericStateChannelManager" "GENERIC_STATE_CHANNEL_MANAGER" \
|
||||
"forge script script/DeployGenericStateChannelManager.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 6: Trustless bridge (Lockbox138 on Chain 138)
|
||||
run_phase 6 "Trustless bridge (Lockbox138)" "LOCKBOX_138" \
|
||||
"forge script script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 7: DODO / Swap (requires DODO_VENDING_MACHINE_ADDRESS, COMPLIANT_USDT_ADDRESS, COMPLIANT_USDC_ADDRESS)
|
||||
run_phase 7 "DODO PMM Integration" "DODOPMM_INTEGRATION_ADDRESS" \
|
||||
"forge script script/dex/DeployDODOPMMIntegration.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\"" \
|
||||
"DODO_VENDING_MACHINE_ADDRESS"
|
||||
|
||||
# Phase 8: eMoney (Chain 138)
|
||||
run_phase 8 "eMoney (DeployChain138)" "TOKEN_FACTORY_138" \
|
||||
"forge script script/emoney/DeployChain138.s.sol:DeployChain138 --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
# Phase 9: Smart accounts (informational — actual deploy from ERC-4337 impl)
|
||||
run_phase 9 "Smart accounts kit (informational)" "" \
|
||||
"forge script script/smart-accounts/DeploySmartAccountsKit.s.sol --rpc-url \"$RPC\" --broadcast --private-key \"$PRIVATE_KEY\" --with-gas-price \"$GAS_PRICE\""
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Deployments finished."
|
||||
echo "Update .env with new addresses."
|
||||
echo "DeployAll (mainnet/multichain): run script/DeployAll.s.sol per chain."
|
||||
echo "Trustless bridge Mainnet: run DeployTrustlessBridge with MAINNET_RPC."
|
||||
echo "See docs/03-deployment/OPTIONAL_FUTURE_DEPLOYMENTS_RUNBOOK.md"
|
||||
echo "============================================"
|
||||
76
scripts/deployment/deploy-pmm-all-l2s.sh
Executable file
76
scripts/deployment/deploy-pmm-all-l2s.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy DODOPMMIntegration on each L2 (BSC, Polygon, Base, Optimism, Arbitrum, Avalanche, Cronos, Gnosis).
|
||||
# Uses .env for RPC and token addresses. Chains via tag: --chain bsc polygon ... (or DEPLOY_PMM_L2S_FILTER in .env).
|
||||
# Usage: ./scripts/deployment/deploy-pmm-all-l2s.sh [--chain bsc polygon base]
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
source "$SCRIPT_DIR/../lib/deployment/prompts.sh"
|
||||
load_deployment_env
|
||||
|
||||
parse_chain_filter "$@"
|
||||
if [[ ${#CHAIN_FILTER[@]} -eq 0 && -n "${DEPLOY_PMM_L2S_FILTER:-}" ]]; then
|
||||
CHAIN_FILTER=()
|
||||
for n in $DEPLOY_PMM_L2S_FILTER; do n="$(normalize_chain_name "$n")"; [[ -n "$n" ]] && CHAIN_FILTER+=("$n"); done
|
||||
fi
|
||||
|
||||
CHAINS=(
|
||||
"BSC:56:BSC_RPC_URL"
|
||||
"POLYGON:137:POLYGON_MAINNET_RPC"
|
||||
"BASE:8453:BASE_MAINNET_RPC"
|
||||
"OPTIMISM:10:OPTIMISM_MAINNET_RPC"
|
||||
"ARBITRUM:42161:ARBITRUM_MAINNET_RPC"
|
||||
"AVALANCHE:43114:AVALANCHE_RPC_URL"
|
||||
"CRONOS:25:CRONOS_RPC_URL"
|
||||
"GNOSIS:100:GNOSIS_MAINNET_RPC"
|
||||
)
|
||||
|
||||
for entry in "${CHAINS[@]}"; do
|
||||
IFS=: read -r name chain_id rpc_var <<< "$entry"
|
||||
if [[ ${#CHAIN_FILTER[@]} -gt 0 ]] && [[ ! " ${CHAIN_FILTER[*]} " =~ " $name " ]]; then continue; fi
|
||||
|
||||
rpc="${!rpc_var:-}"
|
||||
if [[ -z "$rpc" ]]; then
|
||||
echo "Skip $name (chain $chain_id): $rpc_var not set"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Prefer chain-prefixed DVM and tokens; fallback to global
|
||||
dvm_var="${name}_DODO_VENDING_MACHINE_ADDRESS"
|
||||
usdt_var="${name}_OFFICIAL_USDT_ADDRESS"
|
||||
usdc_var="${name}_OFFICIAL_USDC_ADDRESS"
|
||||
cusdt_var="${name}_COMPLIANT_USDT_ADDRESS"
|
||||
cusdc_var="${name}_COMPLIANT_USDC_ADDRESS"
|
||||
# Per-chain cUSDT/cUSDC (optional): CUSDT_ADDRESS_<chainId> / CUSDC_ADDRESS_<chainId> or POLYGON_COMPLIANT_USDT_ADDRESS etc.
|
||||
cusdt_chain="CUSDT_ADDRESS_${chain_id}"
|
||||
cusdc_chain="CUSDC_ADDRESS_${chain_id}"
|
||||
dvm="${!dvm_var:-$DODO_VENDING_MACHINE_ADDRESS}"
|
||||
usdt="${!usdt_var:-$OFFICIAL_USDT_ADDRESS}"
|
||||
usdc="${!usdc_var:-$OFFICIAL_USDC_ADDRESS}"
|
||||
compliant_usdt="${!cusdt_var:-${!cusdt_chain:-$usdt}}"
|
||||
compliant_usdc="${!cusdc_var:-${!cusdc_chain:-$usdc}}"
|
||||
|
||||
if [[ -z "$dvm" ]] || [[ -z "$usdt" ]] || [[ -z "$usdc" ]]; then
|
||||
echo "Skip $name: set ${dvm_var} (or DODO_VENDING_MACHINE_ADDRESS), ${usdt_var}, ${usdc_var} (or OFFICIAL_USDT/USDC_ADDRESS)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "=== Deploying DODOPMMIntegration on $name (chain $chain_id) ==="
|
||||
DODO_VENDING_MACHINE_ADDRESS="$dvm" \
|
||||
OFFICIAL_USDT_ADDRESS="$usdt" \
|
||||
OFFICIAL_USDC_ADDRESS="$usdc" \
|
||||
COMPLIANT_USDT_ADDRESS="$compliant_usdt" \
|
||||
COMPLIANT_USDC_ADDRESS="$compliant_usdc" \
|
||||
forge script script/dex/DeployDODOPMMIntegration.s.sol:DeployDODOPMMIntegration \
|
||||
--rpc-url "$rpc" \
|
||||
--chain-id "$chain_id" \
|
||||
--broadcast \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
-vvv || true
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "Done. Update .env with any new DODOPMM_INTEGRATION_<CHAIN> addresses."
|
||||
85
scripts/deployment/deploy-sufficient-balance-chains.sh
Executable file
85
scripts/deployment/deploy-sufficient-balance-chains.sh
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy to chains with sufficient native token balance (Avalanche, Arbitrum, Cronos).
|
||||
# Run check-balances-gas-and-deploy.sh first to confirm balances.
|
||||
# Chain 138 phased core is deployed separately (check-balances-gas-and-deploy.sh --deploy).
|
||||
#
|
||||
# Requires: PRIVATE_KEY, CCIP_*_ROUTER, CCIP_*_LINK_TOKEN, *_SELECTOR, *_RPC_URL per chain.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Load .env
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
if [ -z "${PRIVATE_KEY:-}" ]; then
|
||||
echo -e "${RED}ERROR: PRIVATE_KEY not set in .env${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Chains with sufficient balance (from last balance check): Avalanche, Arbitrum, Cronos
|
||||
# Prefer INFURA_PROJECT_ID (+ optional INFURA_PROJECT_SECRET) when set; else public RPCs
|
||||
[[ -f "$SCRIPT_DIR/../lib/infura.sh" ]] && source "$SCRIPT_DIR/../lib/infura.sh"
|
||||
_av_rpc=$(build_infura_rpc "avalanche-mainnet" 2>/dev/null || true)
|
||||
_ar_rpc=$(build_infura_rpc "arbitrum-mainnet" 2>/dev/null || true)
|
||||
AVALANCHE_RPC="${AVALANCHE_RPC_URL:-${AVALANCHE_RPC:-${_av_rpc:-https://avalanche-c-chain.publicnode.com}}}"
|
||||
ARBITRUM_RPC="${ARBITRUM_MAINNET_RPC:-${ARBITRUM_RPC:-${_ar_rpc:-https://arbitrum-one.publicnode.com}}}"
|
||||
CRONOS_RPC="${CRONOS_RPC_URL:-${CRONOS_RPC:-https://evm.cronos.org}}"
|
||||
|
||||
deploy_chain() {
|
||||
local name="$1"
|
||||
local rpc="$2"
|
||||
local chain_id="$3"
|
||||
echo -e "${YELLOW}Deploying to ${name} (chain ${chain_id})...${NC}"
|
||||
forge script script/DeployAll.s.sol:DeployAll \
|
||||
--rpc-url "$rpc" \
|
||||
--chain-id "$chain_id" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--broadcast \
|
||||
--slow \
|
||||
-vvvv || {
|
||||
echo -e "${RED}✗ ${name} deployment failed${NC}"
|
||||
return 1
|
||||
}
|
||||
echo -e "${GREEN}✓ ${name} deployment complete${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo -e "${BLUE}Deploy to chains with sufficient balance${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo "Chains: Avalanche, Arbitrum, Cronos"
|
||||
echo ""
|
||||
|
||||
# Verify required CCIP env vars
|
||||
for chain in AVALANCHE ARBITRUM CRONOS; do
|
||||
router="CCIP_${chain}_ROUTER"
|
||||
link="CCIP_${chain}_LINK_TOKEN"
|
||||
selector="${chain}_SELECTOR"
|
||||
if [ -z "${!router:-}" ] || [ -z "${!link:-}" ] || [ -z "${!selector:-}" ]; then
|
||||
echo -e "${RED}ERROR: Missing ${router}, ${link}, or ${selector} in .env${NC}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Deploy (skip --verify to avoid needing chain-specific explorer API keys)
|
||||
deploy_chain "Avalanche" "$AVALANCHE_RPC" "43114"
|
||||
deploy_chain "Arbitrum" "$ARBITRUM_RPC" "42161"
|
||||
deploy_chain "Cronos" "$CRONOS_RPC" "25"
|
||||
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}Deployments complete${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo "Next: update .env with deployed addresses; run verify manually if needed."
|
||||
340
scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh
Executable file
340
scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh
Executable file
@@ -0,0 +1,340 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy WETH9/WETH10 + CCIP bridges (and optionally Cronos D-WIN W) to all blockchains
|
||||
# unless a canonical/pre-existing deployment is already present in .env.
|
||||
#
|
||||
# Deploys:
|
||||
# - WETH9, WETH10, CCIPWETH9Bridge, CCIPWETH10Bridge (via DeployAll.s.sol) on each chain
|
||||
# where WETH9_<CHAIN> and WETH10_<CHAIN> are not both set.
|
||||
# - On Cronos (25): optionally ISO-4217 W system (USDW, EURW, ...) if not already deployed.
|
||||
# - With --deploy-c: cUSDT/cUSDC (and optional c*) on each chain where CUSDT_<CHAIN>/CUSDC_<CHAIN> unset (via DeployCompliantFiatTokensForChain.s.sol).
|
||||
# - With --deploy-cw: cWUSDT/cWUSDC on each chain where CWUSDT_<CHAIN> unset (via DeployCWTokens.s.sol; set CW_BRIDGE_ADDRESS or CW_BRIDGE_<CHAIN>).
|
||||
# - Chain 651940 (ALL Mainnet): env validation only (check AUSDT_ADDRESS_651940 set); no token deploy from this repo.
|
||||
#
|
||||
# Skips:
|
||||
# - Ethereum Mainnet (1): uses canonical WETH from .env (WETH9_MAINNET, WETH10_MAINNET).
|
||||
# - Any chain where both WETH9_* and WETH10_* are already set in .env.
|
||||
# - Chain 138: not in DeployAll; compliant tokens (c*) are deployed separately on 138.
|
||||
#
|
||||
# Usage:
|
||||
# cd smom-dbis-138 && ./scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh [OPTIONS]
|
||||
#
|
||||
# Options:
|
||||
# --dry-run Print commands only; do not broadcast.
|
||||
# --chain 25 56 137 Deploy only to these chain IDs (default: all supported).
|
||||
# --no-iso4217 Do not deploy ISO-4217 W system on Cronos even if missing.
|
||||
# --iso4217-only Only run Cronos ISO-4217 W deploy (skip DeployAll).
|
||||
# --deploy-c Deploy cUSDT/cUSDC (and optional c*) on chains where CUSDT_<CHAIN>/CUSDC_<CHAIN> unset (skip 138, 1).
|
||||
# --deploy-cw Deploy cWUSDT/cWUSDC on chains where CWUSDT_<CHAIN> unset; requires CW_BRIDGE_ADDRESS or CW_BRIDGE_<CHAIN> in .env.
|
||||
#
|
||||
# Requires: .env with PRIVATE_KEY; per-chain RPC and CCIP vars for chains you deploy to.
|
||||
# See: docs/11-references/TOKENS_DEPLOYER_DEPLOYED_ON_OTHER_CHAINS.md
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
[ -f .env ] && set -a && source .env && set +a
|
||||
|
||||
DRY_RUN=false
|
||||
CHAINS_FILTER=""
|
||||
NO_ISO4217=false
|
||||
ISO4217_ONLY=false
|
||||
DEPLOY_C=false
|
||||
DEPLOY_CW=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--no-iso4217) NO_ISO4217=true; shift ;;
|
||||
--iso4217-only) ISO4217_ONLY=true; shift ;;
|
||||
--deploy-c) DEPLOY_C=true; shift ;;
|
||||
--deploy-cw) DEPLOY_CW=true; shift ;;
|
||||
--chain)
|
||||
shift
|
||||
CHAINS_FILTER="$*"
|
||||
break
|
||||
;;
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Chain ID : Name : RPC env var (primary)
|
||||
# DeployAll.s.sol supports: 1, 25, 56, 137, 100, 43114, 8453, 42161, 10. 651940 = env validation only.
|
||||
ALL_CHAINS="1:Mainnet:ETH_MAINNET_RPC_URL 25:Cronos:CRONOS_RPC_URL 56:BSC:BSC_RPC_URL 137:Polygon:POLYGON_RPC_URL 100:Gnosis:GNOSIS_RPC_URL 43114:Avalanche:AVALANCHE_RPC_URL 8453:Base:BASE_RPC_URL 42161:Arbitrum:ARBITRUM_RPC_URL 10:Optimism:OPTIMISM_RPC_URL 651940:ALL:CHAIN_651940_RPC"
|
||||
|
||||
# Fallback RPC env names (some scripts use different names)
|
||||
fallback_rpc() {
|
||||
local chain_id="$1"
|
||||
local rpc_var="$2"
|
||||
local rpc="${!rpc_var:-}"
|
||||
if [[ -z "$rpc" ]]; then
|
||||
case "$chain_id" in
|
||||
1) rpc="${ETHEREUM_MAINNET_RPC:-${ETH_MAINNET_RPC_URL:-}}";;
|
||||
25) rpc="${CRONOS_RPC:-}";;
|
||||
56) rpc="${BSC_RPC_URL:-}";;
|
||||
137) rpc="${POLYGON_MAINNET_RPC:-}";;
|
||||
100) rpc="${GNOSIS_RPC:-}";;
|
||||
43114) rpc="${AVALANCHE_RPC_URL:-}";;
|
||||
8453) rpc="${BASE_MAINNET_RPC:-}";;
|
||||
42161) rpc="${ARBITRUM_MAINNET_RPC:-}";;
|
||||
10) rpc="${OPTIMISM_MAINNET_RPC:-}";;
|
||||
651940) rpc="${CHAIN_651940_RPC:-${ALL_MAINNET_RPC:-}}";;
|
||||
esac
|
||||
fi
|
||||
echo "$rpc"
|
||||
}
|
||||
|
||||
is_canonical_present() {
|
||||
local weth9_var="$1"
|
||||
local weth10_var="$2"
|
||||
local w9="${!weth9_var:-}"
|
||||
local w10="${!weth10_var:-}"
|
||||
w9="${w9//0x/}"
|
||||
w10="${w10//0x/}"
|
||||
[[ -n "$w9" && "${#w9}" -ge 40 && "$w9" != "0000000000000000000000000000000000000000" ]] && \
|
||||
[[ -n "$w10" && "${#w10}" -ge 40 && "$w10" != "0000000000000000000000000000000000000000" ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
run_cmd() {
|
||||
if $DRY_RUN; then
|
||||
echo " [DRY-RUN] $*"
|
||||
else
|
||||
eval "$@" || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- DeployAll (WETH9, WETH10, CCIP bridges) per chain ----------
|
||||
run_deploy_all() {
|
||||
local chain_id="$1"
|
||||
local name="$2"
|
||||
local rpc_var="$3"
|
||||
if [[ "$chain_id" == "651940" ]]; then
|
||||
echo " Skip $name (chain 651940): DeployAll not supported; env validation only."
|
||||
return 0
|
||||
fi
|
||||
local rpc
|
||||
rpc=$(fallback_rpc "$chain_id" "$rpc_var")
|
||||
if [[ -z "$rpc" ]]; then
|
||||
echo " Skip $name (chain $chain_id): RPC not set ($rpc_var)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local weth9_var="WETH9_MAINNET" weth10_var="WETH10_MAINNET"
|
||||
case "$chain_id" in
|
||||
1) weth9_var="WETH9_MAINNET"; weth10_var="WETH10_MAINNET" ;;
|
||||
25) weth9_var="WETH9_CRONOS"; weth10_var="WETH10_CRONOS" ;;
|
||||
56) weth9_var="WETH9_BSC"; weth10_var="WETH10_BSC" ;;
|
||||
137) weth9_var="WETH9_POLYGON"; weth10_var="WETH10_POLYGON" ;;
|
||||
100) weth9_var="WETH9_GNOSIS"; weth10_var="WETH10_GNOSIS" ;;
|
||||
43114) weth9_var="WETH9_AVALANCHE"; weth10_var="WETH10_AVALANCHE" ;;
|
||||
8453) weth9_var="WETH9_BASE"; weth10_var="WETH10_BASE" ;;
|
||||
42161) weth9_var="WETH9_ARBITRUM"; weth10_var="WETH10_ARBITRUM" ;;
|
||||
10) weth9_var="WETH9_OPTIMISM"; weth10_var="WETH10_OPTIMISM" ;;
|
||||
*) echo " Unsupported chain ID $chain_id"; return 1 ;;
|
||||
esac
|
||||
|
||||
# Mainnet: use canonical WETH from .env; DeployAll only deploys CCIPLogger (placeholder). Skip to avoid requiring env.
|
||||
if [[ "$chain_id" == "1" ]]; then
|
||||
if is_canonical_present "$weth9_var" "$weth10_var"; then
|
||||
echo " Skip $name (chain $chain_id): canonical WETH9/WETH10 already set."
|
||||
return 0
|
||||
fi
|
||||
echo " Skip $name (chain $chain_id): set WETH9_MAINNET and WETH10_MAINNET in .env for canonical WETH; DeployAll on Mainnet does not deploy tokens."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if is_canonical_present "$weth9_var" "$weth10_var"; then
|
||||
echo " Skip $name (chain $chain_id): WETH9/WETH10 already set in .env."
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo " Deploying WETH9, WETH10, CCIP bridges on $name (chain $chain_id)..."
|
||||
local gas_opts="--legacy"
|
||||
run_cmd "forge script script/DeployAll.s.sol:DeployAll --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" $gas_opts -vvv" || true
|
||||
echo " → Set WETH9_${name^^}, WETH10_${name^^}, CCIPWETH9_BRIDGE_${name^^}, CCIPWETH10_BRIDGE_${name^^} in .env from script output."
|
||||
}
|
||||
|
||||
# ---------- ISO-4217 W (Cronos): deploy only if USDW not already deployed ----------
|
||||
run_iso4217_cronos() {
|
||||
if $NO_ISO4217; then
|
||||
echo " Skip Cronos ISO-4217 W (--no-iso4217)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local rpc
|
||||
rpc=$(fallback_rpc 25 "CRONOS_RPC_URL")
|
||||
[[ -z "$rpc" ]] && rpc="${CRONOS_RPC:-}"
|
||||
if [[ -z "$rpc" ]]; then
|
||||
echo " Skip Cronos ISO-4217 W: CRONOS_RPC_URL / CRONOS_RPC not set."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local usdw_addr="0x948690147D2e50ffe50C5d38C14125aD6a9FA036"
|
||||
local code_len
|
||||
code_len=$(cast code "$usdw_addr" --rpc-url "$rpc" 2>/dev/null | wc -c)
|
||||
if [[ -n "$code_len" && "$code_len" -gt 10 ]]; then
|
||||
echo " Skip Cronos ISO-4217 W: USDW already deployed at $usdw_addr."
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo " Deploying ISO-4217 W system on Cronos (25)..."
|
||||
run_cmd "forge script script/deploy/iso4217w/DeployISO4217WSystem.s.sol:DeployISO4217WSystem --rpc-url \"$rpc\" --chain-id 25 --broadcast --private-key \"\$PRIVATE_KEY\" --legacy -vvv" || true
|
||||
echo " → Record MintController, TokenRegistry, USDW, EURW, ... addresses from output; add to .env / docs."
|
||||
}
|
||||
|
||||
# ---------- c* (cUSDT, cUSDC) on other chains: DeployCompliantFiatTokensForChain ----------
|
||||
run_deploy_c() {
|
||||
local chain_id="$1"
|
||||
local name="$2"
|
||||
local rpc_var="$3"
|
||||
[[ "$chain_id" == "138" || "$chain_id" == "1" ]] && return 0
|
||||
local rpc
|
||||
rpc=$(fallback_rpc "$chain_id" "$rpc_var")
|
||||
if [[ -z "$rpc" ]]; then return 0; fi
|
||||
local cusdt_var="CUSDT_${name^^}" cusdc_var="CUSDC_${name^^}"
|
||||
local cusdt_val="${!cusdt_var:-}" cusdc_val="${!cusdc_var:-}"
|
||||
cusdt_val="${cusdt_val//0x/}"; cusdc_val="${cusdc_val//0x/}"
|
||||
if [[ -n "$cusdt_val" && "${#cusdt_val}" -ge 40 ]] && [[ -n "$cusdc_val" && "${#cusdc_val}" -ge 40 ]]; then
|
||||
echo " Skip c* on $name (chain $chain_id): CUSDT_${name^^} and CUSDC_${name^^} already set."
|
||||
return 0
|
||||
fi
|
||||
echo " Deploying cUSDT/cUSDC on $name (chain $chain_id)..."
|
||||
run_cmd "forge script script/deploy/DeployCompliantFiatTokensForChain.s.sol:DeployCompliantFiatTokensForChain --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" --legacy -vvv" || true
|
||||
echo " → Set CUSDT_${name^^}, CUSDC_${name^^} in .env from script output."
|
||||
}
|
||||
|
||||
# ---------- cW* (all 12: cWUSDT, cWUSDC, cWEURC, cWEURT, cWGBPC, cWGBPT, cWAUDC, cWJPYC, cWCHFC, cWCADC, cWXAUC, cWXAUT): DeployCWTokens ----------
|
||||
run_deploy_cw() {
|
||||
local chain_id="$1"
|
||||
local name="$2"
|
||||
local rpc_var="$3"
|
||||
local rpc
|
||||
rpc=$(fallback_rpc "$chain_id" "$rpc_var")
|
||||
if [[ -z "$rpc" ]]; then return 0; fi
|
||||
local bridge_var="CW_BRIDGE_${name^^}"
|
||||
local bridge="${!bridge_var:-${CW_BRIDGE_ADDRESS:-}}"
|
||||
if [[ -z "$bridge" || "$bridge" == "0x"*"0000000000000000000000000000000000000000" ]]; then
|
||||
echo " Skip cW* on $name (chain $chain_id): set CW_BRIDGE_ADDRESS or CW_BRIDGE_${name^^} in .env."
|
||||
return 0
|
||||
fi
|
||||
local cw_var="CWUSDT_${name^^}"
|
||||
local cw_val="${!cw_var:-}"
|
||||
cw_val="${cw_val//0x/}"
|
||||
local deploy_opts=""
|
||||
if [[ -n "$cw_val" && "${#cw_val}" -ge 40 ]]; then
|
||||
echo " Deploying remaining cW* (cWEURC..cWXAUT) on $name (chain $chain_id) (bridge $bridge)..."
|
||||
deploy_opts="DEPLOY_CWUSDT=0 DEPLOY_CWUSDC=0"
|
||||
else
|
||||
echo " Deploying all cW* (12 tokens) on $name (chain $chain_id) (bridge $bridge)..."
|
||||
fi
|
||||
local gas_opt=""
|
||||
[[ "$chain_id" == "42161" && -n "${ARBITRUM_GAS_PRICE:-}" ]] && gas_opt="--with-gas-price ${ARBITRUM_GAS_PRICE}"
|
||||
run_cmd "${deploy_opts:+$deploy_opts }CW_BRIDGE_ADDRESS=$bridge forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" --legacy ${gas_opt} -vvv" || true
|
||||
echo " → Set CWUSDT_*, CWUSDC_*, CWEURC_*, CWEURT_*, CWGBPC_*, CWGBPT_*, CWAUDC_*, CWJPYC_*, CWCHFC_*, CWCADC_*, CWXAUC_*, CWXAUT_* in .env from script output."
|
||||
}
|
||||
|
||||
# ---------- 651940 (ALL Mainnet): env validation only ----------
|
||||
run_651940_validate() {
|
||||
local rpc
|
||||
rpc=$(fallback_rpc 651940 "CHAIN_651940_RPC")
|
||||
if [[ -z "$rpc" ]]; then
|
||||
echo " Skip ALL (651940): CHAIN_651940_RPC not set."
|
||||
return 0
|
||||
fi
|
||||
local ausdt_var="AUSDT_ADDRESS_651940"
|
||||
local ausdt_val="${!ausdt_var:-}"
|
||||
if [[ -z "$ausdt_val" || "$ausdt_val" == "0x0000000000000000000000000000000000000000" ]]; then
|
||||
echo " ALL (651940): Set AUSDT_ADDRESS_651940 in .env (ecosystem token; not deployed by this script)."
|
||||
else
|
||||
echo " ALL (651940): AUSDT_ADDRESS_651940 set."
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- Main ----------
|
||||
echo "=============================================="
|
||||
echo "Deploy tokens/WETH to all chains (skip canonical)"
|
||||
echo "=============================================="
|
||||
echo " Dry-run: $DRY_RUN"
|
||||
echo " Chain filter: ${CHAINS_FILTER:-all}"
|
||||
echo " ISO-4217 on Cronos: $(! $NO_ISO4217 && ! $ISO4217_ONLY || $ISO4217_ONLY)"
|
||||
echo " Deploy c* (cUSDT/cUSDC): $DEPLOY_C"
|
||||
echo " Deploy cW* (cWUSDT/cWUSDC): $DEPLOY_CW"
|
||||
echo ""
|
||||
|
||||
if [[ -z "${PRIVATE_KEY:-}" ]]; then
|
||||
echo "ERROR: PRIVATE_KEY not set in .env." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! $ISO4217_ONLY; then
|
||||
echo "--- DeployAll (WETH9, WETH10, CCIP bridges) per chain ---"
|
||||
for entry in $ALL_CHAINS; do
|
||||
chain_id="${entry%%:*}"; rest="${entry#*:}"
|
||||
name="${rest%%:*}"; rpc_var="${rest#*:}"
|
||||
if [[ -n "$CHAINS_FILTER" ]]; then
|
||||
echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue
|
||||
fi
|
||||
run_deploy_all "$chain_id" "$name" "$rpc_var"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! $ISO4217_ONLY; then
|
||||
if [[ -z "$CHAINS_FILTER" ]] || echo "$CHAINS_FILTER" | grep -q "\b25\b"; then
|
||||
echo "--- Cronos: ISO-4217 W (USDW, EURW, ...) ---"
|
||||
run_iso4217_cronos
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
echo "--- Cronos: ISO-4217 W only ---"
|
||||
run_iso4217_cronos
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if $DEPLOY_C; then
|
||||
echo "--- Deploy c* (cUSDT/cUSDC) per chain (skip 138, 1) ---"
|
||||
for entry in $ALL_CHAINS; do
|
||||
chain_id="${entry%%:*}"; rest="${entry#*:}"
|
||||
name="${rest%%:*}"; rpc_var="${rest#*:}"
|
||||
if [[ "$chain_id" == "651940" ]]; then continue; fi
|
||||
if [[ -n "$CHAINS_FILTER" ]]; then
|
||||
echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue
|
||||
fi
|
||||
run_deploy_c "$chain_id" "$name" "$rpc_var"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if $DEPLOY_CW; then
|
||||
echo "--- Deploy cW* (cWUSDT/cWUSDC) per chain ---"
|
||||
for entry in $ALL_CHAINS; do
|
||||
chain_id="${entry%%:*}"; rest="${entry#*:}"
|
||||
name="${rest%%:*}"; rpc_var="${rest#*:}"
|
||||
if [[ "$chain_id" == "651940" ]]; then continue; fi
|
||||
if [[ -n "$CHAINS_FILTER" ]]; then
|
||||
echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue
|
||||
fi
|
||||
run_deploy_cw "$chain_id" "$name" "$rpc_var"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "--- Chain 651940 (ALL Mainnet) env validation ---"
|
||||
for entry in $ALL_CHAINS; do
|
||||
chain_id="${entry%%:*}"; rest="${entry#*:}"
|
||||
name="${rest%%:*}"; rpc_var="${rest#*:}"
|
||||
if [[ "$chain_id" != "651940" ]]; then continue; fi
|
||||
if [[ -n "$CHAINS_FILTER" ]]; then
|
||||
echo "$CHAINS_FILTER" | grep -q "\b651940\b" || continue
|
||||
fi
|
||||
run_651940_validate
|
||||
break
|
||||
done
|
||||
echo ""
|
||||
|
||||
echo "=============================================="
|
||||
echo "Done. Update .env with deployed addresses; see TOKENS_DEPLOYER_DEPLOYED_ON_OTHER_CHAINS.md."
|
||||
echo "=============================================="
|
||||
45
scripts/deployment/deploy-trustless-l2s.sh
Executable file
45
scripts/deployment/deploy-trustless-l2s.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy Trustless Bridge stack (BondManager, ChallengeManager, LiquidityPool, Inbox, optional Lockbox) on each L2.
|
||||
# Uses .env for RPC and PRIVATE_KEY. Chains via --chain bsc polygon ...; Lockbox via --lockbox / --no-lockbox (not .env).
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/deployment/deploy-trustless-l2s.sh
|
||||
# ./scripts/deployment/deploy-trustless-l2s.sh --chain bsc polygon --lockbox
|
||||
# ./scripts/deployment/deploy-trustless-l2s.sh --no-lockbox
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
DOTENV="$REPO_ROOT/.env"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
source "$SCRIPT_DIR/../lib/deployment/prompts.sh"
|
||||
load_deployment_env
|
||||
|
||||
parse_lockbox_tag "$@"
|
||||
set -- "${PARSE_LOCKBOX_REMAINING[@]}"
|
||||
parse_chain_filter "$@"
|
||||
# Backward compat: single positional chain (e.g. deploy-trustless-l2s.sh BSC)
|
||||
if [[ ${#CHAIN_FILTER[@]} -eq 0 && ${#PARSE_CHAIN_FILTER_REMAINING[@]} -eq 1 ]]; then
|
||||
n="$(normalize_chain_name "${PARSE_CHAIN_FILTER_REMAINING[0]}")"
|
||||
[[ -n "$n" ]] && CHAIN_FILTER=("$n")
|
||||
fi
|
||||
|
||||
get_rpc() { local n="$1"; case "$n" in BSC) echo "${BSC_RPC_URL:-}";; POLYGON) echo "${POLYGON_MAINNET_RPC:-}";; BASE) echo "${BASE_MAINNET_RPC:-}";; OPTIMISM) echo "${OPTIMISM_MAINNET_RPC:-}";; ARBITRUM) echo "${ARBITRUM_MAINNET_RPC:-}";; AVALANCHE) echo "${AVALANCHE_RPC_URL:-}";; CRONOS) echo "${CRONOS_RPC_URL:-}";; GNOSIS) echo "${GNOSIS_MAINNET_RPC:-}";; *) echo "";; esac; }
|
||||
get_weth() { local n="$1"; local v="${n}_WETH_ADDRESS"; if [[ -n "${!v:-}" ]]; then echo "${!v}"; return; fi; case "$n" in BSC) echo "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";; POLYGON) echo "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270";; BASE) echo "0x4200000000000000000000000000000000000006";; OPTIMISM) echo "0x4200000000000000000000000000000000000006";; ARBITRUM) echo "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1";; AVALANCHE) echo "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7";; CRONOS) echo "0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23";; GNOSIS) echo "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d";; *) echo "";; esac; }
|
||||
get_chain_id() { case "$1" in BSC) echo 56;; POLYGON) echo 137;; BASE) echo 8453;; OPTIMISM) echo 10;; ARBITRUM) echo 42161;; AVALANCHE) echo 43114;; CRONOS) echo 25;; GNOSIS) echo 100;; *) echo 0;; esac; }
|
||||
|
||||
for name in BSC POLYGON BASE OPTIMISM ARBITRUM AVALANCHE CRONOS GNOSIS; do
|
||||
if [[ ${#CHAIN_FILTER[@]} -gt 0 ]] && [[ ! " ${CHAIN_FILTER[*]} " =~ " $name " ]]; then continue; fi
|
||||
rpc="$(get_rpc "$name")"
|
||||
if [[ -z "$rpc" ]]; then echo "Skip $name: RPC not set"; continue; fi
|
||||
weth="$(get_weth "$name")"
|
||||
chain_id="$(get_chain_id "$name")"
|
||||
echo "=== Deploying Trustless stack on $name (chain $chain_id) ==="
|
||||
TRUSTLESS_WETH_ADDRESS="$weth" TRUSTLESS_DEPLOY_LOCKBOX="${TRUSTLESS_DEPLOY_LOCKBOX:-0}" \
|
||||
forge script script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge \
|
||||
--rpc-url "$rpc" --chain-id "$chain_id" --broadcast --private-key "$PRIVATE_KEY" --slow -vvv || true
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "Done. Update .env with BondManager, ChallengeManager, LiquidityPool, Inbox (and Lockbox) per chain."
|
||||
74
scripts/deployment/deploy-vault-system-and-ac-vdc-sdc.sh
Executable file
74
scripts/deployment/deploy-vault-system-and-ac-vdc-sdc.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy Vault System, then ac* / vdc* / sdc* vaults (DeployAcVdcSdcVaults).
|
||||
# Run from a host that can reach Chain 138 RPC (e.g. on same LAN as 192.168.11.211).
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
RPC_URL="${RPC_URL_138:-http://192.168.11.211:8545}"
|
||||
GAS_PRICE="${GAS_PRICE:-1000000000}"
|
||||
CHAIN_ID="${CHAIN_ID:-138}"
|
||||
|
||||
if [ -z "$PRIVATE_KEY" ]; then
|
||||
echo "Error: PRIVATE_KEY not set (e.g. in smom-dbis-138/.env)"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "$PRIVATE_KEY" =~ ^0x ]]; then
|
||||
export PRIVATE_KEY="0x$PRIVATE_KEY"
|
||||
fi
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "1. Deploy Vault System (DeployVaultSystem.s.sol)"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "RPC: $RPC_URL Chain: $CHAIN_ID Gas: $GAS_PRICE"
|
||||
echo ""
|
||||
|
||||
forge script script/deploy/vault/DeployVaultSystem.s.sol:DeployVaultSystem \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--broadcast \
|
||||
--with-gas-price "$GAS_PRICE"
|
||||
|
||||
# Resolve VaultFactory address from broadcast (last contract creation)
|
||||
RUN_JSON=""
|
||||
for candidate in \
|
||||
"broadcast/DeployVaultSystem.s.sol/$CHAIN_ID/run-latest.json" \
|
||||
"broadcast/vault/DeployVaultSystem.s.sol/$CHAIN_ID/run-latest.json" \
|
||||
"broadcast/script/deploy/vault/DeployVaultSystem.s.sol/$CHAIN_ID/run-latest.json"; do
|
||||
if [ -f "$candidate" ]; then
|
||||
RUN_JSON="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "$RUN_JSON" ] || [ ! -f "$RUN_JSON" ]; then
|
||||
echo "Could not find broadcast file. Set VAULT_FACTORY_ADDRESS manually and run:"
|
||||
echo " VAULT_FACTORY_ADDRESS=0x... forge script script/deploy/vault/DeployAcVdcSdcVaults.s.sol:DeployAcVdcSdcVaults --rpc-url \$RPC_URL_138 --broadcast --with-gas-price 1000000000"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VAULT_FACTORY_ADDRESS=$(jq -r '[.transactions[] | select(.contractAddress != null) | .contractAddress] | last' "$RUN_JSON")
|
||||
if [ -z "$VAULT_FACTORY_ADDRESS" ] || [ "$VAULT_FACTORY_ADDRESS" = "null" ]; then
|
||||
echo "Could not parse Vault Factory address from $RUN_JSON. Set VAULT_FACTORY_ADDRESS and run DeployAcVdcSdcVaults manually."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export VAULT_FACTORY_ADDRESS
|
||||
echo ""
|
||||
echo "Vault Factory address: $VAULT_FACTORY_ADDRESS"
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "2. Deploy ac* / vdc* / sdc* (DeployAcVdcSdcVaults.s.sol)"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Optional: set CUSDC_ADDRESS_138, CUSDT_ADDRESS_138 (or COMPLIANT_USDC_ADDRESS, COMPLIANT_USDT_ADDRESS) to create vaults for those tokens."
|
||||
echo ""
|
||||
|
||||
forge script script/deploy/vault/DeployAcVdcSdcVaults.s.sol:DeployAcVdcSdcVaults \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--broadcast \
|
||||
--with-gas-price "$GAS_PRICE"
|
||||
|
||||
echo ""
|
||||
echo "Done. Record Vault Factory and any new vault/deposit/debt token addresses in .env and config/smart-contracts-master.json if needed."
|
||||
83
scripts/deployment/ensure-prerequisites.sh
Executable file
83
scripts/deployment/ensure-prerequisites.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
# Ensure prerequisites for: LINK funding, PMM (Chain 138), CCIPLogger deploy.
|
||||
# Run from repo root (proxmox) or smom-dbis-138. Fixes what can be automated and reports the rest.
|
||||
# Usage: ./scripts/deployment/ensure-prerequisites.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# PROJECT_ROOT = smom-dbis-138
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
ok() { echo -e "${GREEN}✓${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}⚠${NC} $1"; }
|
||||
fail() { echo -e "${RED}✗${NC} $1"; }
|
||||
|
||||
echo "=== Prerequisites (LINK funding, PMM, CCIPLogger) ==="
|
||||
echo ""
|
||||
|
||||
# 1) .env
|
||||
if [[ ! -f "$PROJECT_ROOT/.env" ]]; then
|
||||
fail ".env not found in $PROJECT_ROOT"
|
||||
exit 1
|
||||
fi
|
||||
ok ".env exists"
|
||||
set -a
|
||||
source "$PROJECT_ROOT/.env" 2>/dev/null || true
|
||||
set +a
|
||||
|
||||
[[ -z "${PRIVATE_KEY:-}" ]] && fail "PRIVATE_KEY not set in .env" || ok "PRIVATE_KEY set"
|
||||
[[ -z "${RPC_URL_138:-}" ]] && warn "RPC_URL_138 not set" || ok "RPC_URL_138 set"
|
||||
|
||||
# 2) npm install in smom-dbis-138 (for Hardhat / CCIPLogger)
|
||||
echo ""
|
||||
echo "--- Dependencies (CCIPLogger / Hardhat) ---"
|
||||
if [[ -f "$PROJECT_ROOT/package.json" ]]; then
|
||||
if [[ ! -d "$PROJECT_ROOT/node_modules/hardhat" ]]; then
|
||||
warn "Hardhat not found in node_modules. Running: npm install --legacy-peer-deps"
|
||||
npm install --legacy-peer-deps 2>/dev/null || true
|
||||
fi
|
||||
if [[ -d "$PROJECT_ROOT/node_modules/hardhat" ]]; then
|
||||
ok "Hardhat available (node_modules)"
|
||||
else
|
||||
warn "Hardhat still missing; run from $PROJECT_ROOT: npm install --legacy-peer-deps"
|
||||
fi
|
||||
else
|
||||
warn "No package.json in $PROJECT_ROOT"
|
||||
fi
|
||||
|
||||
# 3) LINK funding prereqs
|
||||
echo ""
|
||||
echo "--- LINK funding ---"
|
||||
[[ -z "${LINK_TOKEN_CHAIN138:-${LINK_TOKEN:-}}" ]] && warn "LINK_TOKEN_CHAIN138/LINK_TOKEN not set" || ok "Chain 138 LINK token set"
|
||||
[[ -z "${CCIPWETH9_BRIDGE_CHAIN138:-}" ]] && warn "CCIPWETH9_BRIDGE_CHAIN138 not set" || ok "CCIPWETH9_BRIDGE_CHAIN138 set"
|
||||
[[ -z "${MAINNET_CCIP_WETH9_BRIDGE:-}" ]] && warn "MAINNET_CCIP_WETH9_BRIDGE not set" || ok "Mainnet bridge vars set"
|
||||
echo " Deployer must have LINK on each chain. Run: scripts/deployment/fund-ccip-bridges-with-link.sh (use DRY_RUN=1 first)."
|
||||
|
||||
# 4) PMM prereqs
|
||||
echo ""
|
||||
echo "--- PMM (Chain 138) ---"
|
||||
if [[ -z "${DODO_VENDING_MACHINE_ADDRESS:-}" || "${DODO_VENDING_MACHINE_ADDRESS}" =~ ^0x?0*$ ]]; then
|
||||
warn "DODO_VENDING_MACHINE_ADDRESS not set. Set to DODO DVM factory on Chain 138 to run PMM (see docs/deployment/ALL_MAINNETS_DEPLOYMENT_RUNBOOK.md)."
|
||||
else
|
||||
ok "DODO_VENDING_MACHINE_ADDRESS set"
|
||||
fi
|
||||
[[ -z "${COMPLIANT_USDT_ADDRESS:-}" ]] && warn "COMPLIANT_USDT_ADDRESS not set" || ok "COMPLIANT_USDT_ADDRESS set"
|
||||
[[ -z "${COMPLIANT_USDC_ADDRESS:-}" ]] && warn "COMPLIANT_USDC_ADDRESS not set" || ok "COMPLIANT_USDC_ADDRESS set"
|
||||
[[ -z "${OFFICIAL_USDT_ADDRESS:-}" ]] && warn "OFFICIAL_USDT_ADDRESS not set" || ok "OFFICIAL_USDT_ADDRESS set"
|
||||
[[ -z "${OFFICIAL_USDC_ADDRESS:-}" ]] && warn "OFFICIAL_USDC_ADDRESS not set" || ok "OFFICIAL_USDC_ADDRESS set"
|
||||
echo " Then run: scripts/deployment/run-pmm-and-pools.sh"
|
||||
|
||||
# 5) CCIPLogger
|
||||
echo ""
|
||||
echo "--- CCIPLogger ---"
|
||||
echo " Optional. From $PROJECT_ROOT run: scripts/deployment/deploy-ccip-logger-all-chains.sh"
|
||||
echo " If Hardhat compile fails (e.g. missing @emoney/interfaces), fix deps or skip CCIPLogger."
|
||||
echo ""
|
||||
echo "=== Done. Address any ⚠ items above, then run the task scripts. ==="
|
||||
56
scripts/deployment/export-cronos-verification-sources.sh
Executable file
56
scripts/deployment/export-cronos-verification-sources.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# Export flattened Solidity source for Cronos manual verification.
|
||||
# Paste each file at https://explorer.cronos.org/verifyContract
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
OUT_DIR="$PROJECT_ROOT/.cronos-verify"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
CONTRACTS=(
|
||||
"contracts/tokens/WETH.sol:WETH"
|
||||
"contracts/tokens/WETH10.sol:WETH10"
|
||||
"contracts/ccip/CCIPWETH9Bridge.sol:CCIPWETH9Bridge"
|
||||
"contracts/ccip/CCIPWETH10Bridge.sol:CCIPWETH10Bridge"
|
||||
)
|
||||
ADDRESSES=(
|
||||
"0x99B3511A2d315A497C8112C1fdd8D508d4B1E506"
|
||||
"0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6"
|
||||
"0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e"
|
||||
"0x105F8A15b819948a89153505762444Ee9f324684"
|
||||
)
|
||||
|
||||
echo "Exporting flattened source for Cronos manual verification..."
|
||||
echo ""
|
||||
|
||||
for i in "${!CONTRACTS[@]}"; do
|
||||
entry="${CONTRACTS[$i]}"
|
||||
addr="${ADDRESSES[$i]}"
|
||||
path="${entry%%:*}"
|
||||
name="${entry##*:}"
|
||||
base=$(basename "$path" .sol)
|
||||
out="$OUT_DIR/${base}_flattened.sol"
|
||||
forge flatten "$path" > "$out" 2>/dev/null
|
||||
echo " ✓ $name -> $out"
|
||||
done
|
||||
|
||||
# Export Standard JSON Input (required — includes viaIR:true)
|
||||
echo "Exporting Standard JSON Input (includes viaIR — required for bytecode match)..."
|
||||
forge verify-contract "${ADDRESSES[0]}" "${CONTRACTS[0]}" --chain cronos --show-standard-json-input 2>/dev/null | jq -c . > "$OUT_DIR/WETH_standard_input.json"
|
||||
forge verify-contract "${ADDRESSES[1]}" "${CONTRACTS[1]}" --chain cronos --show-standard-json-input 2>/dev/null | jq -c . > "$OUT_DIR/WETH10_standard_input.json"
|
||||
forge verify-contract "${ADDRESSES[2]}" "${CONTRACTS[2]}" --chain cronos --constructor-args "$(cast abi-encode 'constructor(address,address,address)' 0xE26B0A098D861d5C7d9434aD471c0572Ca6EAa67 0x99B3511A2d315A497C8112C1fdd8D508d4B1E506 0x8c80A01F461f297Df7F9DA3A4f740D7297C8Ac85)" --show-standard-json-input 2>/dev/null | jq -c . > "$OUT_DIR/CCIPWETH9Bridge_standard_input.json"
|
||||
forge verify-contract "${ADDRESSES[3]}" "${CONTRACTS[3]}" --chain cronos --constructor-args "$(cast abi-encode 'constructor(address,address,address)' 0xE26B0A098D861d5C7d9434aD471c0572Ca6EAa67 0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6 0x8c80A01F461f297Df7F9DA3A4f740D7297C8Ac85)" --show-standard-json-input 2>/dev/null | jq -c . > "$OUT_DIR/CCIPWETH10Bridge_standard_input.json"
|
||||
echo " ✓ Standard JSON files written to $OUT_DIR/*_standard_input.json"
|
||||
echo ""
|
||||
echo "IMPORTANT: Use Standard-Json-Input (not flattened source). Contracts were deployed with via_ir=true."
|
||||
echo " Flattened source produces different bytecode → Unmatched."
|
||||
echo ""
|
||||
echo "Next: https://explorer.cronos.org/verifyContract"
|
||||
echo " 1. Select 'Solidity (Standard-Json-Input)'"
|
||||
echo " 2. Upload the *_standard_input.json file for each contract"
|
||||
echo " 3. See docs/deployment/CRONOS_VERIFICATION_RUNBOOK.md"
|
||||
echo ""
|
||||
echo "Sources: $OUT_DIR/"
|
||||
57
scripts/deployment/fix-nonce-and-retry.sh
Executable file
57
scripts/deployment/fix-nonce-and-retry.sh
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
# Fix nonce mismatch by clearing broadcast/cache so Forge uses fresh on-chain nonce.
|
||||
# Usage: ./scripts/deployment/fix-nonce-and-retry.sh [--chain cronos] [--script <path>]
|
||||
# ./scripts/deployment/fix-nonce-and-retry.sh cronos # positional still supported
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
load_deployment_env
|
||||
|
||||
CHAIN=""
|
||||
SCRIPT=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--chain) CHAIN="${2:-cronos}"; shift 2 ;;
|
||||
--script) SCRIPT="${2:-script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge}"; shift 2 ;;
|
||||
*) if [[ -z "$CHAIN" ]]; then CHAIN="$1"; elif [[ -z "$SCRIPT" ]]; then SCRIPT="$1"; fi; shift ;;
|
||||
esac
|
||||
done
|
||||
CHAIN="${CHAIN:-cronos}"
|
||||
SCRIPT="${SCRIPT:-script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge}"
|
||||
|
||||
case "$(echo "$CHAIN" | tr '[:upper:]' '[:lower:]')" in
|
||||
cronos) RPC="${CRONOS_RPC_URL:-https://evm.cronos.org}"; CHAIN_ID=25 ;;
|
||||
chain138) RPC="${RPC_URL_138:-${CHAIN_138_RPC_URL:-}}"; CHAIN_ID=138 ;;
|
||||
bsc) RPC="${BSC_RPC_URL:-}"; CHAIN_ID=56 ;;
|
||||
polygon) RPC="${POLYGON_MAINNET_RPC:-}"; CHAIN_ID=137 ;;
|
||||
base) RPC="${BASE_MAINNET_RPC:-}"; CHAIN_ID=8453 ;;
|
||||
optimism) RPC="${OPTIMISM_MAINNET_RPC:-}"; CHAIN_ID=10 ;;
|
||||
arbitrum) RPC="${ARBITRUM_MAINNET_RPC:-}"; CHAIN_ID=42161 ;;
|
||||
avalanche) RPC="${AVALANCHE_RPC_URL:-}"; CHAIN_ID=43114 ;;
|
||||
gnosis) RPC="${GNOSIS_MAINNET_RPC:-}"; CHAIN_ID=100 ;;
|
||||
*) echo "Unknown chain: $CHAIN (use: cronos, chain138, bsc, polygon, base, optimism, arbitrum, avalanche, gnosis)"; exit 1 ;;
|
||||
esac
|
||||
if [[ -z "$RPC" ]]; then echo "RPC not set for $CHAIN"; exit 1; fi
|
||||
|
||||
DEPLOYER=$(cast wallet address --private-key "$PRIVATE_KEY" 2>/dev/null || true)
|
||||
NONCE=$(cast nonce "$DEPLOYER" --rpc-url "$RPC" 2>/dev/null || echo "0")
|
||||
echo "Deployer: $DEPLOYER"
|
||||
echo "Current on-chain nonce: $NONCE"
|
||||
echo "RPC: $RPC"
|
||||
echo ""
|
||||
|
||||
# Clear broadcast cache so Forge fetches fresh nonce
|
||||
CACHE_DIR="$PROJECT_ROOT/cache"
|
||||
BROADCAST_DIR="$PROJECT_ROOT/broadcast"
|
||||
SCRIPT_PATH="${SCRIPT%%:*}"
|
||||
rm -rf "$CACHE_DIR/$SCRIPT_PATH/$CHAIN_ID" 2>/dev/null || true
|
||||
rm -rf "$BROADCAST_DIR/$SCRIPT_PATH/$CHAIN_ID" 2>/dev/null || true
|
||||
echo "Cleared cache for $SCRIPT_PATH on chain $CHAIN_ID"
|
||||
|
||||
echo ""
|
||||
echo "Run deployment (use --slow to avoid nonce gaps):"
|
||||
echo " forge script $SCRIPT --rpc-url \"$RPC\" --chain-id $CHAIN_ID --broadcast --private-key \"\$PRIVATE_KEY\" --slow"
|
||||
echo ""
|
||||
91
scripts/deployment/fund-ccip-bridges-with-link.sh
Executable file
91
scripts/deployment/fund-ccip-bridges-with-link.sh
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
# Fund all CCIP WETH9/WETH10 bridge contracts with LINK on each chain.
|
||||
# Amount via tag (not .env): --link <amount> (default 10 LINK), --dry-run to print commands only.
|
||||
# Usage: ./scripts/deployment/fund-ccip-bridges-with-link.sh [--link 10] [--dry-run]
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
source "$SCRIPT_DIR/../lib/deployment/prompts.sh"
|
||||
load_deployment_env
|
||||
parse_link_tags "$@"
|
||||
|
||||
[[ -f "$SCRIPT_DIR/../lib/infura.sh" ]] && source "$SCRIPT_DIR/../lib/infura.sh" 2>/dev/null || true
|
||||
[[ -n "${PRIVATE_KEY:-}" && ! "$PRIVATE_KEY" =~ ^0x ]] && PRIVATE_KEY="0x$PRIVATE_KEY"
|
||||
|
||||
run_or_echo() {
|
||||
if [[ "${DRY_RUN:-0}" = "1" ]]; then
|
||||
echo " [DRY RUN] $*"
|
||||
else
|
||||
if eval "$*"; then
|
||||
echo " OK"
|
||||
else
|
||||
echo " Failed (non-fatal)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_rpc() { local rpc="$1"; type ensure_infura_rpc_url &>/dev/null && [[ -n "$rpc" ]] && rpc=$(ensure_infura_rpc_url "$rpc"); echo "$rpc"; }
|
||||
|
||||
if [[ -z "$PRIVATE_KEY" ]]; then
|
||||
echo "ERROR: PRIVATE_KEY not set" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Funding CCIP bridges with LINK (amount per bridge: $LINK_AMOUNT_WEI wei)"
|
||||
echo ""
|
||||
|
||||
# Chain 138
|
||||
if [[ -n "${RPC_URL_138:-}" && -n "${LINK_TOKEN_CHAIN138:-${LINK_TOKEN:-}}" ]]; then
|
||||
link="${LINK_TOKEN_CHAIN138:-$LINK_TOKEN}"
|
||||
rpc=$(ensure_rpc "$RPC_URL_138")
|
||||
echo "Chain 138 (RPC: ${rpc%%\?*}...)"
|
||||
[[ -n "${CCIPWETH9_BRIDGE_CHAIN138:-}" ]] && run_or_echo "cast send $link \"transfer(address,uint256)\" $CCIPWETH9_BRIDGE_CHAIN138 $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy"
|
||||
[[ -n "${CCIPWETH10_BRIDGE_CHAIN138:-}" ]] && run_or_echo "cast send $link \"transfer(address,uint256)\" $CCIPWETH10_BRIDGE_CHAIN138 $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Ethereum
|
||||
if [[ -n "${ETHEREUM_MAINNET_RPC:-}" && -n "${MAINNET_LINK_TOKEN:-${CCIP_ETH_LINK_TOKEN:-}}" ]]; then
|
||||
link="${MAINNET_LINK_TOKEN:-$CCIP_ETH_LINK_TOKEN}"
|
||||
rpc=$(ensure_rpc "$ETHEREUM_MAINNET_RPC")
|
||||
echo "Ethereum Mainnet"
|
||||
[[ -n "${MAINNET_CCIP_WETH9_BRIDGE:-}" ]] && run_or_echo "cast send $link \"transfer(address,uint256)\" $MAINNET_CCIP_WETH9_BRIDGE $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy"
|
||||
[[ -n "${MAINNET_CCIP_WETH10_BRIDGE:-}" ]] && run_or_echo "cast send $link \"transfer(address,uint256)\" $MAINNET_CCIP_WETH10_BRIDGE $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# BSC, Polygon, Base, Optimism, Arbitrum, Avalanche, Cronos, Gnosis, Celo
|
||||
for label in BSC POLYGON BASE OPTIMISM ARBITRUM AVALANCHE CRONOS GNOSIS CELO; do
|
||||
case "$label" in
|
||||
BSC) rpc_var="BSC_RPC_URL"; link_var="CCIP_BSC_LINK_TOKEN"; ;;
|
||||
POLYGON) rpc_var="POLYGON_MAINNET_RPC"; link_var="CCIP_POLYGON_LINK_TOKEN"; ;;
|
||||
BASE) rpc_var="BASE_MAINNET_RPC"; link_var="CCIP_BASE_LINK_TOKEN"; ;;
|
||||
OPTIMISM) rpc_var="OPTIMISM_MAINNET_RPC"; link_var="CCIP_OPTIMISM_LINK_TOKEN"; ;;
|
||||
ARBITRUM) rpc_var="ARBITRUM_MAINNET_RPC"; link_var="CCIP_ARBITRUM_LINK_TOKEN"; ;;
|
||||
AVALANCHE) rpc_var="AVALANCHE_RPC_URL"; link_var="CCIP_AVALANCHE_LINK_TOKEN"; ;;
|
||||
CRONOS) rpc_var="CRONOS_RPC_URL"; link_var="CCIP_CRONOS_LINK_TOKEN"; rpc_fb="CRONOS_RPC"; link_fb="LINK_TOKEN_CRONOS"; ;;
|
||||
GNOSIS) rpc_var="GNOSIS_MAINNET_RPC"; link_var="CCIP_GNOSIS_LINK_TOKEN"; rpc_fb="GNOSIS_RPC"; link_fb="LINK_TOKEN_GNOSIS"; ;;
|
||||
CELO) rpc_var="CELO_MAINNET_RPC"; link_var="CCIP_CELO_LINK_TOKEN"; rpc_fb="CELO_RPC"; link_fb="LINK_TOKEN_CELO"; ;;
|
||||
esac
|
||||
rpc="${!rpc_var:-${!rpc_fb:-}}"
|
||||
link="${!link_var:-${!link_fb:-}}"
|
||||
rpc=$(ensure_rpc "$rpc")
|
||||
[[ -z "$rpc" || -z "$link" ]] && continue
|
||||
|
||||
bridge9_var="CCIPWETH9_BRIDGE_${label}"
|
||||
bridge10_var="CCIPWETH10_BRIDGE_${label}"
|
||||
addr9="${!bridge9_var:-}"
|
||||
addr10="${!bridge10_var:-}"
|
||||
[[ -z "$addr9" && -z "$addr10" ]] && continue
|
||||
|
||||
echo "$label"
|
||||
[[ -n "$addr9" ]] && run_or_echo "cast send $link \"transfer(address,uint256)\" $addr9 $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy"
|
||||
[[ -n "$addr10" ]] && run_or_echo "cast send $link \"transfer(address,uint256)\" $addr10 $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy"
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "Done. Use --link <amount> and --dry-run to adjust."
|
||||
49
scripts/deployment/fund-mainnet-lp.sh
Executable file
49
scripts/deployment/fund-mainnet-lp.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# Fund the mainnet LiquidityPoolETH with ETH and/or WETH (G4).
|
||||
# Uses .env for PRIVATE_KEY, LIQUIDITY_POOL_ETH_MAINNET (or LIQUIDITY_POOL), ETHEREUM_MAINNET_RPC.
|
||||
# Amounts via tags (not .env): --eth <amount>, --weth <amount> (in ETH), or --eth-wei / --weth-wei.
|
||||
# If no amounts given and stdin is a TTY, prompts interactively.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/deployment/fund-mainnet-lp.sh --eth 1.5 --weth 0.5
|
||||
# ./scripts/deployment/fund-mainnet-lp.sh --eth 1
|
||||
# ./scripts/deployment/fund-mainnet-lp.sh # interactive prompt
|
||||
# ./scripts/deployment/fund-mainnet-lp.sh --dry-run # no tx, show what would be sent
|
||||
#
|
||||
# Callable from other scripts: pass same tags; or source and call run_fund_mainnet_lp "${args[@]}"
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Load deployment env and tag parsing
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
source "$SCRIPT_DIR/../lib/deployment/prompts.sh"
|
||||
load_deployment_env
|
||||
|
||||
# Parse tags; remaining args left in PARSE_FUND_TAGS_REMAINING
|
||||
parse_fund_tags "$@"
|
||||
|
||||
# Interactive if no amounts and TTY
|
||||
prompt_fund_amounts
|
||||
|
||||
if [[ "${FUND_ETH_AMOUNT_WEI:-0}" == "0" && "${FUND_WETH_AMOUNT_WEI:-0}" == "0" ]]; then
|
||||
echo "No amounts set. Use --eth <amount> and/or --weth <amount>, or run interactively."
|
||||
echo "Example: $0 --eth 1.5 --weth 0.5"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
require_fund_lp_env || exit 1
|
||||
|
||||
if [[ "${DRY_RUN:-0}" == "1" ]]; then
|
||||
echo "Dry run: would fund LP with ETH wei=$FUND_ETH_AMOUNT_WEI, WETH wei=$FUND_WETH_AMOUNT_WEI"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Funding mainnet LP at $LIQUIDITY_POOL_ETH_MAINNET (ETH wei=$FUND_ETH_AMOUNT_WEI, WETH wei=$FUND_WETH_AMOUNT_WEI)"
|
||||
FUND_ETH_AMOUNT_WEI="$FUND_ETH_AMOUNT_WEI" FUND_WETH_AMOUNT_WEI="$FUND_WETH_AMOUNT_WEI" \
|
||||
forge script script/bridge/trustless/FundMainnetLP.s.sol:FundMainnetLP \
|
||||
--rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
--broadcast \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
-vvv
|
||||
140
scripts/deployment/generate-all-adapters.sh
Executable file
140
scripts/deployment/generate-all-adapters.sh
Executable file
@@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
# Generate all chain adapters and deployment configurations
|
||||
# This script creates the complete multi-chain integration package
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
CONTRACTS_DIR="$PROJECT_ROOT/contracts/bridge/adapters"
|
||||
SCRIPTS_DIR="$PROJECT_ROOT/script/deploy/chains"
|
||||
CONFIG_DIR="$PROJECT_ROOT/config/chains"
|
||||
|
||||
echo "🚀 Generating comprehensive multi-chain adapter deployment package..."
|
||||
|
||||
# Create directory structure
|
||||
mkdir -p "$CONTRACTS_DIR"/{evm,non-evm,hyperledger}
|
||||
mkdir -p "$SCRIPTS_DIR"/{evm,non-evm,hyperledger}
|
||||
mkdir -p "$CONFIG_DIR"/{evm,non-evm,hyperledger}
|
||||
mkdir -p "$PROJECT_ROOT/services"/{firefly-bridge,cacti-bridge,fabric-bridge,indy-verifier}
|
||||
mkdir -p "$PROJECT_ROOT/docs/chains"/{evm,non-evm,hyperledger}
|
||||
|
||||
echo "✅ Directory structure created"
|
||||
|
||||
# Generate chain configuration files
|
||||
cat > "$CONFIG_DIR/SUPPORTED_CHAINS.md" << 'EOF'
|
||||
# Supported Chains - Complete List
|
||||
|
||||
## EVM Chains
|
||||
|
||||
| Chain | Chain ID | Status | Adapter | Explorer |
|
||||
|-------|----------|--------|---------|----------|
|
||||
| ChainID 138 | 138 | ✅ Live | UniversalCCIPBridge | https://explorer.d-bis.org |
|
||||
| Ethereum Mainnet | 1 | ⚠️ Deploy | EVMAdapter | https://etherscan.io |
|
||||
| Polygon | 137 | ⚠️ Deploy | EVMAdapter | https://polygonscan.com |
|
||||
| Arbitrum | 42161 | ⚠️ Deploy | EVMAdapter | https://arbiscan.io |
|
||||
| Optimism | 10 | ⚠️ Deploy | EVMAdapter | https://optimistic.etherscan.io |
|
||||
| Base | 8453 | ⚠️ Deploy | EVMAdapter | https://basescan.org |
|
||||
| Avalanche | 43114 | ⚠️ Deploy | EVMAdapter | https://snowtrace.io |
|
||||
| BSC | 56 | ⚠️ Deploy | EVMAdapter | https://bscscan.com |
|
||||
| XDC Network | 50 | ⚠️ Deploy | XDCAdapter | https://explorer.xdc.network |
|
||||
| ALL Mainnet | 651940 | ⚠️ Deploy | AlltraAdapter | https://alltra.global |
|
||||
|
||||
## Non-EVM Chains
|
||||
|
||||
| Chain | Type | Status | Adapter | Explorer |
|
||||
|-------|------|--------|---------|----------|
|
||||
| XRP Ledger | XRPL | ⚠️ Deploy | XRPLAdapter | https://xrpscan.com |
|
||||
| Stellar | Stellar | 🔨 Plan | StellarAdapter | https://stellarchain.io |
|
||||
| Algorand | Algorand | 🔨 Plan | AlgorandAdapter | https://algoexplorer.io |
|
||||
| Hedera | Hashgraph | 🔨 Plan | HederaAdapter | https://hashscan.io |
|
||||
| Tron | Tron | 🔨 Plan | TronAdapter | https://tronscan.org |
|
||||
| TON | TON | 🔨 Plan | TONAdapter | https://tonscan.org |
|
||||
| Cosmos Hub | Cosmos | 🔨 Plan | CosmosAdapter | https://mintscan.io |
|
||||
| Solana | Solana | 🔨 Plan | SolanaAdapter | https://solscan.io |
|
||||
|
||||
## Hyperledger Enterprise
|
||||
|
||||
| Framework | Type | Status | Adapter | Nodes |
|
||||
|-----------|------|--------|---------|-------|
|
||||
| Firefly | Orchestration | ✅ Deployed | FireflyAdapter | VMID 6202, 6203 |
|
||||
| Cacti | Interoperability | ✅ Deployed | CactiAdapter | VMID 5201 |
|
||||
| Fabric | Permissioned | 🔨 Plan | FabricAdapter | TBD |
|
||||
| Indy | Identity | 🔨 Plan | IndyVerifier | TBD |
|
||||
|
||||
## Legend
|
||||
- ✅ Live: Fully deployed and operational
|
||||
- ⚠️ Deploy: Code ready, needs deployment
|
||||
- 🔨 Plan: Design phase, implementation needed
|
||||
EOF
|
||||
|
||||
echo "✅ Chain configuration documentation created"
|
||||
|
||||
# Create deployment orchestrator script
|
||||
cat > "$PROJECT_ROOT/scripts/deployment/deploy-all-chains.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
# Deploy Universal Bridge to all supported chains
|
||||
# This script orchestrates deployment across all chains
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
source "$PROJECT_ROOT/.env" 2>/dev/null || true
|
||||
|
||||
# Chain configurations
|
||||
declare -A EVM_CHAINS=(
|
||||
["1"]="Ethereum Mainnet"
|
||||
["137"]="Polygon"
|
||||
["42161"]="Arbitrum"
|
||||
["10"]="Optimism"
|
||||
["8453"]="Base"
|
||||
["43114"]="Avalanche"
|
||||
["56"]="BSC"
|
||||
["50"]="XDC Network"
|
||||
)
|
||||
|
||||
# Deployment function
|
||||
deploy_chain() {
|
||||
local chain_id=$1
|
||||
local chain_name=$2
|
||||
|
||||
echo "📦 Deploying to $chain_name (Chain ID: $chain_id)..."
|
||||
|
||||
# Run deployment script for this chain
|
||||
if [ -f "$PROJECT_ROOT/script/deploy/chains/evm/deploy-chain-$chain_id.s.sol" ]; then
|
||||
forge script "script/deploy/chains/evm/deploy-chain-$chain_id.s.sol:DeployChain" \
|
||||
--rpc-url "${RPC_URLS[$chain_id]}" \
|
||||
--broadcast \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--verify || echo "⚠️ Deployment failed for $chain_name"
|
||||
else
|
||||
echo "⚠️ Deployment script not found for $chain_name"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main deployment loop
|
||||
echo "🚀 Starting multi-chain deployment..."
|
||||
echo ""
|
||||
|
||||
for chain_id in "${!EVM_CHAINS[@]}"; do
|
||||
deploy_chain "$chain_id" "${EVM_CHAINS[$chain_id]}"
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "✅ Multi-chain deployment complete!"
|
||||
EOF
|
||||
|
||||
chmod +x "$PROJECT_ROOT/scripts/deployment/deploy-all-chains.sh"
|
||||
|
||||
echo "✅ Deployment orchestrator script created"
|
||||
|
||||
echo ""
|
||||
echo "🎉 Multi-chain adapter generation complete!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Review generated adapters in: $CONTRACTS_DIR"
|
||||
echo "2. Configure chain RPC endpoints in: $CONFIG_DIR"
|
||||
echo "3. Run deployment: ./scripts/deployment/deploy-all-chains.sh"
|
||||
echo "4. Configure admin dashboard with new chains"
|
||||
236
scripts/deployment/list-deployer-tokens-all-networks.sh
Executable file
236
scripts/deployment/list-deployer-tokens-all-networks.sh
Executable file
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env bash
|
||||
# List all tokens in the deployer wallet across all networks.
|
||||
# Token categories (see docs/11-references/TOKEN_CATEGORIES_CANONICAL.md):
|
||||
# 1. Canonical 138 Compliant: Native ETH, WETH, WETH10, LINK, cUSDT, cUSDC, cEURT, cEURC, cGBPT, cGBPC, cAUDT, cAUDC, cJPYT, cJPYC, cCHFT, cCHFC, cCADT, cCADC, cAUSDT
|
||||
# 2. ALL Mainnet (Alltra): Native, AUSDT, USDT, USDC, WETH, WALL
|
||||
# 3. Compliant Wrapped (cW*): cWUSDT, cWUSDC, cWEURT, cWEURC, ... (per public chain)
|
||||
# 4. D-WIN W Tokens: USDW, EURW, GBPW, AUDW, JPYW, CHFW, CADW (Cronos §4)
|
||||
# This script lists (1) Chain 138, (2) ALL Mainnet, (4) Cronos D-WIN W, plus Ethereum/Polygon/Base/Optimism/BSC/Avalanche/Arbitrum.
|
||||
# Uses PRIVATE_KEY or DEPLOYER_ADDRESS; falls back to public RPCs when env RPC vars unset.
|
||||
#
|
||||
# Usage: ./scripts/deployment/list-deployer-tokens-all-networks.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Deployer: derive from PRIVATE_KEY or use DEPLOYER_ADDRESS if set (read-only mode)
|
||||
if [ -n "${DEPLOYER_ADDRESS:-}" ]; then
|
||||
DEPLOYER="${DEPLOYER_ADDRESS}"
|
||||
[[ "$DEPLOYER" != 0x* ]] && DEPLOYER="0x$DEPLOYER"
|
||||
else
|
||||
if [ -z "${PRIVATE_KEY:-}" ]; then
|
||||
echo "ERROR: Set PRIVATE_KEY in .env or DEPLOYER_ADDRESS=0x4A666F96fC8764181194447A7dFdb7d471b301C8 for read-only"
|
||||
exit 1
|
||||
fi
|
||||
DEPLOYER=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || true)
|
||||
if [ -z "$DEPLOYER" ]; then
|
||||
echo "ERROR: Could not derive deployer address (is 'cast' available?)"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Format raw balance with decimals (divide by 10^decimals). Uses cast when decimals=18.
|
||||
format_balance() {
|
||||
local raw="$1"
|
||||
local decimals="${2:-18}"
|
||||
if [ -z "$raw" ] || [ "$raw" = "0" ]; then
|
||||
echo "0"
|
||||
return
|
||||
fi
|
||||
if [ "$decimals" = "18" ]; then
|
||||
cast --to-unit "$raw" ether 2>/dev/null || echo "$raw"
|
||||
return
|
||||
fi
|
||||
# bc: 10^decimals (e.g. 10^6 for USDC)
|
||||
echo "scale=12; $raw / 10^$decimals" | bc 2>/dev/null | sed 's/^\./0./;s/0*$//;s/\.$//' || echo "$raw"
|
||||
}
|
||||
|
||||
# Fetch ERC-20 balance and decimals, print " SYMBOL: balance"
|
||||
token_balance_line() {
|
||||
local rpc="$1"
|
||||
local token_addr="$2"
|
||||
local symbol="$3"
|
||||
local decimals_override="${4:-}"
|
||||
local bal_hex
|
||||
bal_hex=$(cast call "$token_addr" "balanceOf(address)(uint256)" "$DEPLOYER" --rpc-url "$rpc" 2>/dev/null || echo "0x0")
|
||||
local bal_raw
|
||||
bal_raw=$(cast --to-dec "$bal_hex" 2>/dev/null || echo "0")
|
||||
if [ -z "$decimals_override" ]; then
|
||||
decimals_override=$(cast call "$token_addr" "decimals()(uint8)" --rpc-url "$rpc" 2>/dev/null | cast --to-dec 2>/dev/null || echo "18")
|
||||
fi
|
||||
local disp
|
||||
disp=$(format_balance "$bal_raw" "$decimals_override")
|
||||
printf " %-8s %s\n" "$symbol:" "$disp"
|
||||
}
|
||||
|
||||
# Report one network: native + optional ERC-20 list (name, rpc, chain_id, native_symbol, "addr:symbol:decimals ...")
|
||||
report_network() {
|
||||
local name="$1"
|
||||
local rpc="$2"
|
||||
local chain_id="$3"
|
||||
local native_sym="$4"
|
||||
local token_list="$5"
|
||||
|
||||
echo ""
|
||||
echo "=== $name (chain $chain_id) ==="
|
||||
if [ -z "$rpc" ]; then
|
||||
echo " (no RPC configured)"
|
||||
return
|
||||
fi
|
||||
local native_wei
|
||||
native_wei=$(cast balance "$DEPLOYER" --rpc-url "$rpc" 2>/dev/null || echo "0")
|
||||
local native_disp
|
||||
native_disp=$(cast --to-unit "$native_wei" ether 2>/dev/null || echo "0")
|
||||
echo " Native ($native_sym): $native_disp"
|
||||
|
||||
local entry addr rest sym dec
|
||||
for entry in $token_list; do
|
||||
entry=$(echo "$entry" | tr -d '[:space:]')
|
||||
[ -z "$entry" ] && continue
|
||||
addr="${entry%%:*}"
|
||||
rest="${entry#*:}"
|
||||
sym="${rest%%:*}"
|
||||
dec="${rest#*:}"
|
||||
[ "$dec" = "$rest" ] && dec=""
|
||||
token_balance_line "$rpc" "$addr" "$sym" "$dec"
|
||||
done
|
||||
}
|
||||
|
||||
echo "============================================"
|
||||
echo "Deployer wallet tokens (all networks)"
|
||||
echo "Deployer: $DEPLOYER"
|
||||
echo "============================================"
|
||||
|
||||
# Fallback public RPCs when env not set (so token lists are always shown)
|
||||
RPC_138="${RPC_URL_138:-https://rpc-core.d-bis.org}"
|
||||
RPC_1="${ETHEREUM_MAINNET_RPC:-https://eth.llamarpc.com}"
|
||||
RPC_651940="${CHAIN_651940_RPC:-${ALLTRA_MAINNET_RPC:-https://mainnet-rpc.alltra.global}}"
|
||||
RPC_25="${CRONOS_RPC:-${CRONOS_MAINNET_RPC:-https://evm.cronos.org}}"
|
||||
RPC_137="${POLYGON_MAINNET_RPC:-https://polygon-rpc.com}"
|
||||
RPC_8453="${BASE_MAINNET_RPC:-https://mainnet.base.org}"
|
||||
RPC_10="${OPTIMISM_MAINNET_RPC:-https://mainnet.optimism.io}"
|
||||
RPC_56="${BSC_RPC_URL:-${BSC_MAINNET_RPC:-https://bsc-dataseed.binance.org}}"
|
||||
RPC_43114="${AVALANCHE_RPC_URL:-${AVALANCHE_MAINNET_RPC:-https://api.avax.network/ext/bc/C/rpc}}"
|
||||
RPC_42161="${ARBITRUM_MAINNET_RPC:-https://arb1.arbitrum.io/rpc}"
|
||||
|
||||
# Chain 138 tokens (from CHAIN138_TOKEN_ADDRESSES)
|
||||
CHAIN138_TOKENS="
|
||||
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2:WETH:18
|
||||
0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f:WETH10:18
|
||||
0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03:LINK:18
|
||||
0x93E66202A11B1772E55407B32B44e5Cd8eda7f22:cUSDT:6
|
||||
0xf22258f57794CC8E06237084b353Ab30fFfa640b:cUSDC:6
|
||||
0x15DF1D5BFDD8Aa4b380445D4e3E9B38d34283619:USDT:6
|
||||
"
|
||||
report_network "Chain 138" "$RPC_138" "138" "ETH" "$CHAIN138_TOKENS"
|
||||
|
||||
# Ethereum Mainnet
|
||||
MAINNET_TOKENS="
|
||||
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2:WETH:18
|
||||
0xdAC17F958D2ee523a2206206994597C13D831ec7:USDT:6
|
||||
0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48:USDC:6
|
||||
0x514910771AF9Ca656af840dff83E8264EcF986CA:LINK:18
|
||||
0x6B175474E89094C44Da98b954EedeAC495271d0F:DAI:18
|
||||
"
|
||||
report_network "Ethereum Mainnet" "$RPC_1" "1" "ETH" "$MAINNET_TOKENS"
|
||||
|
||||
# ALL Mainnet (651940)
|
||||
ALLMAINNET_TOKENS="
|
||||
0x015B1897Ed5279930bC2Be46F661894d219292A6:AUSDT:18
|
||||
0x66D8Efa0AF63B0e84eb1Dd72bf00f00cd1e2234e:USDT:18
|
||||
0xa95EeD79f84E6A0151eaEb9d441F9Ffd50e8e881:USDC:18
|
||||
0x798F6762BB40d6801A593459d08F890603D3979C:WETH:18
|
||||
0x2da2b8f961F161ab6320acB3377e2e844a3C3ce4:WALL:18
|
||||
"
|
||||
report_network "ALL Mainnet (Alltra)" "$RPC_651940" "651940" "ETH" "$ALLMAINNET_TOKENS"
|
||||
|
||||
# Cronos (25)
|
||||
CRONOS_TOKENS="
|
||||
0x99B3511A2d315A497C8112C1fdd8D508d4B1E506:WETH9:18
|
||||
0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6:WETH10:18
|
||||
0x8c80A01F461f297Df7F9DA3A4f740D7297C8Ac85:LINK:18
|
||||
0x948690147D2e50ffe50C5d38C14125aD6a9FA036:USDW:2
|
||||
0x58a8D8F78F1B65c06dAd7542eC46b299629A60dd:EURW:2
|
||||
0xFb4B6Cc81211F7d886950158294A44C312abCA29:GBPW:2
|
||||
0xf9f5D0ACD71C76F9476F10B3F3d3E201F0883C68:AUDW:2
|
||||
0xeE17bB0322383fecCA2784fbE2d4CD7d02b1905B:JPYW:2
|
||||
0xc9750828124D4c10e7a6f4B655cA8487bD3842EB:CHFW:2
|
||||
0x328Cd365Bb35524297E68ED28c6fF2C9557d1363:CADW:2
|
||||
"
|
||||
report_network "Cronos" "$RPC_25" "25" "CRO" "$CRONOS_TOKENS"
|
||||
|
||||
# Polygon
|
||||
POLYGON_TOKENS="
|
||||
0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619:WETH:18
|
||||
0xc2132D05D31c914a87C6611C10748AEb04B58e8F:USDT:6
|
||||
0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174:USDC:6
|
||||
0xb0897686c545045aFc77CF20eA7Ee945E98F291e:LINK:18
|
||||
"
|
||||
report_network "Polygon" "$RPC_137" "137" "MATIC" "$POLYGON_TOKENS"
|
||||
|
||||
# Base
|
||||
BASE_TOKENS="
|
||||
0x4200000000000000000000000000000000000006:WETH:18
|
||||
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913:USDC:6
|
||||
0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb:DAI:18
|
||||
"
|
||||
report_network "Base" "$RPC_8453" "8453" "ETH" "$BASE_TOKENS"
|
||||
|
||||
# Optimism
|
||||
OPTIMISM_TOKENS="
|
||||
0x4200000000000000000000000000000000000006:WETH:18
|
||||
0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85:USDC:6
|
||||
0x94b008aA00579c1307B0EF2c499aD98a8ce58e58:USDT:6
|
||||
"
|
||||
report_network "Optimism" "$RPC_10" "10" "ETH" "$OPTIMISM_TOKENS"
|
||||
|
||||
# BSC (56)
|
||||
BSC_TOKENS="
|
||||
0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173c095c:WBNB:18
|
||||
0x55d398326f99059fF775485246999027B3197955:USDT:18
|
||||
0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d:USDC:18
|
||||
0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c:BTCB:18
|
||||
"
|
||||
report_network "BSC (BNB Chain)" "$RPC_56" "56" "BNB" "$BSC_TOKENS"
|
||||
|
||||
# Avalanche C-Chain
|
||||
AVAX_TOKENS="
|
||||
0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7:WAVAX:18
|
||||
0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7:USDT:6
|
||||
0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E:USDC:6
|
||||
"
|
||||
report_network "Avalanche C-Chain" "$RPC_43114" "43114" "AVAX" "$AVAX_TOKENS"
|
||||
|
||||
# Arbitrum One
|
||||
ARBITRUM_TOKENS="
|
||||
0x82aF49447D8a07e3bd95BD0d56f35241523fBab1:WETH:18
|
||||
0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9:USDT:6
|
||||
0xaf88d065e77c8cC2239327C5EDb3A432268e5831:USDC:6
|
||||
"
|
||||
report_network "Arbitrum One" "$RPC_42161" "42161" "ETH" "$ARBITRUM_TOKENS"
|
||||
|
||||
# Sepolia (optional; no token list)
|
||||
report_network "Ethereum Sepolia" "${ETHEREUM_SEPOLIA_RPC:-}" "11155111" "ETH" ""
|
||||
|
||||
# Polygon Amoy
|
||||
report_network "Polygon Amoy" "${POLYGON_AMOY_RPC:-}" "80002" "MATIC" ""
|
||||
|
||||
# Base Sepolia
|
||||
report_network "Base Sepolia" "${BASE_SEPOLIA_RPC:-}" "84532" "ETH" ""
|
||||
|
||||
# Optimism Sepolia
|
||||
report_network "Optimism Sepolia" "${OPTIMISM_SEPOLIA_RPC:-}" "11155420" "ETH" ""
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Done. Override RPCs via .env: RPC_URL_138, ETHEREUM_MAINNET_RPC, CHAIN_651940_RPC, CRONOS_RPC, etc."
|
||||
echo "============================================"
|
||||
47
scripts/deployment/live-test-trustless-bridge.sh
Executable file
47
scripts/deployment/live-test-trustless-bridge.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
# Print cast commands for live trustless bridge test (138 -> mainnet) and optionally check LP/BondManager state.
|
||||
# Does NOT send the lock tx; you run that and capture depositId from the Deposit event.
|
||||
# Usage: ./scripts/deployment/live-test-trustless-bridge.sh [--check]
|
||||
# --check Print LP getPoolStats(0) and BondManager totalEthHeld() for mainnet.
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
[[ -f .env ]] && set -a && source .env && set +a
|
||||
|
||||
BOND_MANAGER="${BOND_MANAGER_MAINNET:-${BOND_MANAGER:-}}"
|
||||
CHALLENGE_MANAGER="${CHALLENGE_MANAGER_MAINNET:-${CHALLENGE_MANAGER:-}}"
|
||||
LIQUIDITY_POOL="${LIQUIDITY_POOL_ETH_MAINNET:-${LIQUIDITY_POOL:-}}"
|
||||
INBOX_ETH="${INBOX_ETH_MAINNET:-${INBOX_ETH:-}}"
|
||||
RPC_138="${RPC_URL_138:-${CHAIN_138_RPC_URL:-}}"
|
||||
RPC_MAINNET="${ETHEREUM_MAINNET_RPC:-}"
|
||||
|
||||
if [[ "${1:-}" == "--check" ]]; then
|
||||
echo "--- Mainnet LP ETH pool stats (AssetType 0) ---"
|
||||
cast call "$LIQUIDITY_POOL" "getPoolStats(uint8)(uint256,uint256,uint256)" 0 --rpc-url "$RPC_MAINNET" 2>/dev/null || echo " (set LIQUIDITY_POOL and ETHEREUM_MAINNET_RPC)"
|
||||
echo "--- BondManager totalEthHeld ---"
|
||||
cast call "$BOND_MANAGER" "totalEthHeld()(uint256)" --rpc-url "$RPC_MAINNET" 2>/dev/null || echo " (set BOND_MANAGER and ETHEREUM_MAINNET_RPC)"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "=== Live test commands (138 -> mainnet) ==="
|
||||
echo "Set: RECIPIENT (mainnet address), DEPOSIT_ID (from Lockbox Deposit event depositId — NOT the amount), AMOUNT_WEI (e.g. 1000000000000000 for 0.001 ether)"
|
||||
echo ""
|
||||
echo "Get DEPOSIT_ID after lock: ./scripts/deployment/run-e2e-trustless-live-test.sh get-deposit-id <LOCK_TX_HASH> # or cast logs <TX> \"Deposit(...)\" --rpc-url \$RPC_URL_138"
|
||||
echo ""
|
||||
echo "1) Lock on Chain 138 (run this; then get DEPOSIT_ID from Deposit event):"
|
||||
echo " cast send \$LOCKBOX_138 \"depositNative(address,bytes32)\" \$RECIPIENT \$(cast keccak \"live-test-\$(date +%s)\") --value 0.01ether --rpc-url \$RPC_URL_138 --private-key \$PRIVATE_KEY --legacy --gas-price \${GAS_PRICE_138:-1000000000}"
|
||||
echo ""
|
||||
echo "2) Bond for claim (run and set BOND=...):"
|
||||
echo " BOND=\$(cast call \$BOND_MANAGER \"getRequiredBond(uint256)\" \$AMOUNT_WEI --rpc-url \$ETHEREUM_MAINNET_RPC)"
|
||||
echo ""
|
||||
echo "3) Submit claim on mainnet:"
|
||||
echo " cast send \$INBOX_ETH \"submitClaim(uint256,address,uint256,address,bytes)\" \$DEPOSIT_ID 0x0000000000000000000000000000000000000000 \$AMOUNT_WEI \$RECIPIENT 0x --value \$BOND --rpc-url \$ETHEREUM_MAINNET_RPC --private-key \$PRIVATE_KEY"
|
||||
echo ""
|
||||
echo "4) After challenge window (e.g. 30 min), finalize:"
|
||||
echo " cast send \$CHALLENGE_MANAGER \"finalizeClaim(uint256)\" \$DEPOSIT_ID --rpc-url \$ETHEREUM_MAINNET_RPC --private-key \$PRIVATE_KEY # CHALLENGE_MANAGER in .env"
|
||||
echo ""
|
||||
echo "5) Release bond:"
|
||||
echo " cast send \$BOND_MANAGER \"releaseBond(uint256)\" \$DEPOSIT_ID --rpc-url \$ETHEREUM_MAINNET_RPC --private-key \$PRIVATE_KEY"
|
||||
echo ""
|
||||
echo "Full runbook: docs/bridge/trustless/DEPLOYMENT_GUIDE.md (Deploy, Configure, and Live Test section)"
|
||||
145
scripts/deployment/preflight-config-ready-chains.sh
Executable file
145
scripts/deployment/preflight-config-ready-chains.sh
Executable file
@@ -0,0 +1,145 @@
|
||||
#!/usr/bin/env bash
|
||||
# Preflight check for Config-Ready Chains (Gnosis, Cronos, Celo, Wemix) CCIP bridge deployment.
|
||||
# Verifies: RPC connectivity, deployer address, native gas balance on each chain.
|
||||
# Run before deploy-bridges-config-ready-chains.sh.
|
||||
#
|
||||
# Usage: ./scripts/deployment/preflight-config-ready-chains.sh [gnosis|cronos|celo|wemix|all]
|
||||
# SKIP_BALANCE=1 ... # skip balance checks (RPC-only)
|
||||
# DEPLOYER_ADDRESS=0x... # use specific address instead of deriving from PRIVATE_KEY
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
[[ -f "$PROJECT_ROOT/.env" ]] && set -a && source "$PROJECT_ROOT/.env" && set +a
|
||||
|
||||
SKIP_BALANCE="${SKIP_BALANCE:-0}"
|
||||
CHAIN="${1:-all}"
|
||||
|
||||
# Chain config: name | chain_id | RPC_var | gas_token | min_recommended (human)
|
||||
get_chain_config() {
|
||||
case "$1" in
|
||||
gnosis) echo "Gnosis|100|GNOSIS_RPC|xDAI|0.1" ;;
|
||||
cronos) echo "Cronos|25|CRONOS_RPC|CRO|1" ;;
|
||||
celo) echo "Celo|42220|CELO_RPC|CELO|0.1" ;;
|
||||
wemix) echo "Wemix|1111|WEMIX_RPC|WEMIX|0.4" ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Default RPCs (from env or public)
|
||||
GNOSIS_RPC="${GNOSIS_RPC:-https://rpc.gnosischain.com}"
|
||||
CRONOS_RPC="${CRONOS_RPC:-https://evm.cronos.org}"
|
||||
CELO_RPC="${CELO_RPC:-https://forno.celo.org}"
|
||||
WEMIX_RPC="${WEMIX_RPC:-https://api.wemix.com}"
|
||||
|
||||
# Deployer
|
||||
if [[ -n "${DEPLOYER_ADDRESS:-}" ]]; then
|
||||
DEPLOYER="${DEPLOYER_ADDRESS}"
|
||||
[[ "$DEPLOYER" != 0x* ]] && DEPLOYER="0x$DEPLOYER"
|
||||
else
|
||||
if [[ -z "${PRIVATE_KEY:-}" ]]; then
|
||||
echo "Error: Set PRIVATE_KEY in .env or DEPLOYER_ADDRESS for read-only check" >&2
|
||||
exit 1
|
||||
fi
|
||||
DEPLOYER=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || true)
|
||||
if [[ -z "$DEPLOYER" ]]; then
|
||||
echo "Error: Could not derive deployer from PRIVATE_KEY (is 'cast' available?)" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
check_chain() {
|
||||
local key="$1"
|
||||
local config
|
||||
config=$(get_chain_config "$key")
|
||||
[[ -z "$config" ]] && return 1
|
||||
local name chain_id rpc_var gas_token min_rec
|
||||
IFS='|' read -r name chain_id rpc_var gas_token min_rec <<< "$config"
|
||||
local rpc="${!rpc_var:-}"
|
||||
|
||||
if [[ -z "$rpc" ]]; then
|
||||
echo -e " ${RED}✗${NC} $name: $rpc_var not set in .env"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# RPC connectivity
|
||||
local res
|
||||
res=$(curl -s -m 10 -X POST "$rpc" -H "Content-Type: application/json" \
|
||||
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null || true)
|
||||
if [[ -z "$res" ]] || ! echo "$res" | grep -q '"result"'; then
|
||||
echo -e " ${RED}✗${NC} $name: RPC unreachable ($rpc)"
|
||||
return 1
|
||||
fi
|
||||
echo -e " ${GREEN}✓${NC} $name: RPC OK (chain $chain_id)"
|
||||
|
||||
if [[ "$SKIP_BALANCE" == "1" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Balance check
|
||||
local balance_wei
|
||||
balance_wei=$(cast balance "$DEPLOYER" --rpc-url "$rpc" 2>/dev/null || echo "0")
|
||||
local balance_eth
|
||||
balance_eth=$(echo "scale=6; $balance_wei / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
||||
|
||||
if [[ -z "$balance_wei" || "$balance_wei" == "0" ]]; then
|
||||
echo -e " ${RED}✗${NC} Balance: 0 $gas_token (need $min_rec $gas_token)"
|
||||
return 1
|
||||
fi
|
||||
# Compare: balance_eth >= min_rec (use bc for decimals)
|
||||
if ! command -v bc >/dev/null 2>&1; then
|
||||
echo -e " ${YELLOW}?${NC} Balance: $balance_eth $gas_token (bc not found, cannot compare)"
|
||||
return 0
|
||||
fi
|
||||
if [[ "$(echo "$balance_eth >= $min_rec" | bc 2>/dev/null)" != "1" ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Balance: $balance_eth $gas_token (recommended: $min_rec $gas_token)"
|
||||
return 1
|
||||
fi
|
||||
echo -e " ${GREEN}✓${NC} Balance: $balance_eth $gas_token"
|
||||
return 0
|
||||
}
|
||||
|
||||
run_checks() {
|
||||
local keys
|
||||
case "$CHAIN" in
|
||||
gnosis) keys="gnosis" ;;
|
||||
cronos) keys="cronos" ;;
|
||||
celo) keys="celo" ;;
|
||||
wemix) keys="wemix" ;;
|
||||
all) keys="gnosis cronos celo wemix" ;;
|
||||
*) echo "Usage: $0 [gnosis|cronos|celo|wemix|all]"; exit 1 ;;
|
||||
esac
|
||||
|
||||
local failed=0
|
||||
for k in $keys; do
|
||||
if ! check_chain "$k"; then
|
||||
failed=1
|
||||
fi
|
||||
done
|
||||
return $failed
|
||||
}
|
||||
|
||||
echo "=== Preflight: Config-Ready Chains (Gnosis, Cronos, Celo, Wemix) ==="
|
||||
echo "Deployer: ${DEPLOYER:0:10}...${DEPLOYER: -8}"
|
||||
echo "SKIP_BALANCE=$SKIP_BALANCE CHAIN=$CHAIN"
|
||||
echo ""
|
||||
|
||||
if run_checks; then
|
||||
echo ""
|
||||
echo "Preflight OK. Run: ./scripts/deployment/deploy-bridges-config-ready-chains.sh $CHAIN"
|
||||
exit 0
|
||||
else
|
||||
echo ""
|
||||
echo "Preflight failed. Fix RPCs and gas balances before deploy."
|
||||
echo " Gas tokens: Gnosis=xDAI, Cronos=CRO, Celo=CELO, Wemix=WEMIX"
|
||||
echo " Recommended: Gnosis 0.1, Cronos 1, Celo 0.1, Wemix 0.4"
|
||||
exit 1
|
||||
fi
|
||||
64
scripts/deployment/register-all-mainnet.s.sol
Normal file
64
scripts/deployment/register-all-mainnet.s.sol
Normal file
@@ -0,0 +1,64 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {ChainRegistry} from "../../contracts/registry/ChainRegistry.sol";
|
||||
|
||||
/**
|
||||
* @title RegisterAllMainnet
|
||||
* @notice Register ALL Mainnet (651940) in ChainRegistry
|
||||
* @dev Run this after deploying AlltraAdapter
|
||||
*/
|
||||
contract RegisterAllMainnet is Script {
|
||||
function run() external {
|
||||
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(deployerPrivateKey);
|
||||
|
||||
// Load environment variables
|
||||
address registryAddress = vm.envOr("CHAIN_REGISTRY_ADDRESS", address(0));
|
||||
address alltraAdapterAddress = vm.envOr("ALLTRA_ADAPTER_ADDRESS", address(0));
|
||||
|
||||
require(registryAddress != address(0), "CHAIN_REGISTRY_ADDRESS not set");
|
||||
require(alltraAdapterAddress != address(0), "ALLTRA_ADAPTER_ADDRESS not set");
|
||||
|
||||
console.log("Registering ALL Mainnet (651940) in ChainRegistry");
|
||||
console.log("Registry:", vm.toString(registryAddress));
|
||||
console.log("Adapter:", vm.toString(alltraAdapterAddress));
|
||||
|
||||
vm.startBroadcast(deployerPrivateKey);
|
||||
|
||||
ChainRegistry registry = ChainRegistry(registryAddress);
|
||||
|
||||
// Register ALL Mainnet as EVM chain
|
||||
// Parameters:
|
||||
// - chainId: 651940
|
||||
// - adapter: AlltraAdapter address
|
||||
// - explorerUrl: https://alltra.global
|
||||
// - minConfirmations: 12 (standard EVM)
|
||||
// - avgBlockTime: 2 seconds (TBD - verify actual block time)
|
||||
// - additionalData: empty (can include CCIP selector if available later)
|
||||
registry.registerEVMChain(
|
||||
651940, // chainId
|
||||
alltraAdapterAddress, // adapter
|
||||
"https://alltra.global", // explorerUrl
|
||||
12, // minConfirmations
|
||||
2, // avgBlockTime (seconds) - TODO: Verify actual block time
|
||||
"" // additionalData
|
||||
);
|
||||
|
||||
vm.stopBroadcast();
|
||||
|
||||
console.log("\n=== Registration Summary ===");
|
||||
console.log("Chain ID: 651940");
|
||||
console.log("Chain Name: ALL Mainnet");
|
||||
console.log("Adapter:", vm.toString(alltraAdapterAddress));
|
||||
console.log("Explorer: https://alltra.global");
|
||||
console.log("Min Confirmations: 12");
|
||||
console.log("Avg Block Time: 2 seconds");
|
||||
console.log("\n✅ ALL Mainnet registered successfully!");
|
||||
console.log("\nNext Steps:");
|
||||
console.log("1. Verify chain registration: cast call <REGISTRY> 'evmChains(uint256)(uint256,string,uint8,address,bool,uint256,uint256,bool,string,string,bytes)' 651940 --rpc-url <RPC>");
|
||||
console.log("2. Test adapter: Verify AlltraAdapter.getChainIdentifier() returns (651940, 'ALL-Mainnet')");
|
||||
console.log("3. Update routing services to use AlltraAdapter for chain 651940");
|
||||
}
|
||||
}
|
||||
48
scripts/deployment/run-all-deployments-parallel.sh
Executable file
48
scripts/deployment/run-all-deployments-parallel.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run all deployment tasks in parallel where possible.
|
||||
# Respects dependency order. Requires .env with PRIVATE_KEY, RPC URLs.
|
||||
# Usage: ./scripts/deployment/run-all-deployments-parallel.sh [chain]
|
||||
# chain: chain138 (default), cronos, mainnet
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
source .env 2>/dev/null || true
|
||||
CHAIN="${1:-chain138}"
|
||||
|
||||
case "$CHAIN" in
|
||||
chain138) RPC="${RPC_URL_138:-$CHAIN138_RPC_URL}"; CHAIN_ID=138 ;;
|
||||
cronos) RPC="${CRONOS_RPC_URL:-https://evm.cronos.org}"; CHAIN_ID=25 ;;
|
||||
mainnet) RPC="${ETHEREUM_MAINNET_RPC}"; CHAIN_ID=1 ;;
|
||||
*) echo "Unknown chain: $CHAIN"; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo "=== Parallel Deployment: $CHAIN (chain $CHAIN_ID) ==="
|
||||
echo "RPC: $RPC"
|
||||
echo ""
|
||||
|
||||
# Phase 1: Independent deployments (run in parallel)
|
||||
echo "Phase 1: Core (parallel)..."
|
||||
(
|
||||
forge script script/DeployMulticall.s.sol:DeployMulticall --rpc-url "$RPC" --broadcast &
|
||||
forge script script/DeployOracle.s.sol:DeployOracle --rpc-url "$RPC" --broadcast &
|
||||
wait
|
||||
) 2>&1 | tee /tmp/deploy-phase1.log || true
|
||||
|
||||
# Phase 2: Depends on Phase 1 (CREATE2 if needed for deterministic)
|
||||
echo ""
|
||||
echo "Phase 2: CREATE2Factory (if not exists)..."
|
||||
if [ -z "${CREATE2_FACTORY:-}" ] || [ "$CREATE2_FACTORY" = "0x0000000000000000000000000000000000000000" ]; then
|
||||
forge script script/Deploy.s.sol:Deploy --rpc-url "$RPC" --broadcast 2>&1 || true
|
||||
fi
|
||||
|
||||
# Phase 3: Token/Reserve (require TOKEN_FACTORY etc.)
|
||||
echo ""
|
||||
echo "Phase 3: Token systems (require existing deps)..."
|
||||
# DeployChain138, DeployISO4217WSystem, etc. — run if deps present
|
||||
|
||||
echo ""
|
||||
echo "Deployment batch complete. Check logs for any failures."
|
||||
echo "Note: Chain 138 may show 'Replacement transaction underpriced' if mempool has stuck tx."
|
||||
58
scripts/deployment/run-all-four-gaps.sh
Executable file
58
scripts/deployment/run-all-four-gaps.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run liquidity-gap tasks (G1–G4) using .env. Phase and G4 amounts via tags (not .env).
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/deployment/run-all-four-gaps.sh # run all phases (G4 interactive if no amounts)
|
||||
# ./scripts/deployment/run-all-four-gaps.sh g1 g4 # run only G1 and G4
|
||||
# ./scripts/deployment/run-all-four-gaps.sh g4 --eth 1 --weth 0.5 # G4 with amounts (no prompt)
|
||||
# ./scripts/deployment/run-all-four-gaps.sh g4 # G4 with interactive prompt
|
||||
#
|
||||
# Phases: g1 (PMM on L2s), g2g3 (Trustless + Lockbox on L2s), g4 (fund mainnet LP).
|
||||
# G4 amounts: use --eth, --weth, --eth-wei, --weth-wei (see fund-mainnet-lp.sh).
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
load_deployment_env
|
||||
DOTENV="${ENV_FILE:-$PROJECT_ROOT/.env}"
|
||||
if [[ ! -f "$DOTENV" ]]; then
|
||||
echo "No .env at $DOTENV. Create from .env.example and set PRIVATE_KEY, RPCs, token addresses. Or set ENV_FILE."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse phase tags (g1, g2g3, g4); remaining args may include G2G3 tags (--lockbox, --chain) and G4 tags (--eth, --weth)
|
||||
source "$SCRIPT_DIR/../lib/deployment/prompts.sh"
|
||||
parse_phase_tags "$@"
|
||||
REMAINING=("${PARSE_PHASE_TAGS_REMAINING[@]}")
|
||||
parse_lockbox_tag "${REMAINING[@]}"
|
||||
parse_chain_filter "${PARSE_LOCKBOX_REMAINING[@]}"
|
||||
G4_ARGS=("${PARSE_CHAIN_FILTER_REMAINING[@]}")
|
||||
G2G3_ARGS=()
|
||||
[[ "${TRUSTLESS_DEPLOY_LOCKBOX:-1}" == "1" ]] && G2G3_ARGS+=(--lockbox) || G2G3_ARGS+=(--no-lockbox)
|
||||
[[ ${#CHAIN_FILTER[@]} -gt 0 ]] && G2G3_ARGS+=(--chain "${CHAIN_FILTER[@]}")
|
||||
|
||||
echo "=============================================="
|
||||
echo "Running liquidity gaps (secrets from .env)"
|
||||
echo "=============================================="
|
||||
|
||||
if [[ "$RUN_G1" == "1" ]]; then
|
||||
echo ""
|
||||
echo "--- G1: Deploy PMM on L2s ---"
|
||||
./scripts/deployment/deploy-pmm-all-l2s.sh || true
|
||||
fi
|
||||
|
||||
if [[ "$RUN_G2G3" == "1" ]]; then
|
||||
echo ""
|
||||
echo "--- G2/G3: Deploy Trustless (+ Lockbox) on L2s ---"
|
||||
./scripts/deployment/deploy-trustless-l2s.sh "${G2G3_ARGS[@]}" || true
|
||||
fi
|
||||
|
||||
if [[ "$RUN_G4" == "1" ]]; then
|
||||
echo ""
|
||||
echo "--- G4: Fund mainnet LP ---"
|
||||
./scripts/deployment/fund-mainnet-lp.sh "${G4_ARGS[@]}" || true
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Done. Update .env with any new contract addresses printed above."
|
||||
114
scripts/deployment/run-e2e-trustless-live-test.sh
Executable file
114
scripts/deployment/run-e2e-trustless-live-test.sh
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env bash
|
||||
# E2E live test: lock on 138 -> submit claim on mainnet -> (after 30 min) finalize -> release bond.
|
||||
# Run from a host that can reach RPC_URL_138. Requires .env in smom-dbis-138 repo root.
|
||||
# Best: cd /path/to/smom-dbis-138 then ./scripts/deployment/run-e2e-trustless-live-test.sh
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/deployment/run-e2e-trustless-live-test.sh # run step 1 (lock), then print steps 2–3
|
||||
# ./scripts/deployment/run-e2e-trustless-live-test.sh get-deposit-id <LOCK_TX_HASH> # print DEPOSIT_ID from lock tx
|
||||
# DEPOSIT_ID=0x... AMOUNT_WEI=1000000000000000 ./scripts/deployment/run-e2e-trustless-live-test.sh claim # run step 2 only
|
||||
# DEPOSIT_ID=0x... ./scripts/deployment/run-e2e-trustless-live-test.sh finalize # run step 3 only
|
||||
set -euo pipefail
|
||||
# Resolve repo root from script path so this works from any cwd (use full path to script when invoking)
|
||||
SCRIPT_PATH="${BASH_SOURCE[0]}"
|
||||
[[ -z "$SCRIPT_PATH" ]] && SCRIPT_PATH="$0"
|
||||
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
if [[ ! -d "$REPO_ROOT" ]]; then
|
||||
echo "Error: REPO_ROOT not found: $REPO_ROOT. Run from smom-dbis-138 repo, e.g. cd /path/to/smom-dbis-138 && ./scripts/deployment/run-e2e-trustless-live-test.sh"
|
||||
exit 1
|
||||
fi
|
||||
cd "$REPO_ROOT" || { echo "Error: cannot cd to $REPO_ROOT"; exit 1; }
|
||||
[[ -f .env ]] && set -a && source .env && set +a
|
||||
|
||||
# Use _MAINNET variants if unsuffixed not set (for .env that only has _MAINNET)
|
||||
export BOND_MANAGER="${BOND_MANAGER:-${BOND_MANAGER_MAINNET:-}}"
|
||||
export CHALLENGE_MANAGER="${CHALLENGE_MANAGER:-${CHALLENGE_MANAGER_MAINNET:-}}"
|
||||
export INBOX_ETH="${INBOX_ETH:-${INBOX_ETH_MAINNET:-}}"
|
||||
export LOCKBOX_138="${LOCKBOX_138:-}"
|
||||
export RPC_URL_138="${RPC_URL_138:-${CHAIN_138_RPC_URL:-}}"
|
||||
export ETHEREUM_MAINNET_RPC="${ETHEREUM_MAINNET_RPC:-}"
|
||||
|
||||
# Require key and RPCs so we fail with a clear message instead of "Invalid params"
|
||||
[[ -n "${PRIVATE_KEY:-}" ]] || { echo "PRIVATE_KEY not set in .env"; exit 1; }
|
||||
RECIPIENT=$(cast wallet address "$PRIVATE_KEY")
|
||||
NONCE=$(cast keccak "e2e-$(date +%s)" | tr -d '\n\r')
|
||||
# 0.001 ether in wei
|
||||
AMOUNT_WEI="${AMOUNT_WEI:-1000000000000000}"
|
||||
|
||||
case "${1:-}" in
|
||||
get-deposit-id)
|
||||
[[ -n "${RPC_URL_138:-}" ]] || { echo "RPC_URL_138 not set"; exit 1; }
|
||||
LOCK_TX="${2:-}"
|
||||
[[ -n "$LOCK_TX" ]] || { echo "Usage: $0 get-deposit-id <LOCK_TX_HASH>"; exit 1; }
|
||||
# Deposit event: first indexed param is depositId (topics[1])
|
||||
DEPOSIT_ID_HEX=$(cast receipt "$LOCK_TX" --rpc-url "$RPC_URL_138" -j 2>/dev/null | jq -r '.logs[0].topics[1] // empty')
|
||||
if [[ -z "$DEPOSIT_ID_HEX" ]]; then
|
||||
echo "No Deposit log in tx or jq failed. Try: cast logs $LOCK_TX \"Deposit(uint256,address,uint256,address,bytes32,address,uint256)\" --rpc-url \$RPC_URL_138"
|
||||
exit 1
|
||||
fi
|
||||
# cast expects uint256 as decimal or 0x; topics are 32-byte hex (0x + 64 chars)
|
||||
echo "$DEPOSIT_ID_HEX"
|
||||
exit 0
|
||||
;;
|
||||
claim)
|
||||
[[ -n "${ETHEREUM_MAINNET_RPC:-}" ]] || { echo "ETHEREUM_MAINNET_RPC not set"; exit 1; }
|
||||
[[ -n "${INBOX_ETH:-}" && -n "${BOND_MANAGER:-}" ]] || { echo "INBOX_ETH and BOND_MANAGER must be set for claim"; exit 1; }
|
||||
if [[ -z "${DEPOSIT_ID:-}" ]]; then
|
||||
echo "Set DEPOSIT_ID (from step 1 lock tx Deposit event). Example: DEPOSIT_ID=0x... $0 claim"
|
||||
echo "To get DEPOSIT_ID from lock tx: cast logs <LOCK_TX_HASH> \"Deposit(uint256,address,uint256,address,bytes32,address,uint256)\" --rpc-url \$RPC_URL_138"
|
||||
echo " Use the first decoded arg (depositId) as DEPOSIT_ID. Do NOT use AMOUNT_WEI as DEPOSIT_ID."
|
||||
exit 1
|
||||
fi
|
||||
# Avoid common mistake: DEPOSIT_ID must be the event's depositId (large/hash), not the amount
|
||||
if [[ "${DEPOSIT_ID:-}" == "1000000000000000" ]] || [[ "${DEPOSIT_ID:-}" == "$AMOUNT_WEI" ]]; then
|
||||
echo "Error: DEPOSIT_ID looks like AMOUNT_WEI (0.001 ether). Set DEPOSIT_ID to the depositId from the Deposit event, not the amount."
|
||||
exit 1
|
||||
fi
|
||||
BOND=$(cast call "$BOND_MANAGER" "getRequiredBond(uint256)(uint256)" "$AMOUNT_WEI" --rpc-url "$ETHEREUM_MAINNET_RPC")
|
||||
# cast may append " [1e18]" etc.; use only the numeric part for --value
|
||||
BOND="${BOND%% *}"
|
||||
echo "BOND (required for claim): $BOND wei"
|
||||
cast send "$INBOX_ETH" "submitClaim(uint256,address,uint256,address,bytes)" \
|
||||
"$DEPOSIT_ID" 0x0000000000000000000000000000000000000000 "$AMOUNT_WEI" "$RECIPIENT" 0x \
|
||||
--value "$BOND" --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"
|
||||
echo "Claim submitted. Wait ~30 min then run: DEPOSIT_ID=$DEPOSIT_ID $0 finalize"
|
||||
exit 0
|
||||
;;
|
||||
finalize)
|
||||
[[ -n "${ETHEREUM_MAINNET_RPC:-}" ]] || { echo "ETHEREUM_MAINNET_RPC not set"; exit 1; }
|
||||
[[ -n "${CHALLENGE_MANAGER:-}" && -n "${BOND_MANAGER:-}" ]] || { echo "CHALLENGE_MANAGER and BOND_MANAGER must be set for finalize"; exit 1; }
|
||||
if [[ -z "${DEPOSIT_ID:-}" ]]; then
|
||||
echo "Set DEPOSIT_ID. Example: DEPOSIT_ID=0x... $0 finalize"
|
||||
exit 1
|
||||
fi
|
||||
cast send "$CHALLENGE_MANAGER" "finalizeClaim(uint256)" "$DEPOSIT_ID" \
|
||||
--rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"
|
||||
cast send "$BOND_MANAGER" "releaseBond(uint256)" "$DEPOSIT_ID" \
|
||||
--rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"
|
||||
echo "Finalized and bond released."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# Step 1: Lock on 138
|
||||
[[ -n "${RPC_URL_138:-}" ]] || { echo "RPC_URL_138 not set (required for lock on 138)"; exit 1; }
|
||||
[[ -n "${LOCKBOX_138:-}" ]] || { echo "LOCKBOX_138 not set in .env"; exit 1; }
|
||||
# Fail fast if RPC is not Chain 138 (avoids -32602 Invalid params from wrong chain)
|
||||
CHAIN_ID=$(curl -s -m 5 -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' "$RPC_URL_138" 2>/dev/null | sed -n 's/.*"result":"\([^"]*\)".*/\1/p')
|
||||
if [[ "$CHAIN_ID" != "0x8a" && "$CHAIN_ID" != "0x8A" ]]; then
|
||||
echo "Error: RPC_URL_138 ($RPC_URL_138) returned chainId=$CHAIN_ID; expected 0x8a (138). Fix .env and retry."
|
||||
exit 1
|
||||
fi
|
||||
echo "Step 1: Lock 0.001 ether on Chain 138 (LOCKBOX_138=$LOCKBOX_138)"
|
||||
echo "RECIPIENT=$RECIPIENT NONCE=$NONCE"
|
||||
# Use explicit --gas-limit to avoid eth_estimateGas -32602 Invalid params on some Chain 138 (Besu) nodes
|
||||
cast send "$LOCKBOX_138" "depositNative(address,bytes32)" "$RECIPIENT" "$NONCE" \
|
||||
--value 0.001ether --rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" \
|
||||
--legacy --gas-price "${GAS_PRICE_138:-1000000000}" --gas-limit "${GAS_LIMIT_138:-200000}"
|
||||
echo ""
|
||||
echo "Get DEPOSIT_ID from the lock tx (run with the tx hash from above):"
|
||||
echo " export DEPOSIT_ID=\$(./scripts/deployment/run-e2e-trustless-live-test.sh get-deposit-id <LOCK_TX_HASH>)"
|
||||
echo " AMOUNT_WEI=$AMOUNT_WEI $0 claim"
|
||||
echo "Or manually: cast logs <LOCK_TX_HASH> \"Deposit(uint256,address,uint256,address,bytes32,address,uint256)\" --rpc-url \$RPC_URL_138 (use first decoded arg)"
|
||||
echo "Note: DEPOSIT_ID is the event's depositId, NOT the amount. Required bond for 0.001 ether is 1 ETH (min bond)."
|
||||
44
scripts/deployment/run-pmm-and-pools.sh
Executable file
44
scripts/deployment/run-pmm-and-pools.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run PMM phase (DeployDODOPMMIntegration) and optionally DeployPrivatePoolRegistryAndPools.
|
||||
# Requires: .env with DODO_VENDING_MACHINE_ADDRESS, COMPLIANT_USDT_ADDRESS, COMPLIANT_USDC_ADDRESS,
|
||||
# OFFICIAL_USDT_ADDRESS, OFFICIAL_USDC_ADDRESS (see docs/integration/DODO_PMM_INTEGRATION.md).
|
||||
# For XAU pools: set DODOPMM_INTEGRATION_ADDRESS and XAU_ADDRESS_138 after the first run.
|
||||
# Usage: ./scripts/deployment/run-pmm-and-pools.sh
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
load_deployment_env
|
||||
|
||||
# Reject unset, empty, or zero address (0x0 or 0x000...)
|
||||
if [[ -z "${DODO_VENDING_MACHINE_ADDRESS:-}" ]]; then
|
||||
echo "DODO_VENDING_MACHINE_ADDRESS not set. Set it to the DODO DVM factory on Chain 138 (see docs/deployment/ALL_MAINNETS_DEPLOYMENT_RUNBOOK.md)."
|
||||
exit 1
|
||||
fi
|
||||
# Reject 0x0 or 0x000...000 (zero address)
|
||||
if [[ "$(echo "${DODO_VENDING_MACHINE_ADDRESS}" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')" =~ ^0x0+$ ]]; then
|
||||
echo "DODO_VENDING_MACHINE_ADDRESS is zero. Set it to the DVM factory on Chain 138."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Deploy DODOPMMIntegration (Chain 138) ==="
|
||||
bash "$SCRIPT_DIR/deploy-all-mainnets-with-mapper-oracle-pmm.sh" pmm
|
||||
|
||||
if [[ -n "${DODO_PMM_INTEGRATION:-}" || -n "${DODOPMM_INTEGRATION_ADDRESS:-}" ]]; then
|
||||
addr="${DODO_PMM_INTEGRATION:-$DODOPMM_INTEGRATION_ADDRESS}"
|
||||
echo ""
|
||||
echo "DODOPMMIntegration at $addr. Create cUSDT/USDT and cUSDC/USDC pools via createCUSDTUSDTPool/createCUSDCUSDCPool (see docs/integration/DODO_PMM_INTEGRATION.md)."
|
||||
if [[ -n "${XAU_ADDRESS_138:-}" ]]; then
|
||||
echo "=== Deploy PrivatePoolRegistry and XAU-anchored pools ==="
|
||||
forge script script/dex/DeployPrivatePoolRegistryAndPools.s.sol:DeployPrivatePoolRegistryAndPools \
|
||||
--rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" \
|
||||
--with-gas-price "${GAS_PRICE_138:-1000000000}" --legacy -vvv || true
|
||||
else
|
||||
echo "Set XAU_ADDRESS_138 and DODOPMM_INTEGRATION_ADDRESS in .env to deploy XAU-anchored pools (DeployPrivatePoolRegistryAndPools)."
|
||||
fi
|
||||
else
|
||||
echo "Set DODO_PMM_INTEGRATION or DODOPMM_INTEGRATION_ADDRESS in .env after deploy, then re-run for pool creation."
|
||||
fi
|
||||
143
scripts/deployment/run-pmm-full-parity-all-phases.sh
Executable file
143
scripts/deployment/run-pmm-full-parity-all-phases.sh
Executable file
@@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run PMM full parity: Phase 1 (Chain 138) and Phase 2 (L2s) in full parallel where possible.
|
||||
# Usage:
|
||||
# ./scripts/deployment/run-pmm-full-parity-all-phases.sh # run all phases
|
||||
# RUN_PHASE1=0 ./scripts/deployment/run-pmm-full-parity-all-phases.sh # skip Phase 1
|
||||
# RUN_PHASE2=0 ./scripts/deployment/run-pmm-full-parity-all-phases.sh # skip Phase 2
|
||||
# DRY_RUN=1 ./scripts/deployment/run-pmm-full-parity-all-phases.sh # print only
|
||||
# ADD_LIQUIDITY_BASE_AMOUNT=1000000e6 ADD_LIQUIDITY_QUOTE_AMOUNT=1000000e6 ... # liquidity amounts (6 decimals)
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
load_deployment_env
|
||||
# Ensure .env is loaded (for PRIVATE_KEY, RPCs, etc.)
|
||||
[[ -f ".env" ]] && set -a && source ".env" && set +a
|
||||
|
||||
RUN_PHASE1="${RUN_PHASE1:-1}"
|
||||
RUN_PHASE2="${RUN_PHASE2:-1}"
|
||||
DRY_RUN="${DRY_RUN:-}"
|
||||
RPC_138="${RPC_URL_138:-${RPC_URL:-http://192.168.11.211:8545}}"
|
||||
GAS_PRICE="${GAS_PRICE_138:-${GAS_PRICE:-1000000000}}"
|
||||
INTEGRATION="${DODO_PMM_INTEGRATION_ADDRESS:-${DODO_PMM_INTEGRATION:-0x79cdbaFBaA0FdF9F55D26F360F54cddE5c743F7D}}"
|
||||
POOL_CUSDTCUSDC="${POOL_CUSDTCUSDC:-0x9fcB06Aa1FD5215DC0E91Fd098aeff4B62fEa5C8}"
|
||||
POOL_CUSDTUSDT="${POOL_CUSDTUSDT:-0xa3Ee6091696B28e5497b6F491fA1e99047250c59}"
|
||||
POOL_CUSDCUSDC="${POOL_CUSDCUSDC:-0x90bd9Bf18Daa26Af3e814ea224032d015db58Ea5}"
|
||||
|
||||
export RPC_URL_138="$RPC_138"
|
||||
export DODO_PMM_INTEGRATION_ADDRESS="$INTEGRATION"
|
||||
export POOL_CUSDTCUSDC POOL_CUSDTUSDT POOL_CUSDCUSDC
|
||||
|
||||
log() { echo "[$(date +%H:%M:%S)] $*"; }
|
||||
run_or_dry() {
|
||||
if [[ -n "$DRY_RUN" ]]; then
|
||||
log "[DRY RUN] $*"
|
||||
return 0
|
||||
fi
|
||||
"$@"
|
||||
}
|
||||
|
||||
# ---------- Phase 1: Chain 138 ----------
|
||||
phase1() {
|
||||
log "=== Phase 1: Chain 138 (verify pools, register, add liquidity) ==="
|
||||
if [[ -z "${PRIVATE_KEY:-}" ]]; then
|
||||
log "Skip Phase 1: PRIVATE_KEY not set"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 1a) Create all 3 pools in parallel (if not already created — scripts will fail if pool exists)
|
||||
log "Creating PMM pools (parallel)..."
|
||||
if [[ -z "$DRY_RUN" ]]; then
|
||||
( forge script script/dex/CreateCUSDTCUSDCPool.s.sol:CreateCUSDTCUSDCPool \
|
||||
--rpc-url "$RPC_138" --broadcast --private-key "$PRIVATE_KEY" --with-gas-price "$GAS_PRICE" -vv 2>&1 | tee /tmp/pmm-create-cusdt-cusdc.log ) &
|
||||
PID1=$!
|
||||
( forge script script/dex/CreateCUSDTUSDTPool.s.sol:CreateCUSDTUSDTPool \
|
||||
--rpc-url "$RPC_138" --broadcast --private-key "$PRIVATE_KEY" --with-gas-price "$GAS_PRICE" -vv 2>&1 | tee /tmp/pmm-create-cusdt-usdt.log ) &
|
||||
PID2=$!
|
||||
( forge script script/dex/CreateCUSDCUSDCPool.s.sol:CreateCUSDCUSDCPool \
|
||||
--rpc-url "$RPC_138" --broadcast --private-key "$PRIVATE_KEY" --with-gas-price "$GAS_PRICE" -vv 2>&1 | tee /tmp/pmm-create-cusdc-usdc.log ) &
|
||||
PID3=$!
|
||||
wait $PID1 2>/dev/null || true
|
||||
wait $PID2 2>/dev/null || true
|
||||
wait $PID3 2>/dev/null || true
|
||||
else
|
||||
log "[DRY RUN] forge script CreateCUSDTCUSDCPool ..."
|
||||
log "[DRY RUN] forge script CreateCUSDTUSDTPool ..."
|
||||
log "[DRY RUN] forge script CreateCUSDCUSDCPool ..."
|
||||
fi
|
||||
|
||||
# 1b) Register pools with DODOPMMProvider (requires DODO_PMM_PROVIDER_ADDRESS)
|
||||
if [[ -n "${DODO_PMM_PROVIDER_ADDRESS:-}" ]]; then
|
||||
log "Registering pools with DODOPMMProvider..."
|
||||
run_or_dry forge script script/liquidity/RegisterDODOPools.s.sol:RegisterDODOPools \
|
||||
--rpc-url "$RPC_138" --broadcast --private-key "$PRIVATE_KEY" --with-gas-price "$GAS_PRICE" -vv
|
||||
else
|
||||
log "Skip register: DODO_PMM_PROVIDER_ADDRESS not set"
|
||||
fi
|
||||
|
||||
# 1c) Add liquidity (optional: set ADD_LIQUIDITY_BASE_AMOUNT and ADD_LIQUIDITY_QUOTE_AMOUNT)
|
||||
if [[ -n "${ADD_LIQUIDITY_BASE_AMOUNT:-}" && -n "${ADD_LIQUIDITY_QUOTE_AMOUNT:-}" ]]; then
|
||||
log "Adding liquidity to PMM pools..."
|
||||
run_or_dry forge script script/dex/AddLiquidityPMMPoolsChain138.s.sol:AddLiquidityPMMPoolsChain138 \
|
||||
--rpc-url "$RPC_138" --broadcast --private-key "$PRIVATE_KEY" --with-gas-price "$GAS_PRICE" -vv
|
||||
else
|
||||
log "Skip add liquidity: set ADD_LIQUIDITY_BASE_AMOUNT and ADD_LIQUIDITY_QUOTE_AMOUNT (e.g. 1000000e6)"
|
||||
fi
|
||||
|
||||
log "Phase 1 done."
|
||||
}
|
||||
|
||||
# ---------- Phase 2: One chain (deploy cUSDT/cUSDC + DODOPMMIntegration) ----------
|
||||
phase2_chain() {
|
||||
local name="$1" chain_id="$2" rpc_var="$3"
|
||||
local rpc="${!rpc_var:-}"
|
||||
[[ -z "$rpc" ]] && return 0
|
||||
log "[$name] Deploy cUSDT/cUSDC + DODOPMMIntegration (chain $chain_id)"
|
||||
if [[ -n "$DRY_RUN" ]]; then
|
||||
log "[DRY RUN] $name: deploy tokens + integration"
|
||||
return 0
|
||||
fi
|
||||
local name_lower
|
||||
name_lower=$(echo "$name" | tr '[:upper:]' '[:lower:]')
|
||||
(
|
||||
export DEPLOY_CUSDT_CUSDC_FILTER="$name"
|
||||
export DEPLOY_PMM_L2S_FILTER="$name_lower"
|
||||
cd "$REPO_ROOT"
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
load_deployment_env
|
||||
./scripts/deployment/deploy-cusdt-cusdc-all-chains.sh 2>&1 | tee "/tmp/pmm-phase2-$name-tokens.log" || true
|
||||
./scripts/deployment/deploy-pmm-all-l2s.sh --chain "$name_lower" 2>&1 | tee "/tmp/pmm-phase2-$name-pmm.log" || true
|
||||
)
|
||||
log "[$name] done."
|
||||
}
|
||||
|
||||
# ---------- Phase 2: All L2s in parallel ----------
|
||||
phase2() {
|
||||
log "=== Phase 2: L2s (deploy cUSDT/cUSDC + DODOPMMIntegration per chain, parallel) ==="
|
||||
CHAINS=(
|
||||
"BSC:56:BSC_RPC_URL"
|
||||
"POLYGON:137:POLYGON_MAINNET_RPC"
|
||||
"BASE:8453:BASE_MAINNET_RPC"
|
||||
"OPTIMISM:10:OPTIMISM_MAINNET_RPC"
|
||||
"ARBITRUM:42161:ARBITRUM_MAINNET_RPC"
|
||||
"AVALANCHE:43114:AVALANCHE_RPC_URL"
|
||||
"CRONOS:25:CRONOS_RPC_URL"
|
||||
"GNOSIS:100:GNOSIS_MAINNET_RPC"
|
||||
)
|
||||
PIDS=()
|
||||
for entry in "${CHAINS[@]}"; do
|
||||
IFS=: read -r name chain_id rpc_var <<< "$entry"
|
||||
phase2_chain "$name" "$chain_id" "$rpc_var" &
|
||||
PIDS+=($!)
|
||||
done
|
||||
for p in "${PIDS[@]}"; do wait "$p" 2>/dev/null || true; done
|
||||
log "Phase 2 done."
|
||||
}
|
||||
|
||||
# ---------- Main ----------
|
||||
log "PMM full parity — Phase1=$RUN_PHASE1 Phase2=$RUN_PHASE2 DRY_RUN=$DRY_RUN"
|
||||
[[ "$RUN_PHASE1" = "1" ]] && phase1
|
||||
[[ "$RUN_PHASE2" = "1" ]] && phase2
|
||||
log "All requested phases finished."
|
||||
49
scripts/deployment/run-remaining-g2g3-with-nonce-fix.sh
Executable file
49
scripts/deployment/run-remaining-g2g3-with-nonce-fix.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run G2/G3 (Trustless + Lockbox) on the chains that previously failed: BSC, POLYGON, BASE, OPTIMISM, CRONOS.
|
||||
# Fixes nonce for Cronos by clearing broadcast cache first; uses --slow and delay between chains to avoid 429/nonce issues.
|
||||
# Tags: --delay <sec>, --lockbox / --no-lockbox.
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
source "$SCRIPT_DIR/../lib/deployment/prompts.sh"
|
||||
load_deployment_env
|
||||
parse_delay_tag "$@"
|
||||
parse_lockbox_tag "${PARSE_DELAY_REMAINING[@]}"
|
||||
|
||||
TRUSTLESS_SCRIPT="script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge"
|
||||
DELAY_BETWEEN_CHAINS="${DELAY_BETWEEN_CHAINS:-45}"
|
||||
|
||||
echo "=============================================="
|
||||
echo "G2/G3 remaining: BSC, POLYGON, BASE, OPTIMISM, CRONOS (nonce fix for Cronos)"
|
||||
echo "=============================================="
|
||||
|
||||
# Cronos: clear nonce cache then deploy
|
||||
echo ""
|
||||
echo "--- Fix nonce for Cronos (clear cache) ---"
|
||||
./scripts/deployment/fix-nonce-and-retry.sh --chain cronos --script "$TRUSTLESS_SCRIPT" || true
|
||||
echo ""
|
||||
echo "--- Deploy Trustless + Lockbox on CRONOS (chain 25) ---"
|
||||
rpc="${CRONOS_RPC_URL:-https://evm.cronos.org}"
|
||||
weth="0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23"
|
||||
TRUSTLESS_WETH_ADDRESS="$weth" TRUSTLESS_DEPLOY_LOCKBOX="${TRUSTLESS_DEPLOY_LOCKBOX:-1}" \
|
||||
forge script script/bridge/trustless/DeployTrustlessBridge.s.sol:DeployTrustlessBridge \
|
||||
--rpc-url "$rpc" --chain-id 25 --broadcast --private-key "$PRIVATE_KEY" --slow -vvv || true
|
||||
sleep "$DELAY_BETWEEN_CHAINS"
|
||||
|
||||
# BSC, Polygon, Base, Optimism with delay between each
|
||||
for name in BSC POLYGON BASE OPTIMISM; do
|
||||
echo ""
|
||||
echo "--- Deploy Trustless + Lockbox on $name ---"
|
||||
if [[ "${TRUSTLESS_DEPLOY_LOCKBOX:-1}" == "1" ]]; then
|
||||
./scripts/deployment/deploy-trustless-l2s.sh --chain "$name" --lockbox || true
|
||||
else
|
||||
./scripts/deployment/deploy-trustless-l2s.sh --chain "$name" --no-lockbox || true
|
||||
fi
|
||||
sleep "$DELAY_BETWEEN_CHAINS"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Done. Update .env with BondManager, ChallengeManager, LiquidityPool, Inbox, Lockbox per chain."
|
||||
@@ -36,21 +36,23 @@ update_var() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Update the provided variables
|
||||
# Update the provided variables (use placeholders; set real values in .env and never commit).
|
||||
if [ ! -z "$1" ] && [ "$1" == "update" ]; then
|
||||
update_var "ETHEREUM_MAINNET_RPC" "https://mainnet.infura.io/v3/43b945b33d58463a9246cf5ca8aa6286"
|
||||
update_var "RPC_URL_138" "http://192.168.11.250"
|
||||
update_var "ETHERSCAN_API_KEY" "89HVZNN68DWKWVZHQRGQJ1B74FGKWBJV1W"
|
||||
update_var "ETHEREUM_MAINNET_RPC" "https://mainnet.infura.io/v3/<INFURA_PROJECT_ID>"
|
||||
update_var "RPC_URL_138" "http://192.168.11.211:8545"
|
||||
update_var "ETHERSCAN_API_KEY" "<YOUR_ETHERSCAN_API_KEY>"
|
||||
update_var "INFURA_PROJECT_ID" "<YOUR_INFURA_PROJECT_ID>"
|
||||
update_var "INFURA_PROJECT_SECRET" "<YOUR_INFURA_PROJECT_SECRET>"
|
||||
echo ""
|
||||
echo "✓ Environment variables updated"
|
||||
echo "✓ Environment variables updated with placeholders"
|
||||
echo " Set real values in .env (INFURA_PROJECT_ID, INFURA_PROJECT_SECRET, ETHERSCAN_API_KEY); never commit secrets."
|
||||
echo ""
|
||||
echo "Run: ./scripts/deployment/check-env-requirements.sh to verify"
|
||||
else
|
||||
echo "Usage: $0 update"
|
||||
echo ""
|
||||
echo "This will update:"
|
||||
echo " - ETHEREUM_MAINNET_RPC"
|
||||
echo " - RPC_URL_138"
|
||||
echo " - ETHERSCAN_API_KEY"
|
||||
echo "This will set placeholders for:"
|
||||
echo " - ETHEREUM_MAINNET_RPC (Infura), RPC_URL_138, ETHERSCAN_API_KEY"
|
||||
echo " - INFURA_PROJECT_ID, INFURA_PROJECT_SECRET (for Infura RPC + Basic Auth)"
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,41 +1,48 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Verify All RPC Endpoints
|
||||
# This script tests connectivity to all configured RPC endpoints
|
||||
#!/usr/bin/env bash
|
||||
# Verify All RPC Endpoints — tests connectivity to Mainnet, Chain 138, and all configured chain RPCs.
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
echo "=== RPC Endpoint Verification ==="
|
||||
echo ""
|
||||
|
||||
# Load environment variables
|
||||
if [ -f .env ]; then
|
||||
export $(cat .env | grep -v '^#' | grep -v '^$' | xargs)
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Use Infura with Basic Auth when INFURA_PROJECT_SECRET is set (fixes "error sending request" from Infura)
|
||||
[ -f "${PROJECT_ROOT}/scripts/lib/infura.sh" ] && source "${PROJECT_ROOT}/scripts/lib/infura.sh"
|
||||
|
||||
if ! command -v cast &> /dev/null; then
|
||||
echo "Error: cast command not found. Install foundry to verify RPC endpoints."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to test RPC
|
||||
# Function to test RPC (uses Infura Basic Auth URL when INFURA_PROJECT_SECRET is set)
|
||||
test_rpc() {
|
||||
local name=$1
|
||||
local url=$2
|
||||
[ -n "$url" ] && type ensure_infura_rpc_url &>/dev/null && url=$(ensure_infura_rpc_url "$url")
|
||||
|
||||
if [ -z "$url" ] || [ "$url" == "http://chain138.example.com:8545" ] || [[ "$url" == *"YOUR_PROJECT_ID"* ]]; then
|
||||
if [ -z "$url" ] || [ "$url" == "http://chain138.example.com:8545" ] || [[ "$url" == *"YOUR_PROJECT_ID"* ]] || [[ "$url" == *"<"* ]]; then
|
||||
echo "○ $name: Not configured"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -n "Testing $name... "
|
||||
BLOCK=$(cast block-number --rpc-url "$url" 2>&1)
|
||||
|
||||
if [ $? -eq 0 ] && [[ "$BLOCK" =~ ^[0-9]+$ ]]; then
|
||||
BLOCK=$(cast block-number --rpc-url "$url" 2>&1) || true
|
||||
if [[ "$BLOCK" =~ ^[0-9]+$ ]]; then
|
||||
echo "✓ Connected (block: $BLOCK)"
|
||||
else
|
||||
echo "✗ Failed: $BLOCK"
|
||||
echo "✗ Failed (${BLOCK:0:80})"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
echo "--- Required RPC Endpoints ---"
|
||||
@@ -43,7 +50,7 @@ test_rpc "Ethereum Mainnet" "$ETHEREUM_MAINNET_RPC"
|
||||
test_rpc "ChainID 138" "$RPC_URL_138"
|
||||
|
||||
echo ""
|
||||
echo "--- Additional Network RPC Endpoints ---"
|
||||
echo "--- Additional Network RPC Endpoints (Infura when set) ---"
|
||||
test_rpc "Ethereum Sepolia" "$ETHEREUM_SEPOLIA_RPC"
|
||||
test_rpc "Polygon Mainnet" "$POLYGON_MAINNET_RPC"
|
||||
test_rpc "Polygon Amoy" "$POLYGON_AMOY_RPC"
|
||||
@@ -51,6 +58,19 @@ test_rpc "Base Mainnet" "$BASE_MAINNET_RPC"
|
||||
test_rpc "Base Sepolia" "$BASE_SEPOLIA_RPC"
|
||||
test_rpc "Optimism Mainnet" "$OPTIMISM_MAINNET_RPC"
|
||||
test_rpc "Optimism Sepolia" "$OPTIMISM_SEPOLIA_RPC"
|
||||
test_rpc "Arbitrum Mainnet" "$ARBITRUM_MAINNET_RPC"
|
||||
test_rpc "Arbitrum Sepolia" "$ARBITRUM_SEPOLIA_RPC"
|
||||
test_rpc "Avalanche Mainnet" "$AVALANCHE_MAINNET_RPC"
|
||||
test_rpc "Avalanche Fuji" "$AVALANCHE_FUJI_RPC"
|
||||
test_rpc "BSC Mainnet" "$BSC_MAINNET_RPC"
|
||||
test_rpc "Celo Mainnet" "$CELO_MAINNET_RPC"
|
||||
test_rpc "Linea Mainnet" "$LINEA_MAINNET_RPC"
|
||||
|
||||
echo ""
|
||||
echo "--- Other chain RPCs (aliases / public fallbacks) ---"
|
||||
test_rpc "AVALANCHE_RPC_URL" "${AVALANCHE_RPC_URL:-}"
|
||||
test_rpc "ARBITRUM_RPC" "${ARBITRUM_MAINNET_RPC:-$ARBITRUM_RPC}"
|
||||
test_rpc "Cronos" "$CRONOS_RPC_URL"
|
||||
|
||||
echo ""
|
||||
echo "=== Verification Complete ==="
|
||||
|
||||
80
scripts/deployment/verify-ccip-logger-other-chains.sh
Executable file
80
scripts/deployment/verify-ccip-logger-other-chains.sh
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verify CCIPLogger on Etherscan-V2-supported chains (BSC, Polygon, Gnosis, Optimism, Base, Arbitrum, Avalanche).
|
||||
# Prerequisite: Deploy CCIPLogger per chain (deploy-ccip-logger-all-chains.sh) and set in .env:
|
||||
# CCIP_LOGGER_BSC, CCIP_BSC_ROUTER (and same for polygon, gnosis, optimism, base, arbitrum, avalanche).
|
||||
# Mainnet: already verified (see COMPLETION_RUN_WITH_KEYS_20260223.md). Cronos: not Etherscan V2; use Cronoscan.
|
||||
# Usage: cd smom-dbis-138 && ./scripts/deployment/verify-ccip-logger-other-chains.sh
|
||||
# Requires: ETHERSCAN_API_KEY and PRIVATE_KEY in .env; npm/hardhat.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if [[ -f .env ]]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
AUTH_SIGNER="${AUTHORIZED_SIGNER:-0x0000000000000000000000000000000000000000}"
|
||||
SOURCE_CHAIN_SELECTOR="${CHAIN138_SELECTOR:-138}"
|
||||
|
||||
# Network -> env suffix (logger address, router). mainnet skipped (already verified); cronos skipped (no V2).
|
||||
declare -A LOGGER_VAR=(
|
||||
[bsc]=CCIP_LOGGER_BSC
|
||||
[polygon]=CCIP_LOGGER_POLYGON
|
||||
[gnosis]=CCIP_LOGGER_GNOSIS
|
||||
[optimism]=CCIP_LOGGER_OPTIMISM
|
||||
[base]=CCIP_LOGGER_BASE
|
||||
[arbitrum]=CCIP_LOGGER_ARBITRUM
|
||||
[avalanche]=CCIP_LOGGER_AVALANCHE
|
||||
)
|
||||
declare -A ROUTER_VAR=(
|
||||
[bsc]=CCIP_BSC_ROUTER
|
||||
[polygon]=CCIP_POLYGON_ROUTER
|
||||
[gnosis]=CCIP_GNOSIS_ROUTER
|
||||
[optimism]=CCIP_OPTIMISM_ROUTER
|
||||
[base]=CCIP_BASE_ROUTER
|
||||
[arbitrum]=CCIP_ARBITRUM_ROUTER
|
||||
[avalanche]=CCIP_AVALANCHE_ROUTER
|
||||
)
|
||||
|
||||
if [[ -z "${ETHERSCAN_API_KEY:-}" ]]; then
|
||||
echo "ETHERSCAN_API_KEY not set. Add to .env and re-run." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERIFIED=0
|
||||
SKIPPED=0
|
||||
FAILED=0
|
||||
|
||||
for net in bsc polygon gnosis optimism base arbitrum avalanche; do
|
||||
addr_var="${LOGGER_VAR[$net]}"
|
||||
router_var="${ROUTER_VAR[$net]}"
|
||||
addr="${!addr_var:-}"
|
||||
router="${!router_var:-}"
|
||||
if [[ -z "$addr" || "$addr" = "0x0000000000000000000000000000000000000000" ]]; then
|
||||
echo "[$net] Skip (no $addr_var in .env)"
|
||||
SKIPPED=$((SKIPPED + 1))
|
||||
continue
|
||||
fi
|
||||
if [[ -z "$router" || "$router" = "0x0000000000000000000000000000000000000000" ]]; then
|
||||
echo "[$net] Skip ($addr_var set but $router_var missing)"
|
||||
SKIPPED=$((SKIPPED + 1))
|
||||
continue
|
||||
fi
|
||||
echo "[$net] Verifying CCIPLogger $addr ..."
|
||||
if npx hardhat verify --network "$net" "$addr" "$router" "$AUTH_SIGNER" "$SOURCE_CHAIN_SELECTOR" 2>&1; then
|
||||
echo "[$net] Verified."
|
||||
VERIFIED=$((VERIFIED + 1))
|
||||
else
|
||||
echo "[$net] Verify failed (may already be verified)."
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Summary: $VERIFIED verified, $SKIPPED skipped (no address/router), $FAILED failed."
|
||||
echo "To deploy first: ./scripts/deployment/deploy-ccip-logger-all-chains.sh then set CCIP_LOGGER_* and CCIP_*_ROUTER in .env."
|
||||
@@ -3,9 +3,19 @@
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/../.."
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
cd "$SCRIPT_DIR/../.."
|
||||
[ -f "$SCRIPT_DIR/../lib/init.sh" ] && source "$SCRIPT_DIR/../lib/init.sh" 2>/dev/null || true
|
||||
|
||||
# Color codes
|
||||
# Color codes (fallbacks if init.sh not loaded)
|
||||
: "${GREEN:=\033[0;32m}"
|
||||
: "${RED:=\033[0;31m}"
|
||||
: "${YELLOW:=\033[1;33m}"
|
||||
: "${NC:=\033[0m}"
|
||||
log_info() { echo "$@"; }
|
||||
log_success() { echo "$@"; }
|
||||
log_warn() { echo "$@"; }
|
||||
log_error() { echo "$@" >&2; }
|
||||
|
||||
echo "==================================================================="
|
||||
echo " CHAIN-138 FULL DEPLOYMENT VERIFICATION"
|
||||
@@ -13,9 +23,17 @@ echo "==================================================================="
|
||||
|
||||
# Load environment variables
|
||||
if [ -f .env ]; then
|
||||
set +u
|
||||
source .env 2>/dev/null || true
|
||||
set -u 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Optional vars (allow unset for graceful checks)
|
||||
CHAIN138_CCIP_REPORTER="${CHAIN138_CCIP_REPORTER:-}"
|
||||
CCIP_CHAIN138_ROUTER="${CCIP_CHAIN138_ROUTER:-$CCIP_ROUTER}"
|
||||
CHAIN138_CCIP_WETH9_BRIDGE="${CHAIN138_CCIP_WETH9_BRIDGE:-$CCIPWETH9_BRIDGE_CHAIN138}"
|
||||
CHAIN138_CCIP_WETH10_BRIDGE="${CHAIN138_CCIP_WETH10_BRIDGE:-$CCIPWETH10_BRIDGE_CHAIN138}"
|
||||
|
||||
ERRORS=0
|
||||
WARNINGS=0
|
||||
SUCCESS=0
|
||||
@@ -133,7 +151,7 @@ if [ -n "$CHAIN138_CCIP_REPORTER" ] && [ "$CHAIN138_CCIP_REPORTER" != "" ]; then
|
||||
check_status "CCIPTxReporter" "warning" "$CHAIN138_CCIP_REPORTER (address in .env, cannot verify on-chain)"
|
||||
fi
|
||||
else
|
||||
check_status "CCIPTxReporter" "error" "Not deployed (no address in .env)"
|
||||
check_status "CCIPTxReporter" "warning" "Not deployed (optional; set CHAIN138_CCIP_REPORTER when deployed)"
|
||||
fi
|
||||
|
||||
# CCIP Router on Chain-138
|
||||
@@ -236,7 +254,7 @@ if [ -f "genesis.json" ]; then
|
||||
check_status "WETH10 in Genesis" "warning" "Not found in genesis.json"
|
||||
fi
|
||||
else
|
||||
check_status "Genesis File" "error" "genesis.json not found"
|
||||
check_status "Genesis File" "warning" "genesis.json not found (optional for RPC-only Chain 138)"
|
||||
fi
|
||||
|
||||
# Check .env configuration
|
||||
|
||||
75
scripts/deployment/verify-cronos-contracts.sh
Executable file
75
scripts/deployment/verify-cronos-contracts.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verify all four Cronos contracts via Etherscan-style API.
|
||||
# Uses explorer-api.cronos.org (module/action, solidity-standard-json-input).
|
||||
# Run from smom-dbis-138/
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
if [ -z "${CRONOSCAN_API_KEY:-}" ]; then
|
||||
echo "ERROR: CRONOSCAN_API_KEY not set. Set in .env (from explorer.cronos.org/register)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export CRONOSCAN_API_KEY
|
||||
|
||||
echo "Cronos verification (Etherscan-style API)"
|
||||
echo " API: https://explorer-api.cronos.org/mainnet/api"
|
||||
echo " Chain: cronos (from foundry.toml)"
|
||||
echo ""
|
||||
|
||||
verify() {
|
||||
local addr="$1"
|
||||
local contract="$2"
|
||||
local extra_args="${3:-}"
|
||||
echo "Verifying $contract at $addr..."
|
||||
# shellcheck disable=SC2086
|
||||
if forge verify-contract \
|
||||
"$addr" "$contract" \
|
||||
--chain cronos \
|
||||
--etherscan-api-key "$CRONOSCAN_API_KEY" \
|
||||
--skip-is-verified-check \
|
||||
$extra_args \
|
||||
--watch 2>&1; then
|
||||
echo " ✓ $contract verified"
|
||||
else
|
||||
echo " ✗ $contract verification failed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
FAIL=0
|
||||
|
||||
# WETH9 - no constructor args
|
||||
verify "0x99B3511A2d315A497C8112C1fdd8D508d4B1E506" "contracts/tokens/WETH.sol:WETH" || FAIL=$((FAIL+1))
|
||||
|
||||
# WETH10 - no constructor args
|
||||
verify "0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6" "contracts/tokens/WETH10.sol:WETH10" || FAIL=$((FAIL+1))
|
||||
|
||||
# CCIPWETH9Bridge - constructor(router, weth9, linkToken)
|
||||
verify "0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e" "contracts/ccip/CCIPWETH9Bridge.sol:CCIPWETH9Bridge" \
|
||||
"--constructor-args $(cast abi-encode 'constructor(address,address,address)' 0xE26B0A098D861d5C7d9434aD471c0572Ca6EAa67 0x99B3511A2d315A497C8112C1fdd8D508d4B1E506 0x8c80A01F461f297Df7F9DA3A4f740D7297C8Ac85)" || FAIL=$((FAIL+1))
|
||||
|
||||
# CCIPWETH10Bridge - constructor(router, weth10, linkToken)
|
||||
verify "0x105F8A15b819948a89153505762444Ee9f324684" "contracts/ccip/CCIPWETH10Bridge.sol:CCIPWETH10Bridge" \
|
||||
"--constructor-args $(cast abi-encode 'constructor(address,address,address)' 0xE26B0A098D861d5C7d9434aD471c0572Ca6EAa67 0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6 0x8c80A01F461f297Df7F9DA3A4f740D7297C8Ac85)" || FAIL=$((FAIL+1))
|
||||
|
||||
echo ""
|
||||
if [ "$FAIL" -eq 0 ]; then
|
||||
echo "All four Cronos contracts verified."
|
||||
exit 0
|
||||
else
|
||||
echo "$FAIL contract(s) failed."
|
||||
echo ""
|
||||
echo "Manual verification (recommended):"
|
||||
echo " 1. ./scripts/deployment/export-cronos-verification-sources.sh"
|
||||
echo " 2. Open https://explorer.cronos.org/verifyContract"
|
||||
echo " 3. Follow docs/deployment/CRONOS_VERIFICATION_RUNBOOK.md"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
72
scripts/deployment/verify-deployed-contracts.sh
Executable file
72
scripts/deployment/verify-deployed-contracts.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verify deployed contracts on Avalanche, Arbitrum, Cronos.
|
||||
# Requires ETHERSCAN_API_KEY (or SNOWTRACE_API_KEY, ARBISCAN_API_KEY, CRONOSCAN_API_KEY per chain).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
if [ -z "${ETHERSCAN_API_KEY:-}" ]; then
|
||||
echo "ERROR: ETHERSCAN_API_KEY not set. Set in .env or export."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export SNOWTRACE_API_KEY="${SNOWTRACE_API_KEY:-$ETHERSCAN_API_KEY}"
|
||||
export ARBISCAN_API_KEY="${ARBISCAN_API_KEY:-$ETHERSCAN_API_KEY}"
|
||||
# Cronos not in Etherscan V2; needs separate CRONOSCAN_API_KEY from cronoscan.com (no fallback)
|
||||
|
||||
verify_one() {
|
||||
local addr="$1"
|
||||
local contract="$2"
|
||||
local chain_arg="$3"
|
||||
local chain_name="$4"
|
||||
echo "Verifying $contract at $addr on $chain_name..."
|
||||
# shellcheck disable=SC2086
|
||||
forge verify-contract "$addr" "$contract" $chain_arg \
|
||||
--etherscan-api-key "${ETHERSCAN_API_KEY}" \
|
||||
--watch 2>/dev/null || echo " (may already be verified or need chain-specific API key)"
|
||||
}
|
||||
|
||||
# Avalanche 43114
|
||||
for addr in 0xa4B9DD039565AeD9641D45b57061f99d9cA6Df08 0x89dd12025bfCD38A168455A44B400e913ED33BE2 0xe0E93247376aa097dB308B92e6Ba36bA015535D0 0xAb57BF30F1354CA0590af22D8974c7f24DB2DbD7; do
|
||||
case "$addr" in
|
||||
0xa4B9DD039565AeD9641D45b57061f99d9cA6Df08) c="contracts/tokens/WETH.sol:WETH" ;;
|
||||
0x89dd12025bfCD38A168455A44B400e913ED33BE2) c="contracts/tokens/WETH10.sol:WETH10" ;;
|
||||
0xe0E93247376aa097dB308B92e6Ba36bA015535D0) c="contracts/ccip/CCIPWETH9Bridge.sol:CCIPWETH9Bridge" ;;
|
||||
0xAb57BF30F1354CA0590af22D8974c7f24DB2DbD7) c="contracts/ccip/CCIPWETH10Bridge.sol:CCIPWETH10Bridge" ;;
|
||||
esac
|
||||
verify_one "$addr" "$c" "--chain avalanche" "Avalanche"
|
||||
done
|
||||
|
||||
# Arbitrum 42161
|
||||
for addr in 0x89dd12025bfCD38A168455A44B400e913ED33BE2 0xe0E93247376aa097dB308B92e6Ba36bA015535D0 0xAb57BF30F1354CA0590af22D8974c7f24DB2DbD7 0xa780ef19A041745d353c9432f2a7f5A241335ffE; do
|
||||
case "$addr" in
|
||||
0x89dd12025bfCD38A168455A44B400e913ED33BE2) c="contracts/tokens/WETH.sol:WETH" ;;
|
||||
0xe0E93247376aa097dB308B92e6Ba36bA015535D0) c="contracts/tokens/WETH10.sol:WETH10" ;;
|
||||
0xAb57BF30F1354CA0590af22D8974c7f24DB2DbD7) c="contracts/ccip/CCIPWETH9Bridge.sol:CCIPWETH9Bridge" ;;
|
||||
0xa780ef19A041745d353c9432f2a7f5A241335ffE) c="contracts/ccip/CCIPWETH10Bridge.sol:CCIPWETH10Bridge" ;;
|
||||
esac
|
||||
verify_one "$addr" "$c" "--chain arbitrum" "Arbitrum"
|
||||
done
|
||||
|
||||
# Cronos 25 — API: explorer-api.cronos.org/mainnet. Forge Blockscout verifier incompatible.
|
||||
# Try: ./scripts/deployment/verify-cronos-contracts.sh (may fail; use manual fallback)
|
||||
# See docs/04-configuration/CRONOS_EXPLORER_OPERATIONS.md
|
||||
if [ -n "${CRONOSCAN_API_KEY:-}" ]; then
|
||||
echo ""
|
||||
echo "Cronos contracts: run ./scripts/deployment/verify-cronos-contracts.sh"
|
||||
echo "If that fails, manual verification: export-cronos-verification-sources.sh then CRONOS_VERIFICATION_RUNBOOK.md"
|
||||
echo " WETH9: 0x99B3511A2d315A497C8112C1fdd8D508d4B1E506"
|
||||
echo " WETH10: 0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6"
|
||||
echo " CCIPWETH9: 0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e"
|
||||
echo " CCIPWETH10: 0x105F8A15b819948a89153505762444Ee9f324684"
|
||||
echo ""
|
||||
else
|
||||
echo "Skipping Cronos: set CRONOSCAN_API_KEY (from explorer.cronos.org) for manual verification."
|
||||
fi
|
||||
|
||||
echo "Verification complete."
|
||||
121
scripts/deployment/verify-trustless-deployments.sh
Executable file
121
scripts/deployment/verify-trustless-deployments.sh
Executable file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verify deployed Trustless Bridge contracts (BondManager, LiquidityPool, Inbox, Lockbox) on each chain.
|
||||
# Uses dotenv at smom-dbis-138/.env. Requires: cast (Foundry).
|
||||
# Exit 0 if all checked addresses have code; non-zero if any missing.
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
DOTENV="$REPO_ROOT/.env"
|
||||
cd "$REPO_ROOT"
|
||||
[[ -f "$DOTENV" ]] && set -a && source "$DOTENV" && set +a
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
FAILED_CHAINS=""
|
||||
|
||||
check_addr() {
|
||||
local label="$1"
|
||||
local addr="$2"
|
||||
local rpc="$3"
|
||||
if [[ -z "$addr" || "$addr" == "0x"*"..." ]]; then return; fi
|
||||
local code
|
||||
code=$(cast code "$addr" --rpc-url "$rpc" 2>/dev/null || true)
|
||||
if [[ -n "$code" && "${#code}" -gt 2 ]]; then
|
||||
echo " OK $label $addr"
|
||||
PASS=$((PASS+1))
|
||||
return 0
|
||||
else
|
||||
echo " FAIL $label $addr (no code or RPC error)"
|
||||
FAIL=$((FAIL+1))
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
verify_chain() {
|
||||
local name="$1"
|
||||
local rpc="$2"
|
||||
shift 2
|
||||
if [[ -z "$rpc" ]]; then echo "Skip $name (no RPC)"; return; fi
|
||||
echo "--- $name ---"
|
||||
local any_fail=0
|
||||
while [[ $# -ge 2 ]]; do
|
||||
check_addr "$1" "$2" "$rpc" || any_fail=1
|
||||
shift 2
|
||||
done
|
||||
if [[ $any_fail -ne 0 ]]; then FAILED_CHAINS="$FAILED_CHAINS $name"; fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Mainnet (Ethereum)
|
||||
verify_chain "Ethereum Mainnet" "${ETHEREUM_MAINNET_RPC:-}" \
|
||||
"BOND_MANAGER" "${BOND_MANAGER_MAINNET:-}" \
|
||||
"LIQUIDITY_POOL" "${LIQUIDITY_POOL_ETH_MAINNET:-}" \
|
||||
"INBOX" "${INBOX_ETH_MAINNET:-}"
|
||||
|
||||
# Chain 138
|
||||
verify_chain "Chain 138" "${RPC_URL_138:-${CHAIN_138_RPC_URL:-}}" \
|
||||
"LOCKBOX_138" "${LOCKBOX_138:-}"
|
||||
|
||||
# BSC
|
||||
verify_chain "BSC" "${BSC_RPC_URL:-}" \
|
||||
"BOND_MANAGER" "${BSC_BOND_MANAGER:-}" \
|
||||
"LIQUIDITY_POOL" "${BSC_LIQUIDITY_POOL_ETH:-}" \
|
||||
"INBOX" "${BSC_INBOX_ETH:-}" \
|
||||
"LOCKBOX" "${BSC_LOCKBOX:-}"
|
||||
|
||||
# Polygon
|
||||
verify_chain "Polygon" "${POLYGON_MAINNET_RPC:-}" \
|
||||
"BOND_MANAGER" "${POLYGON_BOND_MANAGER:-}" \
|
||||
"LIQUIDITY_POOL" "${POLYGON_LIQUIDITY_POOL_ETH:-}" \
|
||||
"INBOX" "${POLYGON_INBOX_ETH:-}" \
|
||||
"LOCKBOX" "${POLYGON_LOCKBOX:-}"
|
||||
|
||||
# Base
|
||||
verify_chain "Base" "${BASE_MAINNET_RPC:-}" \
|
||||
"BOND_MANAGER" "${BASE_BOND_MANAGER:-}" \
|
||||
"LIQUIDITY_POOL" "${BASE_LIQUIDITY_POOL_ETH:-}" \
|
||||
"INBOX" "${BASE_INBOX_ETH:-}" \
|
||||
"LOCKBOX" "${BASE_LOCKBOX:-}"
|
||||
|
||||
# Optimism
|
||||
verify_chain "Optimism" "${OPTIMISM_MAINNET_RPC:-}" \
|
||||
"BOND_MANAGER" "${OPTIMISM_BOND_MANAGER:-}" \
|
||||
"LIQUIDITY_POOL" "${OPTIMISM_LIQUIDITY_POOL_ETH:-}" \
|
||||
"INBOX" "${OPTIMISM_INBOX_ETH:-}" \
|
||||
"LOCKBOX" "${OPTIMISM_LOCKBOX:-}"
|
||||
|
||||
# Cronos
|
||||
verify_chain "Cronos" "${CRONOS_RPC_URL:-}" \
|
||||
"BOND_MANAGER" "${CRONOS_BOND_MANAGER:-}" \
|
||||
"LIQUIDITY_POOL" "${CRONOS_LIQUIDITY_POOL_ETH:-}" \
|
||||
"INBOX" "${CRONOS_INBOX_ETH:-}" \
|
||||
"LOCKBOX" "${CRONOS_LOCKBOX:-}"
|
||||
|
||||
# Arbitrum (addresses from deployment run; may not be in .env)
|
||||
verify_chain "Arbitrum" "${ARBITRUM_MAINNET_RPC:-}" \
|
||||
"BOND_MANAGER" "${ARBITRUM_BOND_MANAGER:-0x26Eb0AC01BAb5756c73945d48e2B8e28D6b32287}" \
|
||||
"LIQUIDITY_POOL" "${ARBITRUM_LIQUIDITY_POOL_ETH:-0x866aCe8664FF40E0a8842705E0D140E614eCc67B}" \
|
||||
"INBOX" "${ARBITRUM_INBOX_ETH:-0xb1061A71412E18F66FF8D043e3F0682532ECdaf7}" \
|
||||
"LOCKBOX" "${ARBITRUM_LOCKBOX:-0x57f8b4DB2d92CAB6093405b53158ab3224D37D24}"
|
||||
|
||||
# Avalanche
|
||||
verify_chain "Avalanche" "${AVALANCHE_RPC_URL:-${AVALANCHE_MAINNET_RPC:-}}" \
|
||||
"BOND_MANAGER" "${AVALANCHE_BOND_MANAGER:-0xD1695ed8F7683EE5d1BF55ed34585B22F474a7ef}" \
|
||||
"LIQUIDITY_POOL" "${AVALANCHE_LIQUIDITY_POOL_ETH:-0xb6D2f38b9015F32ccE8818509c712264E7fceeD3}" \
|
||||
"INBOX" "${AVALANCHE_INBOX_ETH:-0x866aCe8664FF40E0a8842705E0D140E614eCc67B}" \
|
||||
"LOCKBOX" "${AVALANCHE_LOCKBOX:-0x7e6fB8D80f81430e560F8232b2A4fd06249d74ce}"
|
||||
|
||||
# Gnosis
|
||||
verify_chain "Gnosis" "${GNOSIS_MAINNET_RPC:-}" \
|
||||
"BOND_MANAGER" "${GNOSIS_BOND_MANAGER:-0x73376eB92c16977B126dB9112936A20Fa0De3442}" \
|
||||
"LIQUIDITY_POOL" "${GNOSIS_LIQUIDITY_POOL_ETH:-0xb689c1C69DAa08DEb5D8feA2aBF0F64bFD409727}" \
|
||||
"INBOX" "${GNOSIS_INBOX_ETH:-0x4C38F9A5ed68A04cd28a72E8c68C459Ec34576f3}" \
|
||||
"LOCKBOX" "${GNOSIS_LOCKBOX:-0x0CA60e6f8589c540200daC9D9Cb27BC2e48eE66A}"
|
||||
|
||||
echo "=============================================="
|
||||
echo "Summary: $PASS passed, $FAIL failed"
|
||||
if [[ -n "$FAILED_CHAINS" ]]; then
|
||||
echo "Chains with failures:$FAILED_CHAINS"
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
@@ -13,9 +13,12 @@ load_env() {
|
||||
local env_file="${1:-${PROJECT_ROOT}/.env}"
|
||||
|
||||
if [ -f "$env_file" ]; then
|
||||
# Export variables, ignoring comments and empty lines
|
||||
# Export variables, ignoring comments and empty lines.
|
||||
# Disable set -e so a failing command in .env (e.g. command substitution) does not exit the shell.
|
||||
set -a
|
||||
source <(grep -v '^#' "$env_file" | grep -v '^$' | sed 's/^/export /')
|
||||
set +e
|
||||
source <(grep -v '^#' "$env_file" | grep -v '^$' | sed 's/^/export /') 2>/dev/null || true
|
||||
set -e
|
||||
set +a
|
||||
fi
|
||||
}
|
||||
|
||||
62
scripts/lib/deployment/README.md
Normal file
62
scripts/lib/deployment/README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Deployment script library
|
||||
|
||||
Reusable helpers for deployment scripts: **tag-based CLI** (no .env placeholders for one-off values), **interactive prompts** when run without args, and **callable modular linking** so scripts can invoke each other with arguments.
|
||||
|
||||
## Conventions
|
||||
|
||||
- **Secrets and chain config** stay in `.env` (e.g. `PRIVATE_KEY`, RPC URLs, contract addresses).
|
||||
- **One-off or per-run values** are passed via **script tags** (e.g. `--eth 1.5`, `--chain bsc polygon`, `--lockbox`), not .env.
|
||||
- Scripts that accept amounts **prompt interactively** when run with no args and stdin is a TTY.
|
||||
- Scripts are **callable** from other scripts by passing the same tags (e.g. `run-all-four-gaps.sh g4 --eth 1`).
|
||||
|
||||
## Modules
|
||||
|
||||
| File | Purpose |
|
||||
|------|--------|
|
||||
| `prompts.sh` | Tag parsers: `parse_fund_tags` (--eth, --weth, --dry-run), `prompt_fund_amounts`, `eth_to_wei`, `parse_phase_tags` (g1, g2g3, g4), `parse_chain_filter` (--chain bsc polygon ...), `parse_lockbox_tag` (--lockbox / --no-lockbox), `parse_link_tags` (--link, --dry-run), `parse_dry_run_tag`, `parse_deploy_tag` (--deploy), `parse_delay_tag` (--delay). `L2_CHAIN_NAMES`, `normalize_chain_name`. |
|
||||
| `dotenv.sh` | `load_deployment_env`, `require_fund_lp_env`. |
|
||||
| `costs.sh` | Gas and cost helpers (existing). |
|
||||
|
||||
## Validate syntax (one command)
|
||||
|
||||
- **From this repo** (`smom-dbis-138`):
|
||||
`./scripts/deployment/check-syntax.sh`
|
||||
- **From workspace root** (e.g. `proxmox`):
|
||||
`./smom-dbis-138/scripts/deployment/check-syntax.sh`
|
||||
|
||||
Checks all tag-based deployment scripts and the lib with `bash -n`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# From any script in scripts/deployment:
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
|
||||
source "$SCRIPT_DIR/../lib/deployment/prompts.sh"
|
||||
load_deployment_env
|
||||
|
||||
# Parse G4 amounts from args, then prompt if still empty (TTY)
|
||||
parse_fund_tags "$@"
|
||||
prompt_fund_amounts
|
||||
# Use FUND_ETH_AMOUNT_WEI, FUND_WETH_AMOUNT_WEI
|
||||
```
|
||||
|
||||
## Example: G4 fund mainnet LP
|
||||
|
||||
- **Standalone:** `./scripts/deployment/fund-mainnet-lp.sh --eth 1.5 --weth 0.5`
|
||||
- **Interactive:** `./scripts/deployment/fund-mainnet-lp.sh`
|
||||
- **From run-all:** `./scripts/deployment/run-all-four-gaps.sh g4 --eth 1`
|
||||
|
||||
No `FUND_ETH_AMOUNT_WEI` / `FUND_WETH_AMOUNT_WEI` in .env.
|
||||
|
||||
## Other scripts (tags)
|
||||
|
||||
| Script | Tags |
|
||||
|--------|------|
|
||||
| deploy-pmm-all-l2s.sh | --chain bsc polygon ... (or DEPLOY_PMM_L2S_FILTER in .env) |
|
||||
| live-test-trustless-bridge.sh | --check (optional: print LP stats and BondManager totalEthHeld); prints cast commands for lock → claim → finalize → release |
|
||||
| deploy-trustless-l2s.sh | --chain, --lockbox / --no-lockbox |
|
||||
| fund-ccip-bridges-with-link.sh | --link amount, --dry-run |
|
||||
| fix-nonce-and-retry.sh | --chain, --script (positional still supported) |
|
||||
| run-remaining-g2g3-with-nonce-fix.sh | --delay, --lockbox / --no-lockbox |
|
||||
| check-balances-gas-and-deploy.sh | --deploy |
|
||||
51
scripts/lib/deployment/dotenv.sh
Normal file
51
scripts/lib/deployment/dotenv.sh
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# Load deployment .env and require common vars.
|
||||
# Usage: source "$SCRIPT_DIR/lib/deployment/dotenv.sh"
|
||||
# Optional: load_deployment_env [--repo-root <path>]
|
||||
#
|
||||
# Correct dotenv file (in order):
|
||||
# 1. ENV_FILE if set and the file exists (e.g. export ENV_FILE=/path/to/.env)
|
||||
# 2. PROJECT_ROOT/.env (repo root; PROJECT_ROOT = scripts/lib/deployment/../.. when unset)
|
||||
# So: use repo-root .env by default; set ENV_FILE to use a different file.
|
||||
|
||||
_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
[[ -z "${PROJECT_ROOT:-}" ]] && PROJECT_ROOT="$(cd "$_LIB_DIR/../.." && pwd)"
|
||||
|
||||
# Preferred .env: ENV_FILE if set and readable; else PROJECT_ROOT/.env (repo root).
|
||||
load_deployment_env() {
|
||||
local root="${PROJECT_ROOT}"
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--repo-root) root="$2"; shift 2 ;;
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
export PROJECT_ROOT="$root"
|
||||
local dotenv="${root}/.env"
|
||||
[[ -n "${ENV_FILE:-}" && -f "${ENV_FILE}" ]] && dotenv="${ENV_FILE}"
|
||||
if [[ -f "$dotenv" ]]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
source "$dotenv"
|
||||
set +a
|
||||
fi
|
||||
}
|
||||
|
||||
# Require vars for mainnet LP funding (G4). Fails with message if missing.
|
||||
require_fund_lp_env() {
|
||||
load_deployment_env
|
||||
: "${LIQUIDITY_POOL_ETH_MAINNET:=${LIQUIDITY_POOL:-}}"
|
||||
if [[ -z "${LIQUIDITY_POOL_ETH_MAINNET:-}" ]]; then
|
||||
echo "Set LIQUIDITY_POOL_ETH_MAINNET (or LIQUIDITY_POOL) in .env" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ -z "${ETHEREUM_MAINNET_RPC:-}" ]]; then
|
||||
echo "Set ETHEREUM_MAINNET_RPC in .env" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ -z "${PRIVATE_KEY:-}" ]]; then
|
||||
echo "Set PRIVATE_KEY in .env" >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
247
scripts/lib/deployment/prompts.sh
Normal file
247
scripts/lib/deployment/prompts.sh
Normal file
@@ -0,0 +1,247 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deployment tag parsing and interactive prompts.
|
||||
# Usage: source "$SCRIPT_DIR/lib/deployment/prompts.sh"
|
||||
# Provides: parse_fund_tags, prompt_fund_amounts, eth_to_wei, parse_phase_tags
|
||||
|
||||
# Resolve lib and project paths when sourced
|
||||
_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
[[ -z "${PROJECT_ROOT:-}" ]] && PROJECT_ROOT="$(cd "$_LIB_DIR/../.." && pwd)"
|
||||
|
||||
# Convert ETH string to wei (supports "1.5", "1.5eth", "1000000000000000000" or "1000000000000000000wei")
|
||||
eth_to_wei() {
|
||||
local val="${1:-0}"
|
||||
if [[ -z "$val" || "$val" == "0" ]]; then
|
||||
echo "0"
|
||||
return 0
|
||||
fi
|
||||
if [[ "$val" == *wei ]]; then
|
||||
echo "${val%wei}"
|
||||
return 0
|
||||
fi
|
||||
if [[ "$val" == *eth ]]; then
|
||||
val="${val%eth}"
|
||||
fi
|
||||
if command -v cast &>/dev/null; then
|
||||
cast to-wei "$val" ether 2>/dev/null || echo "0"
|
||||
else
|
||||
# Fallback: 1 eth = 1e18 (bash can't do float well; use bc/python if available)
|
||||
if command -v python3 &>/dev/null; then
|
||||
python3 -c "import math; print(int(float('$val') * 10**18))" 2>/dev/null || echo "0"
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Parse --eth, --weth, --eth-wei, --weth-wei, --dry-run from "$@".
|
||||
# Sets: FUND_ETH_AMOUNT_WEI, FUND_WETH_AMOUNT_WEI (exported), DRY_RUN=1 if --dry-run.
|
||||
# Consumed args are removed from the array; use parse_fund_tags "${@}" before other parsers.
|
||||
parse_fund_tags() {
|
||||
export FUND_ETH_AMOUNT_WEI="${FUND_ETH_AMOUNT_WEI:-0}"
|
||||
export FUND_WETH_AMOUNT_WEI="${FUND_WETH_AMOUNT_WEI:-0}"
|
||||
export DRY_RUN="${DRY_RUN:-0}"
|
||||
local args=()
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--eth)
|
||||
FUND_ETH_AMOUNT_WEI="$(eth_to_wei "${2:-0}")"
|
||||
shift 2
|
||||
;;
|
||||
--weth)
|
||||
FUND_WETH_AMOUNT_WEI="$(eth_to_wei "${2:-0}")"
|
||||
shift 2
|
||||
;;
|
||||
--eth-wei)
|
||||
FUND_ETH_AMOUNT_WEI="${2:-0}"
|
||||
shift 2
|
||||
;;
|
||||
--weth-wei)
|
||||
FUND_WETH_AMOUNT_WEI="${2:-0}"
|
||||
shift 2
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# Return unconsumed args (caller can set PARSE_FUND_TAGS_REMAINING=( "${args[@]}" ) or use as needed)
|
||||
PARSE_FUND_TAGS_REMAINING=("${args[@]}")
|
||||
}
|
||||
|
||||
# Interactive prompt for ETH/WETH amounts (only if both are 0 and stdin is a TTY).
|
||||
# Sets FUND_ETH_AMOUNT_WEI and FUND_WETH_AMOUNT_WEI (exported).
|
||||
prompt_fund_amounts() {
|
||||
local eth_wei="${FUND_ETH_AMOUNT_WEI:-0}"
|
||||
local weth_wei="${FUND_WETH_AMOUNT_WEI:-0}"
|
||||
if [[ -n "$eth_wei" && "$eth_wei" != "0" ]] || [[ -n "$weth_wei" && "$weth_wei" != "0" ]]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ ! -t 0 ]]; then
|
||||
return 0
|
||||
fi
|
||||
echo "G4: Fund mainnet Liquidity Pool (ETH and/or WETH)."
|
||||
read -r -p "ETH amount (e.g. 1.5 or 0 to skip): " eth_input
|
||||
read -r -p "WETH amount (e.g. 0.5 or 0 to skip): " weth_input
|
||||
export FUND_ETH_AMOUNT_WEI="$(eth_to_wei "${eth_input:-0}")"
|
||||
export FUND_WETH_AMOUNT_WEI="$(eth_to_wei "${weth_input:-0}")"
|
||||
}
|
||||
|
||||
# Parse phase tags: g1, g2, g3, g2g3, g4 from "$@".
|
||||
# Sets: RUN_G1, RUN_G2G3, RUN_G4 (0 or 1). Unconsumed args left in PARSE_PHASE_TAGS_REMAINING.
|
||||
parse_phase_tags() {
|
||||
RUN_G1=0
|
||||
RUN_G2G3=0
|
||||
RUN_G4=0
|
||||
local args=()
|
||||
for arg in "$@"; do
|
||||
case "${arg,,}" in
|
||||
g1) RUN_G1=1 ;;
|
||||
g2|g3|g2g3) RUN_G2G3=1 ;;
|
||||
g4) RUN_G4=1 ;;
|
||||
*) args+=("$arg") ;;
|
||||
esac
|
||||
done
|
||||
# If no phase given, run all
|
||||
if [[ "$RUN_G1" -eq 0 && "$RUN_G2G3" -eq 0 && "$RUN_G4" -eq 0 ]]; then
|
||||
RUN_G1=1
|
||||
RUN_G2G3=1
|
||||
RUN_G4=1
|
||||
fi
|
||||
PARSE_PHASE_TAGS_REMAINING=("${args[@]}")
|
||||
}
|
||||
|
||||
# Canonical L2 list for deploy-pmm, deploy-trustless, fund-ccip, etc.
|
||||
L2_CHAIN_NAMES=( BSC POLYGON BASE OPTIMISM ARBITRUM AVALANCHE CRONOS GNOSIS )
|
||||
|
||||
# Parse --chain <name> [<name> ...] from "$@". Names case-insensitive (bsc, BSC, Polygon, etc.).
|
||||
# Sets CHAIN_FILTER=() (empty = all) or CHAIN_FILTER=( BSC POLYGON ... ). Unconsumed in PARSE_CHAIN_FILTER_REMAINING.
|
||||
normalize_chain_name() {
|
||||
case "${1^^}" in
|
||||
BSC) echo BSC ;;
|
||||
POLYGON) echo POLYGON ;;
|
||||
BASE) echo BASE ;;
|
||||
OPTIMISM) echo OPTIMISM ;;
|
||||
ARBITRUM) echo ARBITRUM ;;
|
||||
AVALANCHE) echo AVALANCHE ;;
|
||||
CRONOS) echo CRONOS ;;
|
||||
GNOSIS) echo GNOSIS ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
parse_chain_filter() {
|
||||
CHAIN_FILTER=()
|
||||
local args=()
|
||||
local collecting=0
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == "--chain" ]]; then
|
||||
collecting=1
|
||||
elif [[ "$collecting" -eq 1 ]]; then
|
||||
local n; n="$(normalize_chain_name "$arg")"
|
||||
if [[ -n "$n" ]]; then
|
||||
CHAIN_FILTER+=("$n")
|
||||
else
|
||||
args+=("$arg")
|
||||
collecting=0
|
||||
fi
|
||||
else
|
||||
args+=("$arg")
|
||||
fi
|
||||
done
|
||||
PARSE_CHAIN_FILTER_REMAINING=("${args[@]}")
|
||||
}
|
||||
|
||||
# Parse --lockbox / --no-lockbox. Sets TRUSTLESS_DEPLOY_LOCKBOX=1 or 0. Default from env or 0.
|
||||
# Unconsumed in PARSE_LOCKBOX_REMAINING.
|
||||
parse_lockbox_tag() {
|
||||
TRUSTLESS_DEPLOY_LOCKBOX="${TRUSTLESS_DEPLOY_LOCKBOX:-0}"
|
||||
local args=()
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--lockbox) TRUSTLESS_DEPLOY_LOCKBOX=1; ;;
|
||||
--no-lockbox) TRUSTLESS_DEPLOY_LOCKBOX=0; ;;
|
||||
*) args+=("$arg") ;;
|
||||
esac
|
||||
done
|
||||
PARSE_LOCKBOX_REMAINING=("${args[@]}")
|
||||
}
|
||||
|
||||
# Parse --link <amount> (ETH or wei if --link-wei), --dry-run. Sets LINK_AMOUNT_WEI, DRY_RUN.
|
||||
# Default LINK_AMOUNT_WEI 10e18 (10 LINK) when unset. Unconsumed in PARSE_LINK_TAGS_REMAINING.
|
||||
link_to_wei() {
|
||||
local val="${1:-0}"
|
||||
if [[ -z "$val" || "$val" == "0" ]]; then echo "0"; return; fi
|
||||
if [[ "$val" == *wei ]]; then echo "${val%wei}"; return; fi
|
||||
if command -v cast &>/dev/null; then
|
||||
cast to-wei "$val" ether 2>/dev/null || echo "0"
|
||||
elif command -v python3 &>/dev/null; then
|
||||
python3 -c "import math; print(int(float('$val') * 10**18))" 2>/dev/null || echo "0"
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
parse_link_tags() {
|
||||
export LINK_AMOUNT_WEI="${LINK_AMOUNT_WEI:-10000000000000000000}"
|
||||
export DRY_RUN="${DRY_RUN:-0}"
|
||||
local args=()
|
||||
local i=0
|
||||
local argv=("$@")
|
||||
while [[ $i -lt ${#argv[@]} ]]; do
|
||||
local a="${argv[$i]}"
|
||||
case "$a" in
|
||||
--link)
|
||||
[[ $((i+1)) -lt ${#argv[@]} ]] && LINK_AMOUNT_WEI="$(link_to_wei "${argv[$((i+1))]}")"
|
||||
i=$((i+2)); ;;
|
||||
--link-wei)
|
||||
[[ $((i+1)) -lt ${#argv[@]} ]] && LINK_AMOUNT_WEI="${argv[$((i+1))]}"
|
||||
i=$((i+2)); ;;
|
||||
--dry-run) DRY_RUN=1; i=$((i+1)); ;;
|
||||
*) args+=("$a"); i=$((i+1)); ;;
|
||||
esac
|
||||
done
|
||||
PARSE_LINK_TAGS_REMAINING=("${args[@]}")
|
||||
}
|
||||
|
||||
# Parse --dry-run only. Sets DRY_RUN=1. Unconsumed in PARSE_DRY_RUN_REMAINING.
|
||||
parse_dry_run_tag() {
|
||||
DRY_RUN="${DRY_RUN:-0}"
|
||||
local args=()
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == "--dry-run" ]]; then DRY_RUN=1; else args+=("$arg"); fi
|
||||
done
|
||||
PARSE_DRY_RUN_REMAINING=("${args[@]}")
|
||||
}
|
||||
|
||||
# Parse --deploy. Sets DO_DEPLOY=1. Unconsumed in PARSE_DEPLOY_REMAINING.
|
||||
parse_deploy_tag() {
|
||||
DO_DEPLOY="${DO_DEPLOY:-0}"
|
||||
local args=()
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == "--deploy" ]]; then DO_DEPLOY=1; else args+=("$arg"); fi
|
||||
done
|
||||
PARSE_DEPLOY_REMAINING=("${args[@]}")
|
||||
}
|
||||
|
||||
# Parse --delay <seconds>. Sets DELAY_BETWEEN_CHAINS. Unconsumed in PARSE_DELAY_REMAINING.
|
||||
parse_delay_tag() {
|
||||
DELAY_BETWEEN_CHAINS="${DELAY_BETWEEN_CHAINS:-45}"
|
||||
local args=()
|
||||
local i=0
|
||||
local argv=("$@")
|
||||
while [[ $i -lt ${#argv[@]} ]]; do
|
||||
if [[ "${argv[$i]}" == "--delay" && $((i+1)) -lt ${#argv[@]} ]]; then
|
||||
DELAY_BETWEEN_CHAINS="${argv[$((i+1))]}"
|
||||
i=$((i+2))
|
||||
else
|
||||
args+=("${argv[$i]}")
|
||||
i=$((i+1))
|
||||
fi
|
||||
done
|
||||
PARSE_DELAY_REMAINING=("${args[@]}")
|
||||
}
|
||||
63
scripts/lib/infura.sh
Normal file
63
scripts/lib/infura.sh
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Infura RPC URL builder: uses INFURA_PROJECT_ID and optional INFURA_PROJECT_SECRET (Basic Auth).
|
||||
# Usage: source "$SCRIPT_DIR/lib/infura.sh" # then call build_infura_rpc "avalanche-mainnet"
|
||||
# When INFURA_PROJECT_SECRET is set, the URL uses Basic Auth (required for some operations e.g. eth_sendTransaction).
|
||||
# Set INFURA_PROJECT_ID and optionally INFURA_PROJECT_SECRET in .env; never commit secrets.
|
||||
|
||||
build_infura_rpc() {
|
||||
local host_path="${1:?Usage: build_infura_rpc <host-path> e.g. avalanche-mainnet}"
|
||||
local id="${INFURA_PROJECT_ID:-}"
|
||||
local secret="${INFURA_PROJECT_SECRET:-}"
|
||||
if [[ -z "$id" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local auth=""
|
||||
if [[ -n "$secret" && ! "$secret" =~ \$\{ ]]; then
|
||||
local encoded
|
||||
encoded=$(printf '%s' "$secret" | python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read(), safe=''))" 2>/dev/null) || encoded="$secret"
|
||||
auth="${id}:${encoded}@"
|
||||
fi
|
||||
echo "https://${auth}${host_path}.infura.io/v3/${id}"
|
||||
}
|
||||
|
||||
# Given any RPC URL, if it is an Infura URL (https://HOST.infura.io/v3/PROJECT_ID) and
|
||||
# INFURA_PROJECT_SECRET is set, return the same URL with Basic Auth so requests succeed.
|
||||
# If the URL already contains @ (already has auth), or is not Infura, return as-is.
|
||||
# Use this before passing .env RPC vars to cast/curl so Infura is accessed with the secret.
|
||||
ensure_infura_rpc_url() {
|
||||
local url="${1:-}"
|
||||
[[ -z "$url" ]] && echo "" && return 0
|
||||
[[ "$url" == *"@"* ]] && echo "$url" && return 0
|
||||
if [[ "$url" =~ ^https://([a-zA-Z0-9.-]+)\.infura\.io/v3/([a-zA-Z0-9]+)$ ]]; then
|
||||
local host="${BASH_REMATCH[1]}"
|
||||
local id="${BASH_REMATCH[2]}"
|
||||
local secret="${INFURA_PROJECT_SECRET:-}"
|
||||
if [[ -n "$secret" && ! "$secret" =~ \$\{ ]]; then
|
||||
local encoded
|
||||
encoded=$(printf '%s' "$secret" | python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read(), safe=''))" 2>/dev/null) || encoded="$secret"
|
||||
echo "https://${id}:${encoded}@${host}.infura.io/v3/${id}"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
echo "$url"
|
||||
}
|
||||
|
||||
# Build Infura Gas API URL for Ethereum mainnet (networks/1).
|
||||
# INFURA_GAS_API can be set to full URL; otherwise uses INFURA_PROJECT_ID.
|
||||
get_infura_gas_api_url() {
|
||||
local url="${INFURA_GAS_API:-}"
|
||||
if [[ -n "$url" ]]; then
|
||||
if [[ "$url" == *"/v3/"* ]]; then
|
||||
local key="${url#*v3/}"
|
||||
key="${key%%/*}"
|
||||
echo "https://gas.api.infura.io/v3/${key}/networks/1/suggestedGasFees"
|
||||
return
|
||||
fi
|
||||
echo "$url"
|
||||
return
|
||||
fi
|
||||
local id="${INFURA_PROJECT_ID:-}"
|
||||
if [[ -n "$id" ]]; then
|
||||
echo "https://gas.api.infura.io/v3/${id}/networks/1/suggestedGasFees"
|
||||
fi
|
||||
}
|
||||
@@ -33,5 +33,7 @@ source "${LIB_DIR}/config/regions.sh"
|
||||
source "${LIB_DIR}/azure/cli.sh" 2>/dev/null || true
|
||||
|
||||
# Log that libraries are loaded (only in debug mode)
|
||||
[ "${LOG_LEVEL:-1}" -le 0 ] && log_debug "Common libraries loaded from ${LIB_DIR}"
|
||||
# Use default 1 if LOG_LEVEL is unset or not numeric (e.g. from .env)
|
||||
_ll="${LOG_LEVEL:-1}"
|
||||
[[ "$_ll" =~ ^[0-9]+$ ]] && [ "$_ll" -le 0 ] && log_debug "Common libraries loaded from ${LIB_DIR}" || true
|
||||
|
||||
|
||||
20
scripts/load-env.sh
Normal file
20
scripts/load-env.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Source the correct dotenv for smom-dbis-138 (single source for deploy, relay, token-aggregation).
|
||||
# Uses repo-root .env unless ENV_FILE is already set. Export ENV_FILE so scripts using
|
||||
# scripts/lib/deployment/dotenv.sh (load_deployment_env) use the same file.
|
||||
# Usage: source scripts/load-env.sh (from smom-dbis-138)
|
||||
# source smom-dbis-138/scripts/load-env.sh (from repo root)
|
||||
# ENV_FILE=/path/to/.env source scripts/load-env.sh (override)
|
||||
# Do not execute; source it so variables are in the current shell.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
|
||||
[[ -z "${ENV_FILE:-}" ]] && ENV_FILE="${SCRIPT_DIR}/../.env"
|
||||
export ENV_FILE
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
set -a
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
echo "Loaded: $ENV_FILE"
|
||||
else
|
||||
echo "WARN: $ENV_FILE not found" >&2
|
||||
fi
|
||||
138
scripts/mint-100-tokens.sh
Executable file
138
scripts/mint-100-tokens.sh
Executable file
@@ -0,0 +1,138 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Mint 100 cUSDT and 100 cUSDC to a wallet address
|
||||
# Usage: ./mint-100-tokens.sh
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Change to script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
|
||||
# Load .env
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Try to use RPC_URL_138 first (if available), then RPC_URL, then fallback to public endpoint
|
||||
if [ -n "$RPC_URL_138" ]; then
|
||||
RPC_URL="$RPC_URL_138"
|
||||
elif [ -n "$RPC_URL" ]; then
|
||||
# Keep RPC_URL as is
|
||||
:
|
||||
else
|
||||
RPC_URL="https://rpc-http-pub.d-bis.org"
|
||||
fi
|
||||
|
||||
# Test RPC connectivity and fallback if needed
|
||||
if ! curl -s -X POST -H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||||
--max-time 3 "$RPC_URL" > /dev/null 2>&1; then
|
||||
echo -e "${YELLOW}RPC endpoint not accessible, trying alternative...${NC}"
|
||||
if [ "$RPC_URL" != "http://192.168.11.211:8545" ]; then
|
||||
RPC_URL="http://192.168.11.211:8545"
|
||||
else
|
||||
RPC_URL="https://rpc-http-pub.d-bis.org"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Token addresses (from .env or defaults)
|
||||
COMPLIANT_USDT_ADDRESS=${COMPLIANT_USDT_ADDRESS:-"0x93E66202A11B1772E55407B32B44e5Cd8eda7f22"}
|
||||
COMPLIANT_USDC_ADDRESS=${COMPLIANT_USDC_ADDRESS:-"0xf22258f57794CC8E06237084b353Ab30fFfa640b"}
|
||||
|
||||
# Recipient address
|
||||
RECIPIENT="0xc2D6E6981D1A415967A683D615cf97bA9bC26F0f"
|
||||
|
||||
# Amount: 100 tokens with 6 decimals = 100000000
|
||||
AMOUNT="100000000"
|
||||
|
||||
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Mint 100 cUSDT and 100 cUSDC ║${NC}"
|
||||
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
if [ -z "$PRIVATE_KEY" ]; then
|
||||
echo -e "${RED}Error: PRIVATE_KEY not set${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEPLOYER=$(cast wallet address --private-key "$PRIVATE_KEY" 2>/dev/null)
|
||||
echo -e "${BLUE}Deployer Address:${NC} $DEPLOYER"
|
||||
echo -e "${BLUE}Recipient Address:${NC} $RECIPIENT"
|
||||
echo -e "${BLUE}Amount:${NC} 100 tokens (each)"
|
||||
echo ""
|
||||
|
||||
# Mint cUSDT directly to recipient
|
||||
echo -e "${YELLOW}Minting 100 cUSDT to recipient...${NC}"
|
||||
TX_OUTPUT=$(cast send "$COMPLIANT_USDT_ADDRESS" \
|
||||
"mint(address,uint256)" \
|
||||
"$RECIPIENT" \
|
||||
"$AMOUNT" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy \
|
||||
--gas-price 20000000000 \
|
||||
2>&1)
|
||||
|
||||
if echo "$TX_OUTPUT" | grep -qE "transactionHash"; then
|
||||
TX_HASH=$(echo "$TX_OUTPUT" | grep -oE "transactionHash[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}')
|
||||
echo -e "${GREEN}✓ cUSDT mint successful${NC}"
|
||||
echo " Transaction Hash: $TX_HASH"
|
||||
else
|
||||
echo -e "${RED}✗ cUSDT mint failed${NC}"
|
||||
echo "$TX_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Mint cUSDC directly to recipient
|
||||
echo -e "${YELLOW}Minting 100 cUSDC to recipient...${NC}"
|
||||
TX_OUTPUT=$(cast send "$COMPLIANT_USDC_ADDRESS" \
|
||||
"mint(address,uint256)" \
|
||||
"$RECIPIENT" \
|
||||
"$AMOUNT" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy \
|
||||
--gas-price 20000000000 \
|
||||
2>&1)
|
||||
|
||||
if echo "$TX_OUTPUT" | grep -qE "transactionHash"; then
|
||||
TX_HASH=$(echo "$TX_OUTPUT" | grep -oE "transactionHash[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}')
|
||||
echo -e "${GREEN}✓ cUSDC mint successful${NC}"
|
||||
echo " Transaction Hash: $TX_HASH"
|
||||
else
|
||||
echo -e "${RED}✗ cUSDC mint failed${NC}"
|
||||
echo "$TX_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Verify mints
|
||||
echo -e "${YELLOW}Verifying mints...${NC}"
|
||||
sleep 3
|
||||
|
||||
RECIPIENT_CUSDT=$(cast call "$COMPLIANT_USDT_ADDRESS" "balanceOf(address)" "$RECIPIENT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
RECIPIENT_CUSDC=$(cast call "$COMPLIANT_USDC_ADDRESS" "balanceOf(address)" "$RECIPIENT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
|
||||
RECIPIENT_CUSDT_DISPLAY=$(echo "scale=2; $RECIPIENT_CUSDT / 1000000" | bc 2>/dev/null || echo "0")
|
||||
RECIPIENT_CUSDC_DISPLAY=$(echo "scale=2; $RECIPIENT_CUSDC / 1000000" | bc 2>/dev/null || echo "0")
|
||||
|
||||
echo " Recipient cUSDT Balance: $RECIPIENT_CUSDT_DISPLAY tokens"
|
||||
echo " Recipient cUSDC Balance: $RECIPIENT_CUSDC_DISPLAY tokens"
|
||||
echo ""
|
||||
|
||||
echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ Minting Complete! ║${NC}"
|
||||
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
47
scripts/prepare-hardhat-emoney.js
Normal file
47
scripts/prepare-hardhat-emoney.js
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Create node_modules/@emoney symlink so Hardhat can resolve @emoney/* imports
|
||||
* (Foundry uses remappings in foundry.toml; Hardhat resolves from node_modules.)
|
||||
* Run automatically via "pnpm install" / "prepare" script.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const nodeModules = path.join(root, 'node_modules');
|
||||
const emoneyDir = path.join(nodeModules, '@emoney');
|
||||
const target = path.join(root, 'contracts', 'emoney');
|
||||
|
||||
if (!fs.existsSync(path.join(root, 'contracts', 'emoney'))) {
|
||||
process.exit(0); // no contracts/emoney, skip
|
||||
}
|
||||
|
||||
fs.mkdirSync(nodeModules, { recursive: true });
|
||||
|
||||
try {
|
||||
const stat = fs.lstatSync(emoneyDir);
|
||||
if (stat.isSymbolicLink()) {
|
||||
const current = fs.readlinkSync(emoneyDir);
|
||||
if (path.resolve(current) === path.resolve(target)) process.exit(0);
|
||||
fs.unlinkSync(emoneyDir);
|
||||
} else if (stat.isDirectory()) {
|
||||
// leave existing real @emoney package alone
|
||||
process.exit(0);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.code !== 'ENOENT') throw e;
|
||||
}
|
||||
|
||||
try {
|
||||
fs.symlinkSync(target, emoneyDir, 'dir');
|
||||
} catch (e) {
|
||||
if (process.platform === 'win32') {
|
||||
try {
|
||||
fs.symlinkSync(target, emoneyDir, 'junction');
|
||||
} catch (e2) {
|
||||
console.warn('Could not create @emoney symlink:', e2.message);
|
||||
}
|
||||
} else {
|
||||
console.warn('Could not create @emoney symlink:', e.message);
|
||||
}
|
||||
}
|
||||
33
scripts/run-lint-test-build-deploy.sh
Executable file
33
scripts/run-lint-test-build-deploy.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run: lint, test, compile, then deploy (dry-run by default).
|
||||
# Usage: ./scripts/run-lint-test-build-deploy.sh [--deploy-live]
|
||||
set -e
|
||||
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
export FOUNDRY_PROFILE=default
|
||||
|
||||
echo "=== 1. Compile ==="
|
||||
forge build
|
||||
echo "✅ Build OK"
|
||||
|
||||
echo ""
|
||||
echo "=== 2. Lint ==="
|
||||
forge lint 2>&1 | head -100 || true
|
||||
echo "✅ Lint done"
|
||||
|
||||
echo ""
|
||||
echo "=== 3. Test ==="
|
||||
forge test 2>&1 | tail -50
|
||||
echo "✅ Tests done"
|
||||
|
||||
echo ""
|
||||
echo "=== 4. Deploy ==="
|
||||
if [[ "${1:-}" == "--deploy-live" ]]; then
|
||||
echo "Live deploy: run your preferred deploy script, e.g.:"
|
||||
echo " bash scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh"
|
||||
echo " or: forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens --rpc-url \$RPC_URL --chain-id 138 --broadcast --private-key \$PRIVATE_KEY --legacy"
|
||||
exit 0
|
||||
fi
|
||||
echo "Dry-run: DeployCWTokens (simulation only)"
|
||||
forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens --rpc-url "https://eth.llamarpc.com" --chain-id 1 2>&1 | tail -30
|
||||
echo "✅ Deploy dry-run done (no broadcast)"
|
||||
180
scripts/send-20m-tokens.sh
Executable file
180
scripts/send-20m-tokens.sh
Executable file
@@ -0,0 +1,180 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Send 20M cUSDT and cUSDC to a wallet address
|
||||
# Usage: ./send-20m-tokens.sh
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Change to script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
|
||||
# Load .env
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
RPC_URL=${RPC_URL:-${RPC_URL_138:-"http://192.168.11.211:8545"}}
|
||||
|
||||
# Token addresses (from .env or defaults)
|
||||
COMPLIANT_USDT_ADDRESS=${COMPLIANT_USDT_ADDRESS:-"0x93E66202A11B1772E55407B32B44e5Cd8eda7f22"}
|
||||
COMPLIANT_USDC_ADDRESS=${COMPLIANT_USDC_ADDRESS:-"0xf22258f57794CC8E06237084b353Ab30fFfa640b"}
|
||||
|
||||
# Recipient address
|
||||
RECIPIENT="0x4207aA9aC89B8bF4795dbAbBbE17fdd224E7947C"
|
||||
|
||||
# Amount: 20,000,000 tokens with 6 decimals = 20000000000000
|
||||
AMOUNT="20000000000000"
|
||||
|
||||
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Send 20M cUSDT and cUSDC ║${NC}"
|
||||
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
if [ -z "$PRIVATE_KEY" ]; then
|
||||
echo -e "${RED}Error: PRIVATE_KEY not set${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEPLOYER=$(cast wallet address --private-key "$PRIVATE_KEY" 2>/dev/null)
|
||||
echo -e "${BLUE}Deployer Address:${NC} $DEPLOYER"
|
||||
echo -e "${BLUE}Recipient Address:${NC} $RECIPIENT"
|
||||
echo -e "${BLUE}Amount:${NC} 20,000,000 tokens (each)"
|
||||
echo ""
|
||||
|
||||
# Check balances before transfer
|
||||
echo -e "${YELLOW}Checking balances...${NC}"
|
||||
|
||||
CUSDT_BALANCE=$(cast call "$COMPLIANT_USDT_ADDRESS" "balanceOf(address)" "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
CUSDC_BALANCE=$(cast call "$COMPLIANT_USDC_ADDRESS" "balanceOf(address)" "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
|
||||
CUSDT_BALANCE_DISPLAY=$(echo "scale=2; $CUSDT_BALANCE / 1000000" | bc 2>/dev/null || echo "0")
|
||||
CUSDC_BALANCE_DISPLAY=$(echo "scale=2; $CUSDC_BALANCE / 1000000" | bc 2>/dev/null || echo "0")
|
||||
|
||||
echo " Deployer cUSDT Balance: $CUSDT_BALANCE_DISPLAY tokens"
|
||||
echo " Deployer cUSDC Balance: $CUSDC_BALANCE_DISPLAY tokens"
|
||||
echo ""
|
||||
|
||||
# Check if we need to mint or transfer
|
||||
USE_MINT=false
|
||||
if [ "$(echo "$CUSDT_BALANCE < $AMOUNT" | bc 2>/dev/null || echo 1)" = "1" ]; then
|
||||
echo -e "${YELLOW}Insufficient balance. Will mint tokens directly to recipient...${NC}"
|
||||
USE_MINT=true
|
||||
fi
|
||||
|
||||
if [ "$USE_MINT" = "true" ]; then
|
||||
# Mint cUSDT directly to recipient
|
||||
echo -e "${YELLOW}Minting 20M cUSDT to recipient...${NC}"
|
||||
TX_OUTPUT=$(cast send "$COMPLIANT_USDT_ADDRESS" \
|
||||
"mint(address,uint256)" \
|
||||
"$RECIPIENT" \
|
||||
"$AMOUNT" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy \
|
||||
--gas-price 20000000000 \
|
||||
2>&1)
|
||||
else
|
||||
# Transfer cUSDT
|
||||
echo -e "${YELLOW}Transferring 20M cUSDT...${NC}"
|
||||
TX_OUTPUT=$(cast send "$COMPLIANT_USDT_ADDRESS" \
|
||||
"transfer(address,uint256)" \
|
||||
"$RECIPIENT" \
|
||||
"$AMOUNT" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy \
|
||||
--gas-price 20000000000 \
|
||||
2>&1)
|
||||
fi
|
||||
|
||||
if echo "$TX_OUTPUT" | grep -qE "transactionHash"; then
|
||||
TX_HASH=$(echo "$TX_OUTPUT" | grep -oE "transactionHash[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}')
|
||||
if [ "$USE_MINT" = "true" ]; then
|
||||
echo -e "${GREEN}✓ cUSDT mint successful${NC}"
|
||||
else
|
||||
echo -e "${GREEN}✓ cUSDT transfer successful${NC}"
|
||||
fi
|
||||
echo " Transaction Hash: $TX_HASH"
|
||||
else
|
||||
echo -e "${RED}✗ cUSDT operation failed${NC}"
|
||||
echo "$TX_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Check if we need to mint cUSDC
|
||||
USE_MINT_USDC=false
|
||||
if [ "$(echo "$CUSDC_BALANCE < $AMOUNT" | bc 2>/dev/null || echo 1)" = "1" ]; then
|
||||
USE_MINT_USDC=true
|
||||
fi
|
||||
|
||||
if [ "$USE_MINT_USDC" = "true" ]; then
|
||||
# Mint cUSDC directly to recipient
|
||||
echo -e "${YELLOW}Minting 20M cUSDC to recipient...${NC}"
|
||||
TX_OUTPUT=$(cast send "$COMPLIANT_USDC_ADDRESS" \
|
||||
"mint(address,uint256)" \
|
||||
"$RECIPIENT" \
|
||||
"$AMOUNT" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy \
|
||||
--gas-price 20000000000 \
|
||||
2>&1)
|
||||
else
|
||||
# Transfer cUSDC
|
||||
echo -e "${YELLOW}Transferring 20M cUSDC...${NC}"
|
||||
TX_OUTPUT=$(cast send "$COMPLIANT_USDC_ADDRESS" \
|
||||
"transfer(address,uint256)" \
|
||||
"$RECIPIENT" \
|
||||
"$AMOUNT" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy \
|
||||
--gas-price 20000000000 \
|
||||
2>&1)
|
||||
fi
|
||||
|
||||
if echo "$TX_OUTPUT" | grep -qE "transactionHash"; then
|
||||
TX_HASH=$(echo "$TX_OUTPUT" | grep -oE "transactionHash[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}')
|
||||
if [ "$USE_MINT_USDC" = "true" ]; then
|
||||
echo -e "${GREEN}✓ cUSDC mint successful${NC}"
|
||||
else
|
||||
echo -e "${GREEN}✓ cUSDC transfer successful${NC}"
|
||||
fi
|
||||
echo " Transaction Hash: $TX_HASH"
|
||||
else
|
||||
echo -e "${RED}✗ cUSDC operation failed${NC}"
|
||||
echo "$TX_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Verify transfers
|
||||
echo -e "${YELLOW}Verifying transfers...${NC}"
|
||||
sleep 3
|
||||
|
||||
RECIPIENT_CUSDT=$(cast call "$COMPLIANT_USDT_ADDRESS" "balanceOf(address)" "$RECIPIENT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
RECIPIENT_CUSDC=$(cast call "$COMPLIANT_USDC_ADDRESS" "balanceOf(address)" "$RECIPIENT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
|
||||
RECIPIENT_CUSDT_DISPLAY=$(echo "scale=2; $RECIPIENT_CUSDT / 1000000" | bc 2>/dev/null || echo "0")
|
||||
RECIPIENT_CUSDC_DISPLAY=$(echo "scale=2; $RECIPIENT_CUSDC / 1000000" | bc 2>/dev/null || echo "0")
|
||||
|
||||
echo " Recipient cUSDT Balance: $RECIPIENT_CUSDT_DISPLAY tokens"
|
||||
echo " Recipient cUSDC Balance: $RECIPIENT_CUSDC_DISPLAY tokens"
|
||||
echo ""
|
||||
|
||||
echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ Transfers Complete! ║${NC}"
|
||||
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
@@ -124,4 +124,8 @@ log_info "Next steps:"
|
||||
log_info "1. Add liquidity to pools using addLiquidity()"
|
||||
log_info "2. Monitor pool reserves and prices"
|
||||
log_info "3. Enable trading and arbitrage"
|
||||
log_info ""
|
||||
log_info "For PMM coverage of all tokens (chain 138/651940), use:"
|
||||
log_info " scripts/create-all-dodo-pools-from-token-api.sh"
|
||||
log_info " (requires TOKEN_AGGREGATION_API_URL, CHAIN_ID, QUOTE_TOKEN_ADDRESS, DODO_PMM_INTEGRATION_ADDRESS, ENHANCED_SWAP_ROUTER_ADDRESS, UNIVERSAL_ASSET_REGISTRY_ADDRESS)"
|
||||
|
||||
|
||||
82
scripts/treasury/verify-weth9-fingerprint.js
Normal file
82
scripts/treasury/verify-weth9-fingerprint.js
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Verify WETH9_138 fingerprint (symbol, name, decimals, optional bytecode hash).
|
||||
* Bot/executor must run at startup and halt if fingerprint does not match expected.
|
||||
* Usage: node verify-weth9-fingerprint.js [--no-exit]
|
||||
* Exit 0 = match, 1 = mismatch or error.
|
||||
*/
|
||||
const WETH9_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
|
||||
const RPC_138 = process.env.RPC_URL_138 || 'https://rpc-http-pub.d-bis.org';
|
||||
const RPC_MAINNET = process.env.ETHEREUM_MAINNET_RPC || 'https://eth.llamarpc.com';
|
||||
|
||||
const SELECTORS = { symbol: '0x95d89b41', name: '0x06fdde03', decimals: '0x313ce567' };
|
||||
|
||||
async function call(rpcUrl, to, data) {
|
||||
const res = await fetch(rpcUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ jsonrpc: '2.0', method: 'eth_call', params: [{ to, data }, 'latest'], id: 1 }),
|
||||
});
|
||||
const d = await res.json();
|
||||
if (d.error) throw new Error(d.error.message || JSON.stringify(d.error));
|
||||
return d.result;
|
||||
}
|
||||
|
||||
async function getCode(rpcUrl, address) {
|
||||
const res = await fetch(rpcUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ jsonrpc: '2.0', method: 'eth_getCode', params: [address, 'latest'], id: 1 }),
|
||||
});
|
||||
const d = await res.json();
|
||||
if (d.error) throw new Error(d.error.message || JSON.stringify(d.error));
|
||||
return d.result;
|
||||
}
|
||||
|
||||
function decodeString(hex) {
|
||||
if (!hex || hex === '0x') return '';
|
||||
try {
|
||||
const ethers = require('ethers');
|
||||
return ethers.AbiCoder.defaultAbiCoder().decode(['string'], hex)[0];
|
||||
} catch (_) { return hex; }
|
||||
}
|
||||
|
||||
function decodeUint8(hex) {
|
||||
if (!hex || hex === '0x') return 0;
|
||||
return parseInt(hex.slice(-2), 16);
|
||||
}
|
||||
|
||||
async function getFingerprint(rpcUrl, address) {
|
||||
const [symbolHex, nameHex, decimalsHex] = await Promise.all([
|
||||
call(rpcUrl, address, SELECTORS.symbol),
|
||||
call(rpcUrl, address, SELECTORS.name),
|
||||
call(rpcUrl, address, SELECTORS.decimals),
|
||||
]);
|
||||
const ethers = require('ethers');
|
||||
const code = await getCode(rpcUrl, address);
|
||||
const codeHash = code && code !== '0x' ? ethers.keccak256(code) : null;
|
||||
return {
|
||||
symbol: decodeString(symbolHex),
|
||||
name: decodeString(nameHex),
|
||||
decimals: decodeUint8(decimalsHex),
|
||||
codeHash,
|
||||
};
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const fp138 = await getFingerprint(RPC_138, WETH9_ADDRESS);
|
||||
console.log('Chain 138 fingerprint:', JSON.stringify(fp138, null, 2));
|
||||
const fpMain = await getFingerprint(RPC_MAINNET, WETH9_ADDRESS);
|
||||
console.log('Ethereum mainnet fingerprint:', JSON.stringify(fpMain, null, 2));
|
||||
const match = fp138.symbol === fpMain.symbol && fp138.name === fpMain.name
|
||||
&& fp138.decimals === fpMain.decimals
|
||||
&& (fp138.codeHash == null || fpMain.codeHash == null || fp138.codeHash === fpMain.codeHash);
|
||||
if (match) {
|
||||
console.log('Match: YES — WETH9_138 fingerprint matches expected.');
|
||||
process.exit(0);
|
||||
}
|
||||
console.error('Halt: WETH9_138 fingerprint mismatch.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
main().catch((err) => { console.error(err); process.exit(1); });
|
||||
279
scripts/update-oracle-price.sh
Executable file
279
scripts/update-oracle-price.sh
Executable file
@@ -0,0 +1,279 @@
|
||||
#!/usr/bin/env bash
|
||||
# Update Oracle Contract with Current ETH/USD Price
|
||||
# This script fetches the current ETH price from CoinGecko and updates the oracle contract
|
||||
# Usage: ./scripts/update-oracle-price.sh [rpc-url] [oracle-address] [private-key]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# Load .env if available
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# RPC URL priority: command arg > RPC_URL_138 > RPC_URL > working defaults
|
||||
DEFAULT_RPC="http://192.168.11.211:8545"
|
||||
RPC_URL="${1:-${RPC_URL_138:-${RPC_URL:-$DEFAULT_RPC}}}"
|
||||
ORACLE_ADDRESS="${2:-0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6}"
|
||||
AGGREGATOR_ADDRESS="${AGGREGATOR_ADDRESS:-0x99b3511a2d315a497c8112c1fdd8d508d4b1e506}"
|
||||
PRIVATE_KEY="${3:-${PRIVATE_KEY:-${DEPLOYER_PRIVATE_KEY:-}}}"
|
||||
|
||||
# Test RPC and fallback if needed
|
||||
if ! curl -s -X POST -H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||||
--max-time 3 "$RPC_URL" > /dev/null 2>&1; then
|
||||
log_warn "Primary RPC not accessible, trying alternatives..."
|
||||
# Try alternative RPCs
|
||||
for ALT_RPC in "http://192.168.11.211:8545" "https://rpc-http-pub.d-bis.org"; do
|
||||
if curl -s -X POST -H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||||
--max-time 3 "$ALT_RPC" > /dev/null 2>&1; then
|
||||
log_info "Using alternative RPC: $ALT_RPC"
|
||||
RPC_URL="$ALT_RPC"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "$PRIVATE_KEY" ]; then
|
||||
log_error "Private key required"
|
||||
log_info "Usage: $0 [rpc-url] [oracle-address] [private-key]"
|
||||
log_info " OR: Set DEPLOYER_PRIVATE_KEY environment variable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "========================================="
|
||||
echo "Update Oracle Price Feed"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
log_info "RPC URL: $RPC_URL"
|
||||
log_info "Oracle Address: $ORACLE_ADDRESS"
|
||||
echo ""
|
||||
|
||||
# Check RPC connectivity
|
||||
log_info "Checking RPC connectivity..."
|
||||
if ! curl -s -X POST -H "Content-Type: application/json" \
|
||||
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||||
"$RPC_URL" >/dev/null 2>&1; then
|
||||
log_error "RPC is not accessible at $RPC_URL"
|
||||
exit 1
|
||||
fi
|
||||
log_success "RPC is accessible"
|
||||
|
||||
# Fetch current ETH price from CoinGecko
|
||||
log_info "Fetching ETH/USD price from CoinGecko..."
|
||||
ETH_PRICE=$(curl -s 'https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd' | \
|
||||
python3 -c "import sys, json; data = json.load(sys.stdin); print(data.get('ethereum', {}).get('usd', '0'))" 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$ETH_PRICE" = "0" ] || [ -z "$ETH_PRICE" ]; then
|
||||
log_error "Failed to fetch ETH price from CoinGecko"
|
||||
log_info "Trying Binance API as fallback..."
|
||||
ETH_PRICE=$(curl -s 'https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT' | \
|
||||
python3 -c "import sys, json; data = json.load(sys.stdin); print(data.get('price', '0'))" 2>/dev/null || echo "0")
|
||||
fi
|
||||
|
||||
if [ "$ETH_PRICE" = "0" ] || [ -z "$ETH_PRICE" ]; then
|
||||
log_error "Failed to fetch ETH price from all sources"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "ETH/USD Price: \$$ETH_PRICE"
|
||||
|
||||
# Convert to 8 decimals (oracle format)
|
||||
PRICE_DECIMALS=$(python3 << PYEOF
|
||||
price = float("$ETH_PRICE")
|
||||
decimals = int(price * 100000000)
|
||||
print(decimals)
|
||||
PYEOF
|
||||
)
|
||||
|
||||
log_info "Price in 8 decimals: $PRICE_DECIMALS"
|
||||
echo ""
|
||||
|
||||
# Check current oracle price
|
||||
log_info "Checking current oracle price..."
|
||||
CURRENT_ORACLE_DATA=$(cast call "$ORACLE_ADDRESS" \
|
||||
"latestRoundData()" \
|
||||
--rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$CURRENT_ORACLE_DATA" ] && [ "$CURRENT_ORACLE_DATA" != "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ]; then
|
||||
# Parse current price
|
||||
CURRENT_ANSWER=$(echo "$CURRENT_ORACLE_DATA" | cut -c 131-194) # Extract answer field
|
||||
CURRENT_PRICE=$(python3 << PYEOF
|
||||
answer_hex = "$CURRENT_ANSWER"
|
||||
answer_int = int(answer_hex, 16)
|
||||
# Handle negative (if signed)
|
||||
if answer_int > 2**255:
|
||||
answer_int = answer_int - 2**256
|
||||
price = answer_int / 100000000
|
||||
print(price)
|
||||
PYEOF
|
||||
)
|
||||
log_info "Current oracle price: \$$(printf '%.2f' $CURRENT_PRICE)"
|
||||
|
||||
# Check if update is needed (only update if difference > 1%)
|
||||
PRICE_DIFF=$(python3 << PYEOF
|
||||
current = float("$CURRENT_PRICE")
|
||||
new = float("$ETH_PRICE")
|
||||
diff = abs(new - current) / current * 100
|
||||
print(diff)
|
||||
PYEOF
|
||||
)
|
||||
|
||||
if (( $(echo "$PRICE_DIFF < 1" | bc -l) )); then
|
||||
log_warn "Price difference is less than 1% (${PRICE_DIFF}%)"
|
||||
log_info "Skipping update to save gas"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update oracle contract
|
||||
log_info "Updating oracle contract..."
|
||||
log_info "This will send a transaction to update the price feed..."
|
||||
|
||||
# Check if updateAnswer function exists, if not try transmit
|
||||
if cast sig "updateAnswer(int256)" >/dev/null 2>&1; then
|
||||
UPDATE_METHOD="updateAnswer"
|
||||
elif cast sig "transmit(int256)" >/dev/null 2>&1; then
|
||||
UPDATE_METHOD="transmit"
|
||||
else
|
||||
log_error "Could not determine oracle update method"
|
||||
log_info "Please check the oracle contract ABI"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Using method: $UPDATE_METHOD"
|
||||
|
||||
# Check if account is authorized transmitter
|
||||
if [ -n "$PRIVATE_KEY" ]; then
|
||||
DEPLOYER_ADDR=$(cast wallet address --private-key "$PRIVATE_KEY" 2>/dev/null || echo "")
|
||||
if [ -n "$DEPLOYER_ADDR" ]; then
|
||||
log_info "Checking transmitter authorization..."
|
||||
IS_TRANSMITTER=$(timeout 10 cast call "$AGGREGATOR_ADDRESS" "isTransmitter(address)(bool)" "$DEPLOYER_ADDR" --rpc-url "$RPC_URL" 2>/dev/null || echo "false")
|
||||
if [ "$IS_TRANSMITTER" != "true" ]; then
|
||||
log_warn "Account $DEPLOYER_ADDR is NOT an authorized transmitter"
|
||||
log_info "Oracle requires transmitter role to update prices"
|
||||
log_info "Options:"
|
||||
log_info " 1. Use Oracle Publisher service (VMID 3500) - recommended"
|
||||
log_info " 2. Use an authorized transmitter account private key"
|
||||
log_info " 3. Add this account as transmitter (requires admin)"
|
||||
log_info ""
|
||||
log_info "Checking for transmitter addresses..."
|
||||
TX_COUNT=0
|
||||
for i in 0 1 2 3 4 5; do
|
||||
TX_ADDR=$(timeout 10 cast call "$AGGREGATOR_ADDRESS" "transmitters(uint256)(address)" "$i" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$TX_ADDR" ] && [ "$TX_ADDR" != "0x0000000000000000000000000000000000000000" ]; then
|
||||
log_info " Transmitter $TX_COUNT: $TX_ADDR"
|
||||
TX_COUNT=$((TX_COUNT + 1))
|
||||
fi
|
||||
done
|
||||
if [ $TX_COUNT -eq 0 ]; then
|
||||
log_error "No transmitters found - oracle may not be configured"
|
||||
fi
|
||||
exit 1
|
||||
else
|
||||
log_success "Account is authorized transmitter"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Use aggregator address for updates (proxy is read-only)
|
||||
UPDATE_CONTRACT="$AGGREGATOR_ADDRESS"
|
||||
log_info "Updating aggregator contract: $UPDATE_CONTRACT"
|
||||
|
||||
# Send transaction (with timeout)
|
||||
log_info "Sending transaction to aggregator (this may take 30-60 seconds)..."
|
||||
TX_OUTPUT=$(timeout 90 cast send "$UPDATE_CONTRACT" \
|
||||
"$UPDATE_METHOD(uint256)" \
|
||||
"$PRICE_DECIMALS" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--legacy \
|
||||
--gas-price 20000000000 \
|
||||
2>&1)
|
||||
|
||||
# Check if transaction was sent
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Transaction failed or timed out"
|
||||
echo "$TX_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract transaction hash from output
|
||||
TX_HASH=$(echo "$TX_OUTPUT" | grep -oE "transactionHash[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}' || \
|
||||
echo "$TX_OUTPUT" | grep -oE "0x[0-9a-fA-F]{64}" | head -1 || echo "")
|
||||
|
||||
# If still no hash, check for error messages
|
||||
if [ -z "$TX_HASH" ]; then
|
||||
if echo "$TX_OUTPUT" | grep -qi "error\|failed\|revert"; then
|
||||
log_error "Transaction failed:"
|
||||
echo "$TX_OUTPUT"
|
||||
exit 1
|
||||
elif echo "$TX_OUTPUT" | grep -qi "insufficient funds\|gas"; then
|
||||
log_error "Transaction failed (gas/funds issue):"
|
||||
echo "$TX_OUTPUT"
|
||||
exit 1
|
||||
else
|
||||
log_warn "Could not extract transaction hash from output:"
|
||||
echo "$TX_OUTPUT" | head -20
|
||||
log_info "Transaction may have been sent - check explorer or try again"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$TX_HASH" ]; then
|
||||
log_error "Failed to send transaction"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "Transaction sent: $TX_HASH"
|
||||
|
||||
# Wait for confirmation
|
||||
log_info "Waiting for transaction confirmation..."
|
||||
sleep 5
|
||||
|
||||
# Verify update
|
||||
log_info "Verifying oracle update..."
|
||||
NEW_ORACLE_DATA=$(cast call "$ORACLE_ADDRESS" \
|
||||
"latestRoundData()" \
|
||||
--rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$NEW_ORACLE_DATA" ]; then
|
||||
NEW_ANSWER=$(echo "$NEW_ORACLE_DATA" | cut -c 131-194)
|
||||
NEW_PRICE=$(python3 << PYEOF
|
||||
answer_hex = "$NEW_ANSWER"
|
||||
answer_int = int(answer_hex, 16)
|
||||
if answer_int > 2**255:
|
||||
answer_int = answer_int - 2**256
|
||||
price = answer_int / 100000000
|
||||
print(price)
|
||||
PYEOF
|
||||
)
|
||||
log_success "Oracle updated successfully!"
|
||||
log_info "New oracle price: \$$(printf '%.2f' $NEW_PRICE)"
|
||||
else
|
||||
log_warn "Could not verify oracle update (may need more time for confirmation)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_success "========================================="
|
||||
log_success "Oracle Price Update Complete!"
|
||||
log_success "========================================="
|
||||
echo ""
|
||||
|
||||
@@ -6,11 +6,18 @@
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/../lib/init.sh"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
CONFIG_DIR="$PROJECT_ROOT/config"
|
||||
GENESIS_FILE="$CONFIG_DIR/genesis.json"
|
||||
|
||||
# Minimal logging (used if init.sh is not sourced or fails)
|
||||
log_success() { echo -e "\033[0;32m[✓]\033[0m $*"; }
|
||||
log_error() { echo -e "\033[0;31m[✗]\033[0m $*" >&2; }
|
||||
log_warn() { echo -e "\033[0;33m[⚠]\033[0m $*"; }
|
||||
# Optional: load lib (may fail if .env or Azure deps are missing)
|
||||
if [ -f "$SCRIPT_DIR/../lib/init.sh" ]; then
|
||||
SCRIPT_DIR="$SCRIPT_DIR" source "$SCRIPT_DIR/../lib/init.sh" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
log_success "Validating Genesis File..."
|
||||
|
||||
@@ -60,29 +67,28 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check IBFT configuration
|
||||
log_warn "Checking IBFT configuration..."
|
||||
IBFT_CONFIG=$(jq -r '.config.ibft2' "$GENESIS_FILE")
|
||||
# Check IBFT 2 / QBFT configuration
|
||||
log_warn "Checking IBFT 2 / QBFT configuration..."
|
||||
IBFT_CONFIG=$(jq -r '.config.ibft2 // .config.qbft // "null"' "$GENESIS_FILE")
|
||||
if [ "$IBFT_CONFIG" != "null" ]; then
|
||||
log_success "✓ IBFT 2.0 configuration exists"
|
||||
|
||||
# Check block period
|
||||
BLOCK_PERIOD=$(jq -r '.config.ibft2.blockperiodseconds' "$GENESIS_FILE")
|
||||
log_success "✓ IBFT 2.0 / QBFT configuration exists"
|
||||
# Prefer qbft for Chain 138
|
||||
BLOCK_KEY=".config.qbft.blockperiodseconds // .config.ibft2.blockperiodseconds"
|
||||
EPOCH_KEY=".config.qbft.epochlength // .config.ibft2.epochlength"
|
||||
BLOCK_PERIOD=$(jq -r "$BLOCK_KEY" "$GENESIS_FILE")
|
||||
EPOCH_LENGTH=$(jq -r "$EPOCH_KEY" "$GENESIS_FILE")
|
||||
if [ "$BLOCK_PERIOD" == "2" ]; then
|
||||
log_success "✓ Block period is correct: $BLOCK_PERIOD seconds"
|
||||
else
|
||||
log_warn "⚠ Block period is $BLOCK_PERIOD (expected 2)"
|
||||
fi
|
||||
|
||||
# Check epoch length
|
||||
EPOCH_LENGTH=$(jq -r '.config.ibft2.epochlength' "$GENESIS_FILE")
|
||||
if [ "$EPOCH_LENGTH" == "30000" ]; then
|
||||
log_success "✓ Epoch length is correct: $EPOCH_LENGTH"
|
||||
else
|
||||
log_warn "⚠ Epoch length is $EPOCH_LENGTH (expected 30000)"
|
||||
fi
|
||||
else
|
||||
log_error "✗ IBFT 2.0 configuration not found"
|
||||
log_error "✗ IBFT 2.0 / QBFT configuration not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
80
scripts/verify-all-mainnet-usdc.sh
Executable file
80
scripts/verify-all-mainnet-usdc.sh
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
# Verify USDC contract deployment on ALL Mainnet (651940)
|
||||
# This script helps check if USDC is deployed on ALL Mainnet
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CHAIN_ID=651940
|
||||
RPC_URL="https://mainnet-rpc.alltra.global"
|
||||
EXPLORER_URL="https://alltra.global"
|
||||
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ ALL Mainnet (651940) USDC Verification Script ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "Chain ID: $CHAIN_ID"
|
||||
echo "RPC URL: $RPC_URL"
|
||||
echo "Explorer: $EXPLORER_URL"
|
||||
echo ""
|
||||
|
||||
# Check if cast (Foundry) is available
|
||||
if ! command -v cast &> /dev/null; then
|
||||
echo "⚠️ Warning: 'cast' command not found. Install Foundry to use RPC queries."
|
||||
echo " Install: curl -L https://foundry.paradigm.xyz | bash && foundryup"
|
||||
echo ""
|
||||
echo "📋 Manual Verification Steps:"
|
||||
echo " 1. Visit: $EXPLORER_URL"
|
||||
echo " 2. Search for 'USDC' or 'USD Coin'"
|
||||
echo " 3. Check token contract addresses"
|
||||
echo " 4. Verify contract is verified and has standard USDC interface"
|
||||
echo " 5. Record contract address and decimals (typically 6)"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "🔍 Checking RPC connectivity..."
|
||||
if ! cast block-number --rpc-url "$RPC_URL" > /dev/null 2>&1; then
|
||||
echo "❌ Error: Cannot connect to RPC at $RPC_URL"
|
||||
echo " Please check network connectivity or RPC endpoint"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BLOCK_NUM=$(cast block-number --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
ACTUAL_CHAIN_ID=$(cast chain-id --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
|
||||
if [ "$ACTUAL_CHAIN_ID" != "$CHAIN_ID" ]; then
|
||||
echo "⚠️ Warning: Chain ID mismatch (expected: $CHAIN_ID, got: $ACTUAL_CHAIN_ID)"
|
||||
fi
|
||||
|
||||
echo "✅ RPC accessible (block: $BLOCK_NUM, chain: $ACTUAL_CHAIN_ID)"
|
||||
echo ""
|
||||
|
||||
echo "📋 Common USDC Contract Addresses to Check:"
|
||||
echo ""
|
||||
echo "Standard USDC addresses (may differ on ALL Mainnet):"
|
||||
echo " - Ethereum Mainnet: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
||||
echo " - Base: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
|
||||
echo " - Arbitrum: 0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
|
||||
echo ""
|
||||
echo "🔍 To verify USDC on ALL Mainnet:"
|
||||
echo ""
|
||||
echo "Method 1: Explorer Search"
|
||||
echo " 1. Visit: $EXPLORER_URL"
|
||||
echo " 2. Search for 'USDC' in token search"
|
||||
echo " 3. Check contract verification status"
|
||||
echo " 4. Verify token symbol, name, and decimals"
|
||||
echo ""
|
||||
echo "Method 2: RPC Query (if you have a suspected address)"
|
||||
echo " cast call <ADDRESS> 'symbol()(string)' --rpc-url $RPC_URL"
|
||||
echo " cast call <ADDRESS> 'name()(string)' --rpc-url $RPC_URL"
|
||||
echo " cast call <ADDRESS> 'decimals()(uint8)' --rpc-url $RPC_URL"
|
||||
echo ""
|
||||
echo "Method 3: Check Token Lists"
|
||||
echo " - Check if ALL Mainnet has a token list (similar to Uniswap token lists)"
|
||||
echo " - Look for USDC in official token registries"
|
||||
echo ""
|
||||
echo "📝 After finding USDC address, update:"
|
||||
echo " - alltra-lifi-settlement/src/config/chains.ts"
|
||||
echo " Set: usdcAddress: '<FOUND_ADDRESS>'"
|
||||
echo ""
|
||||
echo "✅ Script complete. Manual verification required for USDC deployment."
|
||||
@@ -14,7 +14,7 @@ fi
|
||||
|
||||
RPC_URL="${RPC_URL:-${RPC_URL_138:-http://192.168.11.250:8545}}"
|
||||
WETH9_ADDRESS="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
||||
WETH9_BRIDGE="0x89dd12025bfCD38A168455A44B400e913ED33BE2"
|
||||
WETH9_BRIDGE="0x971cD9D156f193df8051E48043C476e53ECd4693"
|
||||
ETHEREUM_SELECTOR="5009297550715157269"
|
||||
LINK_TOKEN="${LINK_TOKEN:-0x514910771AF9Ca656af840dff83E8264EcF986CA}"
|
||||
AMOUNT_ETH="${1:-20000}"
|
||||
|
||||
@@ -29,9 +29,9 @@ fi
|
||||
|
||||
# Configuration
|
||||
RPC_URL="${RPC_URL:-${RPC_URL_138:-http://192.168.11.250:8545}}"
|
||||
BRIDGE_ADDRESS="${CCIPWETH9_BRIDGE_CHAIN138:-0x89dd12025bfCD38A168455A44B400e913ED33BE2}"
|
||||
LINK_TOKEN="${LINK_TOKEN:-0x514910771AF9Ca656af840dff83E8264EcF986CA}"
|
||||
CCIP_ROUTER="${CCIP_ROUTER:-0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D}"
|
||||
BRIDGE_ADDRESS="${CCIPWETH9_BRIDGE_CHAIN138:-0x971cD9D156f193df8051E48043C476e53ECd4693}"
|
||||
LINK_TOKEN="${LINK_TOKEN:-0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03}"
|
||||
CCIP_ROUTER="${CCIP_ROUTER:-0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e}"
|
||||
ETH_SELECTOR="5009297550715157269" # Ethereum Mainnet
|
||||
|
||||
echo "========================================="
|
||||
|
||||
30
scripts/verify-tezos-etherlink-support.js
Normal file
30
scripts/verify-tezos-etherlink-support.js
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env node
|
||||
// Verify CCIP/LiFi support for 138, 42793, 651940. Run: node scripts/verify-tezos-etherlink-support.js
|
||||
|
||||
const LIFI_URL = 'https://li.quest/v1/chains';
|
||||
const CCIP_URL = 'https://docs.chain.link/ccip/supported-networks';
|
||||
|
||||
async function main() {
|
||||
console.log('Tezos/Etherlink support check\n');
|
||||
try {
|
||||
const lifiRes = await fetch(LIFI_URL);
|
||||
const lifi = await lifiRes.json();
|
||||
const ids = (lifi.chains || []).map((c) => c.id || c.chainId).filter(Boolean);
|
||||
console.log('LiFi chains include 138:', ids.includes(138));
|
||||
console.log('LiFi chains include 42793:', ids.includes(42793));
|
||||
console.log('LiFi chains include 651940:', ids.includes(651940));
|
||||
} catch (e) {
|
||||
console.log('LiFi error:', e.message);
|
||||
}
|
||||
try {
|
||||
const ccipRes = await fetch(CCIP_URL);
|
||||
const html = await ccipRes.text();
|
||||
console.log('\nCCIP page mentions 42793:', html.includes('42793') || html.toLowerCase().includes('etherlink'));
|
||||
console.log('CCIP page mentions 138:', html.includes('138'));
|
||||
} catch (e) {
|
||||
console.log('CCIP error:', e.message);
|
||||
}
|
||||
console.log('\nJumper: verify manually; see docs/07-ccip/TEZOS_JUMPER_SUPPORT_MATRIX.md');
|
||||
}
|
||||
|
||||
main().catch((e) => { console.error(e); process.exit(1); });
|
||||
60
scripts/verify-weth9-canonical.js
Normal file
60
scripts/verify-weth9-canonical.js
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Verify that WETH9 at 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 on Chain 138
|
||||
* has the same bytecode as canonical WETH9 on Ethereum mainnet.
|
||||
* Compares keccak256(code); if equal, the contract is canonical WETH9.
|
||||
* Also outputs fingerprint (symbol, name, decimals) for bot/executor startup checks.
|
||||
* See docs/treasury: do not assume canonical WETH9 until this (or verify-weth9-fingerprint.js) passes.
|
||||
*/
|
||||
|
||||
const ethers = require('ethers');
|
||||
|
||||
const WETH9_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
|
||||
const RPC_138 = 'https://rpc-http-pub.d-bis.org';
|
||||
const RPC_MAINNET = 'https://eth.llamarpc.com';
|
||||
|
||||
async function getCode(rpcUrl) {
|
||||
const res = await fetch(rpcUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_getCode',
|
||||
params: [WETH9_ADDRESS, 'latest'],
|
||||
id: 1,
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.error) throw new Error(data.error.message || JSON.stringify(data.error));
|
||||
return data.result;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('Fetching WETH9 bytecode from Chain 138 and Ethereum mainnet...');
|
||||
const [code138, codeMainnet] = await Promise.all([
|
||||
getCode(RPC_138),
|
||||
getCode(RPC_MAINNET),
|
||||
]);
|
||||
|
||||
const hash = (hex) => ethers.keccak256(hex);
|
||||
const h138 = hash(code138);
|
||||
const hMain = hash(codeMainnet);
|
||||
|
||||
console.log('Chain 138 bytecode length (bytes):', (code138.length - 2) / 2);
|
||||
console.log('Ethereum main bytecode length (bytes):', (codeMainnet.length - 2) / 2);
|
||||
console.log('Chain 138 keccak256(code):', h138);
|
||||
console.log('Ethereum main keccak256(code):', hMain);
|
||||
console.log('');
|
||||
if (h138 === hMain) {
|
||||
console.log('Match: YES — Chain 138 has canonical WETH9 bytecode at', WETH9_ADDRESS);
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log('Match: NO — Chain 138 has WETH-like bytecode at that address, but not canonical WETH9.');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
# Wrap ETH to WETH9 and Bridge to Ethereum Mainnet
|
||||
# Usage: ./wrap-and-bridge-weth9-to-mainnet.sh [amount_in_eth] [recipient_address] [private_key]
|
||||
# Wrap ETH to WETH9 and Bridge to Ethereum Mainnet (Chain 138 → Ethereum Mainnet via CCIP)
|
||||
# Usage: ./wrap-and-bridge-weth9-to-mainnet.sh <amount_in_eth> [recipient_address] [private_key]
|
||||
# Env: PRIVATE_KEY (or 3rd arg), RPC_URL or RPC_URL_138, CCIPWETH9_BRIDGE_CHAIN138.
|
||||
# Optional: WETH9_ADDRESS_CHAIN138 (if Chain 138 uses different WETH9), EXPLORER_URL_138.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -19,17 +21,20 @@ log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[✗]${NC} $1"; }
|
||||
|
||||
# Load environment variables
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
source "$PROJECT_ROOT/.env"
|
||||
# Load environment variables (try repo root = parent of scripts/, then workspace)
|
||||
if [ -f "$SCRIPT_DIR/../.env" ]; then
|
||||
set -a && source "$SCRIPT_DIR/../.env" && set +a
|
||||
elif [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
set -a && source "$PROJECT_ROOT/.env" && set +a
|
||||
elif [ -f "$PROJECT_ROOT/smom-dbis-138/.env" ]; then
|
||||
source "$PROJECT_ROOT/smom-dbis-138/.env"
|
||||
set -a && source "$PROJECT_ROOT/smom-dbis-138/.env" && set +a
|
||||
fi
|
||||
|
||||
# Configuration
|
||||
# Configuration (override WETH9_ADDRESS / WETH9_ADDRESS_CHAIN138 if Chain 138 uses a different WETH9)
|
||||
RPC_URL="${RPC_URL:-${RPC_URL_138:-http://192.168.11.250:8545}}"
|
||||
WETH9_ADDRESS="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
||||
WETH9_BRIDGE="0x89dd12025bfCD38A168455A44B400e913ED33BE2"
|
||||
WETH9_ADDRESS="${WETH9_ADDRESS_CHAIN138:-${WETH9_ADDRESS:-0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2}}"
|
||||
WETH9_BRIDGE="${CCIPWETH9_BRIDGE_CHAIN138:-0x971cD9D156f193df8051E48043C476e53ECd4693}"
|
||||
EXPLORER_URL_138="${EXPLORER_URL_138:-https://explorer.d-bis.org}"
|
||||
ETHEREUM_SELECTOR="5009297550715157269"
|
||||
LINK_TOKEN="${LINK_TOKEN:-0x514910771AF9Ca656af840dff83E8264EcF986CA}"
|
||||
|
||||
@@ -108,22 +113,25 @@ if (( $(echo "$ETH_BALANCE < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); the
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check WETH9 balance
|
||||
# Check WETH9 balance (cast returns hex; parse to decimal for bc)
|
||||
log_info "Checking WETH9 balance..."
|
||||
WETH9_BALANCE=$(cast call "$WETH9_ADDRESS" "balanceOf(address)" "$SENDER" --rpc-url "$RPC_URL" 2>/dev/null | cast --to-dec 2>/dev/null || echo "0")
|
||||
WETH9_BALANCE_RAW=$(cast call "$WETH9_ADDRESS" "balanceOf(address)(uint256)" "$SENDER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
WETH9_BALANCE=$(echo "$WETH9_BALANCE_RAW" | tr -d '\n\r' | sed 's/\[.*//' | grep -oE '^[0-9]+$' || echo "$WETH9_BALANCE_RAW" | cast --to-dec 2>/dev/null || echo "0")
|
||||
[[ -z "$WETH9_BALANCE" ]] && WETH9_BALANCE=0
|
||||
WETH9_BALANCE_ETH=$(echo "scale=6; $WETH9_BALANCE / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
||||
log_info "WETH9 Balance: $WETH9_BALANCE_ETH WETH9 ($WETH9_BALANCE wei)"
|
||||
|
||||
# Step 1: Wrap ETH to WETH9 (if needed)
|
||||
NEED_TO_WRAP=false
|
||||
if (( $(echo "$WETH9_BALANCE < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); then
|
||||
if (( $(echo "${WETH9_BALANCE:-0} < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); then
|
||||
NEED_TO_WRAP=true
|
||||
WRAP_AMOUNT=$(echo "$AMOUNT_WEI - $WETH9_BALANCE" | bc 2>/dev/null || echo "$AMOUNT_WEI")
|
||||
WRAP_AMOUNT=$(echo "$AMOUNT_WEI - ${WETH9_BALANCE:-0}" | bc 2>/dev/null || echo "$AMOUNT_WEI")
|
||||
[[ -z "$WRAP_AMOUNT" ]] || [[ "$WRAP_AMOUNT" -lt "$AMOUNT_WEI" ]] 2>/dev/null && WRAP_AMOUNT="$AMOUNT_WEI"
|
||||
WRAP_AMOUNT_ETH=$(echo "scale=6; $WRAP_AMOUNT / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
||||
|
||||
log_info ""
|
||||
log_info "Step 1: Wrapping ETH to WETH9..."
|
||||
log_info " Amount to wrap: $WRAP_AMOUNT_ETH ETH"
|
||||
log_info " Amount to wrap: $WRAP_AMOUNT_ETH ETH (wei: $WRAP_AMOUNT)"
|
||||
|
||||
# Check if we have enough ETH for wrapping
|
||||
if (( $(echo "$ETH_BALANCE < $WRAP_AMOUNT" | bc -l 2>/dev/null || echo 1) )); then
|
||||
@@ -131,13 +139,16 @@ if (( $(echo "$WETH9_BALANCE < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); t
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info " Sending transaction..."
|
||||
[[ -z "$WRAP_AMOUNT" ]] && WRAP_AMOUNT="$AMOUNT_WEI"
|
||||
[[ "$WRAP_AMOUNT" = "0" ]] && WRAP_AMOUNT="$AMOUNT_WEI"
|
||||
log_info " Sending transaction (value=$WRAP_AMOUNT wei)..."
|
||||
WRAP_TX=$(cast send "$WETH9_ADDRESS" \
|
||||
"deposit()" \
|
||||
--value "$WRAP_AMOUNT" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--gas-price 20000000000 \
|
||||
--gas-price "${GAS_PRICE_138:-1000000000}" \
|
||||
--gas-limit "${GAS_LIMIT_138:-200000}" \
|
||||
--legacy \
|
||||
-vv 2>&1 || echo "")
|
||||
|
||||
@@ -147,10 +158,18 @@ if (( $(echo "$WETH9_BALANCE < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); t
|
||||
log_info "Waiting for confirmation (15 seconds)..."
|
||||
sleep 15
|
||||
|
||||
# Verify WETH9 balance
|
||||
NEW_WETH9_BALANCE=$(cast call "$WETH9_ADDRESS" "balanceOf(address)" "$SENDER" --rpc-url "$RPC_URL" 2>/dev/null | cast --to-dec 2>/dev/null || echo "0")
|
||||
# Verify WETH9 balance (same parsing as initial balance: balanceOf returns uint256)
|
||||
NEW_WETH9_RAW=$(cast call "$WETH9_ADDRESS" "balanceOf(address)(uint256)" "$SENDER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
NEW_WETH9_BALANCE=$(echo "$NEW_WETH9_RAW" | tr -d '\n\r' | sed 's/\[.*//' | grep -oE '^[0-9]+$' || echo "$NEW_WETH9_RAW" | cast --to-dec 2>/dev/null || echo "0")
|
||||
[[ -z "$NEW_WETH9_BALANCE" ]] && NEW_WETH9_BALANCE=0
|
||||
NEW_WETH9_BALANCE_ETH=$(echo "scale=6; $NEW_WETH9_BALANCE / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
||||
log_success "✓ New WETH9 Balance: $NEW_WETH9_BALANCE_ETH WETH9"
|
||||
if (( $(echo "${NEW_WETH9_BALANCE:-0} < $WRAP_AMOUNT" | bc -l 2>/dev/null || echo 1) )); then
|
||||
log_error "WETH9 balance did not increase after wrap (got $NEW_WETH9_BALANCE_ETH WETH9). Wrap tx may have reverted."
|
||||
log_info "Check wrap tx on explorer: $EXPLORER_URL_138/tx/$TX_HASH"
|
||||
log_info "If the tx reverted, fix the cause (e.g. wrong WETH9 address on this chain) before re-running."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log_error "Failed to wrap ETH"
|
||||
log_info "Output: $WRAP_TX"
|
||||
@@ -163,7 +182,9 @@ fi
|
||||
# Step 2: Approve bridge (if needed)
|
||||
log_info ""
|
||||
log_info "Step 2: Checking bridge approval..."
|
||||
ALLOWANCE=$(cast call "$WETH9_ADDRESS" "allowance(address,address)" "$SENDER" "$WETH9_BRIDGE" --rpc-url "$RPC_URL" 2>/dev/null | cast --to-dec 2>/dev/null || echo "0")
|
||||
ALLOWANCE_RAW=$(cast call "$WETH9_ADDRESS" "allowance(address,address)(uint256)" "$SENDER" "$WETH9_BRIDGE" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
ALLOWANCE=$(echo "$ALLOWANCE_RAW" | tr -d '\n\r' | grep -oE '^[0-9]+$' || echo "$ALLOWANCE_RAW" | cast --to-dec 2>/dev/null || echo "0")
|
||||
[[ -z "$ALLOWANCE" ]] && ALLOWANCE=0
|
||||
|
||||
if (( $(echo "$ALLOWANCE < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); then
|
||||
log_info "Approving bridge to spend WETH9..."
|
||||
@@ -175,7 +196,8 @@ if (( $(echo "$ALLOWANCE < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); then
|
||||
"$MAX_UINT256" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--gas-price 20000000000 \
|
||||
--gas-price "${GAS_PRICE_138:-1000000000}" \
|
||||
--gas-limit "${GAS_LIMIT_138:-200000}" \
|
||||
--legacy \
|
||||
-vv 2>&1 || echo "")
|
||||
|
||||
@@ -208,6 +230,27 @@ if (( $(echo "$LINK_BALANCE < 1000000000000000000" | bc -l 2>/dev/null || echo 0
|
||||
log_warn "Recommended: At least 1-2 LINK for large transfers"
|
||||
fi
|
||||
|
||||
# Chain 138 LINK - approve for CCIP fees (bridge or router pulls). Canonical on 138: 0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03 (see CHAIN138_TOKEN_ADDRESSES.md, LINK_TOKEN_STATUS_FINAL.md).
|
||||
LINK_TOKEN_138="${LINK_TOKEN_CHAIN138:-${LINK_TOKEN:-0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03}}"
|
||||
CCIP_ROUTER_138="${CCIP_ROUTER_ADDRESS:-0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e}"
|
||||
MAX_UINT256="115792089237316195423570985008687907853269984665640564039457584007913129639935"
|
||||
log_info "Approving LINK for CCIP fees (bridge + router)..."
|
||||
cast send "$LINK_TOKEN_138" "approve(address,uint256)" "$WETH9_BRIDGE" "$MAX_UINT256" \
|
||||
--rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" --gas-price "${GAS_PRICE_138:-1000000000}" --gas-limit "${GAS_LIMIT_138:-200000}" --legacy -q 2>/dev/null || true
|
||||
cast send "$LINK_TOKEN_138" "approve(address,uint256)" "$CCIP_ROUTER_138" "$MAX_UINT256" \
|
||||
--rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" --gas-price "${GAS_PRICE_138:-1000000000}" --gas-limit "${GAS_LIMIT_138:-200000}" --legacy -q 2>/dev/null || true
|
||||
|
||||
# Pre-bridge: confirm we have enough WETH9 (avoid bridging 0 or less)
|
||||
FINAL_WETH9_RAW=$(cast call "$WETH9_ADDRESS" "balanceOf(address)(uint256)" "$SENDER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
FINAL_WETH9=$(echo "$FINAL_WETH9_RAW" | tr -d '\n\r' | grep -oE '^[0-9]+$' || echo "$FINAL_WETH9_RAW" | cast --to-dec 2>/dev/null || echo "0")
|
||||
[[ -z "$FINAL_WETH9" ]] && FINAL_WETH9=0
|
||||
if (( $(echo "${FINAL_WETH9:-0} < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); then
|
||||
FINAL_ETH=$(echo "scale=6; $FINAL_WETH9 / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
||||
log_error "Insufficient WETH9 balance to bridge. Have $FINAL_ETH WETH9, need $AMOUNT_ETH WETH9."
|
||||
log_info "Ensure wrap succeeded and balance is visible on-chain before re-running."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 4: Bridge to Ethereum Mainnet
|
||||
log_info ""
|
||||
log_info "Step 4: Bridging WETH9 to Ethereum Mainnet..."
|
||||
@@ -237,7 +280,8 @@ BRIDGE_TX=$(cast send "$WETH9_BRIDGE" \
|
||||
"$AMOUNT_WEI" \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--gas-price 20000000000 \
|
||||
--gas-price "${GAS_PRICE_138:-1000000000}" \
|
||||
--gas-limit "${GAS_LIMIT_138:-300000}" \
|
||||
--legacy \
|
||||
-vv 2>&1 || echo "")
|
||||
|
||||
@@ -261,7 +305,7 @@ if echo "$BRIDGE_TX" | grep -qE "transactionHash"; then
|
||||
log_success ""
|
||||
log_info "Next Steps:"
|
||||
log_info "1. Wait for CCIP confirmation (typically 1-5 minutes)"
|
||||
log_info "2. Check transaction on Blockscout: https://explorer.d-bis.org/tx/$TX_HASH"
|
||||
log_info "2. Check transaction on Blockscout: $EXPLORER_URL_138/tx/$TX_HASH"
|
||||
log_info "3. Verify receipt on Ethereum Mainnet (Etherscan)"
|
||||
log_info "4. Your WETH9 tokens will appear at $RECIPIENT on Ethereum Mainnet"
|
||||
log_info ""
|
||||
|
||||
Reference in New Issue
Block a user