#!/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 # 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)" # Load .env via dotenv (RPC CR/LF trim). Fallback: raw source. if [[ -f "$SCRIPT_DIR/../lib/deployment/dotenv.sh" ]]; then # shellcheck disable=SC1090 source "$SCRIPT_DIR/../lib/deployment/dotenv.sh" load_deployment_env --repo-root "${PROJECT_ROOT:-$REPO_ROOT}" elif [[ -n "${PROJECT_ROOT:-}" && -f "$PROJECT_ROOT/.env" ]]; then set -a # shellcheck disable=SC1090 source "$PROJECT_ROOT/.env" set +a elif [[ -n "${REPO_ROOT:-}" && -f "$REPO_ROOT/.env" ]]; then set -a # shellcheck disable=SC1090 source "$REPO_ROOT/.env" set +a fi 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; } # 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 "; 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 \"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 )" echo " AMOUNT_WEI=$AMOUNT_WEI $0 claim" echo "Or manually: cast logs \"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)."