|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +usage() { |
| 5 | + cat <<'EOF' |
| 6 | +Register PegIn using cast (avoids forge local simulation bridge checks). |
| 7 | +
|
| 8 | +Usage: |
| 9 | + script/tasks/register-pegin-cast.sh \ |
| 10 | + --network development \ |
| 11 | + --quote-file script/tasks/hash-quote.example.json \ |
| 12 | + --signature <lp-signature-hex> \ |
| 13 | + --txid <bitcoin-txid> \ |
| 14 | + [--broadcast --private-key <hex-key>] |
| 15 | +
|
| 16 | +Options: |
| 17 | + --network mainnet|testnet|development|dev (default: development) |
| 18 | + --quote-file Path to PegIn quote JSON (required) |
| 19 | + --signature LP signature (required) |
| 20 | + --txid BTC transaction id (required) |
| 21 | + --rpc-url Override RPC URL |
| 22 | + --pegin-address Override PegIn contract address |
| 23 | + --btc-network mainnet|testnet (default inferred from network) |
| 24 | + --broadcast Send transaction (default: eth_call only) |
| 25 | + --private-key Required when --broadcast |
| 26 | + --gas-limit Tx gas limit for broadcast (default: 10000000) |
| 27 | + -h, --help Show this message |
| 28 | +EOF |
| 29 | +} |
| 30 | + |
| 31 | +require_cmd() { |
| 32 | + command -v "$1" >/dev/null 2>&1 || { |
| 33 | + echo "Error: missing required command '$1'" >&2 |
| 34 | + exit 1 |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +with_0x() { |
| 39 | + local value="${1:-}" |
| 40 | + if [[ -z "$value" ]]; then |
| 41 | + echo "0x" |
| 42 | + return |
| 43 | + fi |
| 44 | + if [[ "$value" == 0x* ]]; then |
| 45 | + echo "$value" |
| 46 | + else |
| 47 | + echo "0x${value}" |
| 48 | + fi |
| 49 | +} |
| 50 | + |
| 51 | +btc_addr_to_hex() { |
| 52 | + local btc_addr="$1" |
| 53 | + npx ts-node script/helpers/parse-btc-address.ts "$btc_addr" | tr -d '\n' |
| 54 | +} |
| 55 | + |
| 56 | +NETWORK="${NETWORK:-development}" |
| 57 | +QUOTE_FILE="${PEGIN_QUOTE_FILE:-}" |
| 58 | +SIGNATURE="${PEGIN_SIGNATURE:-}" |
| 59 | +TXID="${PEGIN_TXID:-}" |
| 60 | +RPC_URL="${RPC_URL:-}" |
| 61 | +PEGIN_ADDRESS="${PEGIN_CONTRACT_ADDRESS:-}" |
| 62 | +BTC_NETWORK="${BTC_NETWORK:-}" |
| 63 | +PRIVATE_KEY="${PRIVATE_KEY:-}" |
| 64 | +GAS_LIMIT="${GAS_LIMIT:-10000000}" |
| 65 | +BROADCAST=false |
| 66 | + |
| 67 | +while [[ $# -gt 0 ]]; do |
| 68 | + case "$1" in |
| 69 | + --network) NETWORK="$2"; shift 2 ;; |
| 70 | + --quote-file) QUOTE_FILE="$2"; shift 2 ;; |
| 71 | + --signature) SIGNATURE="$2"; shift 2 ;; |
| 72 | + --txid) TXID="$2"; shift 2 ;; |
| 73 | + --rpc-url) RPC_URL="$2"; shift 2 ;; |
| 74 | + --pegin-address) PEGIN_ADDRESS="$2"; shift 2 ;; |
| 75 | + --btc-network) BTC_NETWORK="$2"; shift 2 ;; |
| 76 | + --private-key) PRIVATE_KEY="$2"; shift 2 ;; |
| 77 | + --gas-limit) GAS_LIMIT="$2"; shift 2 ;; |
| 78 | + --broadcast) BROADCAST=true; shift 1 ;; |
| 79 | + -h|--help) usage; exit 0 ;; |
| 80 | + *) |
| 81 | + echo "Error: unknown argument '$1'" >&2 |
| 82 | + usage |
| 83 | + exit 1 |
| 84 | + ;; |
| 85 | + esac |
| 86 | +done |
| 87 | + |
| 88 | +[[ -n "$QUOTE_FILE" ]] || { echo "Error: quote file is required (PEGIN_QUOTE_FILE or --quote-file)" >&2; exit 1; } |
| 89 | +[[ -f "$QUOTE_FILE" ]] || { echo "Error: quote file not found: $QUOTE_FILE" >&2; exit 1; } |
| 90 | +[[ -n "$SIGNATURE" ]] || { echo "Error: signature is required (PEGIN_SIGNATURE or --signature)" >&2; exit 1; } |
| 91 | +[[ -n "$TXID" ]] || { echo "Error: txid is required (PEGIN_TXID or --txid)" >&2; exit 1; } |
| 92 | + |
| 93 | +require_cmd jq |
| 94 | +require_cmd cast |
| 95 | +require_cmd npx |
| 96 | + |
| 97 | +case "$NETWORK" in |
| 98 | + mainnet) |
| 99 | + [[ -n "$RPC_URL" ]] || RPC_URL="${MAINNET_RPC_URL:-https://public-node.rsk.co}" |
| 100 | + [[ -n "$BTC_NETWORK" ]] || BTC_NETWORK="mainnet" |
| 101 | + RSK_NETWORK_NAME="rskMainnet" |
| 102 | + ;; |
| 103 | + testnet) |
| 104 | + [[ -n "$RPC_URL" ]] || RPC_URL="${TESTNET_RPC_URL:-https://public-node.testnet.rsk.co}" |
| 105 | + [[ -n "$BTC_NETWORK" ]] || BTC_NETWORK="testnet" |
| 106 | + RSK_NETWORK_NAME="rskTestnet" |
| 107 | + ;; |
| 108 | + development) |
| 109 | + [[ -n "$RPC_URL" ]] || RPC_URL="${TESTNET_RPC_URL:-https://public-node.testnet.rsk.co}" |
| 110 | + [[ -n "$BTC_NETWORK" ]] || BTC_NETWORK="testnet" |
| 111 | + RSK_NETWORK_NAME="rskDevelopment" |
| 112 | + ;; |
| 113 | + dev) |
| 114 | + [[ -n "$RPC_URL" ]] || RPC_URL="${REGTEST_RPC_URL:-http://localhost:4444}" |
| 115 | + [[ -n "$BTC_NETWORK" ]] || BTC_NETWORK="testnet" |
| 116 | + RSK_NETWORK_NAME="rskRegtest" |
| 117 | + ;; |
| 118 | + *) |
| 119 | + echo "Error: unsupported network '$NETWORK'" >&2 |
| 120 | + exit 1 |
| 121 | + ;; |
| 122 | +esac |
| 123 | + |
| 124 | +if [[ -z "$PEGIN_ADDRESS" ]]; then |
| 125 | + PEGIN_ADDRESS="$(jq -r --arg network "$RSK_NETWORK_NAME" '.[$network].PegInContract.address // empty' addresses.json)" |
| 126 | +fi |
| 127 | +[[ -n "$PEGIN_ADDRESS" ]] || { |
| 128 | + echo "Error: could not resolve PegIn address (set PEGIN_CONTRACT_ADDRESS or --pegin-address)" >&2 |
| 129 | + exit 1 |
| 130 | +} |
| 131 | + |
| 132 | +CHAIN_ID="$(cast chain-id --rpc-url "$RPC_URL")" |
| 133 | + |
| 134 | +FED_BTC_ADDR="$(jq -r '.fedBTCAddr' "$QUOTE_FILE")" |
| 135 | +LBC_ADDR="$(jq -r '.lbcAddr' "$QUOTE_FILE")" |
| 136 | +LP_RSK_ADDR="$(jq -r '.lpRSKAddr' "$QUOTE_FILE")" |
| 137 | +BTC_REFUND_ADDR="$(jq -r '.btcRefundAddr' "$QUOTE_FILE")" |
| 138 | +RSK_REFUND_ADDR="$(jq -r '.rskRefundAddr' "$QUOTE_FILE")" |
| 139 | +LP_BTC_ADDR="$(jq -r '.lpBTCAddr' "$QUOTE_FILE")" |
| 140 | + |
| 141 | +CALL_FEE="$(jq -r '.callFee|tostring' "$QUOTE_FILE")" |
| 142 | +PENALTY_FEE="$(jq -r '.penaltyFee|tostring' "$QUOTE_FILE")" |
| 143 | +VALUE="$(jq -r '.value|tostring' "$QUOTE_FILE")" |
| 144 | +GAS_FEE="$(jq -r '.gasFee|tostring' "$QUOTE_FILE")" |
| 145 | +CONTRACT_ADDR="$(jq -r '.contractAddr' "$QUOTE_FILE")" |
| 146 | +DATA="$(jq -r '.data' "$QUOTE_FILE")" |
| 147 | +GAS_LIMIT_QUOTE="$(jq -r '.gasLimit|tostring' "$QUOTE_FILE")" |
| 148 | +NONCE="$(jq -r '.nonce|tostring' "$QUOTE_FILE")" |
| 149 | +AGREEMENT_TIMESTAMP="$(jq -r '.agreementTimestamp|tostring' "$QUOTE_FILE")" |
| 150 | +TIME_FOR_DEPOSIT="$(jq -r '.timeForDeposit|tostring' "$QUOTE_FILE")" |
| 151 | +LP_CALL_TIME="$(jq -r '.lpCallTime|tostring' "$QUOTE_FILE")" |
| 152 | +CONFIRMATIONS="$(jq -r '.confirmations|tostring' "$QUOTE_FILE")" |
| 153 | +CALL_ON_REGISTER="$(jq -r '.callOnRegister' "$QUOTE_FILE")" |
| 154 | + |
| 155 | +FED_ADDR_FULL_HEX="$(btc_addr_to_hex "$FED_BTC_ADDR")" |
| 156 | +FED_ADDR_FULL_HEX="${FED_ADDR_FULL_HEX#0x}" |
| 157 | +if [[ "${#FED_ADDR_FULL_HEX}" -lt 42 ]]; then |
| 158 | + echo "Error: parsed fedBTCAddr has invalid length: $FED_BTC_ADDR" >&2 |
| 159 | + exit 1 |
| 160 | +fi |
| 161 | +FED_BTC_BYTES20="0x${FED_ADDR_FULL_HEX:2:40}" |
| 162 | +BTC_REFUND_BYTES="$(with_0x "$(btc_addr_to_hex "$BTC_REFUND_ADDR")")" |
| 163 | +LP_BTC_BYTES="$(with_0x "$(btc_addr_to_hex "$LP_BTC_ADDR")")" |
| 164 | +DATA="$(with_0x "$DATA")" |
| 165 | +SIGNATURE="$(with_0x "$SIGNATURE")" |
| 166 | + |
| 167 | +TX_JSON="$(npx ts-node script/helpers/fetch-btc-tx-data.ts "$TXID" "$BTC_NETWORK")" |
| 168 | +RAW_TX="$(with_0x "$(jq -r '.rawTx' <<<"$TX_JSON")")" |
| 169 | +PMT="$(with_0x "$(jq -r '.pmt' <<<"$TX_JSON")")" |
| 170 | +HEIGHT="$(jq -r '.height|tostring' <<<"$TX_JSON")" |
| 171 | + |
| 172 | +ABI_SIG='registerPegIn((uint256,uint256,uint256,uint256,uint256,bytes20,address,address,address,address,int64,uint32,uint32,uint32,uint32,uint16,bool,bytes,bytes,bytes),bytes,bytes,bytes,uint256)' |
| 173 | +QUOTE_TUPLE="(${CHAIN_ID},${CALL_FEE},${PENALTY_FEE},${VALUE},${GAS_FEE},${FED_BTC_BYTES20},${LBC_ADDR},${LP_RSK_ADDR},${CONTRACT_ADDR},${RSK_REFUND_ADDR},${NONCE},${GAS_LIMIT_QUOTE},${AGREEMENT_TIMESTAMP},${TIME_FOR_DEPOSIT},${LP_CALL_TIME},${CONFIRMATIONS},${CALL_ON_REGISTER},${BTC_REFUND_BYTES},${LP_BTC_BYTES},${DATA})" |
| 174 | + |
| 175 | +echo "Registering PegIn via cast on $NETWORK" |
| 176 | +echo "RPC URL: $RPC_URL" |
| 177 | +echo "PegIn Contract: $PEGIN_ADDRESS" |
| 178 | +echo "BTC tx height: $HEIGHT" |
| 179 | + |
| 180 | +if [[ "$BROADCAST" == true ]]; then |
| 181 | + [[ -n "$PRIVATE_KEY" ]] || { echo "Error: private key is required in broadcast mode" >&2; exit 1; } |
| 182 | + cast send "$PEGIN_ADDRESS" "$ABI_SIG" "$QUOTE_TUPLE" "$SIGNATURE" "$RAW_TX" "$PMT" "$HEIGHT" \ |
| 183 | + --rpc-url "$RPC_URL" \ |
| 184 | + --private-key "$(with_0x "$PRIVATE_KEY")" \ |
| 185 | + --legacy \ |
| 186 | + --gas-limit "$GAS_LIMIT" |
| 187 | +else |
| 188 | + cast call "$PEGIN_ADDRESS" "$ABI_SIG" "$QUOTE_TUPLE" "$SIGNATURE" "$RAW_TX" "$PMT" "$HEIGHT" \ |
| 189 | + --rpc-url "$RPC_URL" |
| 190 | +fi |
0 commit comments