diff --git a/scripts/deployment/fund-ccip-bridges-with-link.sh b/scripts/deployment/fund-ccip-bridges-with-link.sh index 6e6f455..e60fac2 100755 --- a/scripts/deployment/fund-ccip-bridges-with-link.sh +++ b/scripts/deployment/fund-ccip-bridges-with-link.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash # Fund all CCIP WETH9/WETH10 bridge contracts with LINK on each chain. # Amount via tag (not .env): --link (default 10 LINK), --dry-run to print commands only. -# Usage: ./scripts/deployment/fund-ccip-bridges-with-link.sh [--link 10] [--dry-run] +# --cap-to-deployer: per chain, each bridge gets min(--link, deployer_LINK_balance // bridges_on_chain). +# Usage: ./scripts/deployment/fund-ccip-bridges-with-link.sh [--link 10] [--cap-to-deployer] [--dry-run] set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -74,6 +75,49 @@ print_skip() { echo " Skipped (insufficient LINK balance: have ${bal%% *}, need $needed)" } +# Integer wei per bridge: min(LINK_AMOUNT_WEI, balance // n_bridges). +per_bridge_cap_wei() { + local token="$1" owner="$2" rpc="$3" n="$4" + local bal + bal=$(get_token_balance "$token" "$owner" "$rpc") + bal="${bal%% *}" + [[ "$bal" =~ ^[0-9]+$ ]] || bal="0" + [[ "${n:-1}" -lt 1 ]] && n=1 + python3 -c "b=int('$bal'); r=int('${LINK_AMOUNT_WEI}'); n=int('$n'); print(min(r, b//n))" +} + +# Echo wei to transfer for one bridge; 0 means skip. +resolve_bridge_transfer_wei() { + local token="$1" owner="$2" rpc="$3" n_bridges="$4" + if [[ "${CAP_LINK_TO_DEPLOYER_BALANCE:-0}" == "1" ]]; then + per_bridge_cap_wei "$token" "$owner" "$rpc" "$n_bridges" + return + fi + if has_sufficient_link "$token" "$owner" "$rpc" "$LINK_AMOUNT_WEI"; then + echo "$LINK_AMOUNT_WEI" + else + echo "0" + fi +} + +print_skip_or_cap_zero() { + local label="$1" token="$2" owner="$3" rpc="$4" + if [[ "${CAP_LINK_TO_DEPLOYER_BALANCE:-0}" == "1" ]]; then + local bal + bal=$(get_token_balance "$token" "$owner" "$rpc") + echo " Skipped ($label: deployer LINK ${bal%% *} wei → 0 per-bridge after split/cap vs target $LINK_AMOUNT_WEI)" + else + print_skip "$label" "$token" "$owner" "$rpc" "$LINK_AMOUNT_WEI" + fi +} + +log_capped_notice() { + local label="$1" wei="$2" + if [[ "${CAP_LINK_TO_DEPLOYER_BALANCE:-0}" == "1" ]] && [[ "$wei" != "0" ]] && [[ "$wei" -lt "$LINK_AMOUNT_WEI" ]]; then + echo " $label: transfer ${wei} wei (capped from target ${LINK_AMOUNT_WEI})" + fi +} + if [[ -z "$PRIVATE_KEY" ]]; then echo "ERROR: PRIVATE_KEY not set" >&2 exit 1 @@ -85,7 +129,8 @@ if [[ -z "$DEPLOYER_ADDR" ]]; then exit 1 fi -echo "Funding CCIP bridges with LINK (amount per bridge: $LINK_AMOUNT_WEI wei)" +echo "Funding CCIP bridges with LINK (target per bridge: $LINK_AMOUNT_WEI wei)" +[[ "${CAP_LINK_TO_DEPLOYER_BALANCE:-0}" == "1" ]] && echo "Mode: --cap-to-deployer (each chain uses min(target, balance // bridges_on_chain))" echo "Deployer: $DEPLOYER_ADDR" echo "" @@ -96,18 +141,30 @@ if [[ -n "${RPC_URL_138:-}" && -n "${LINK_TOKEN_CHAIN138:-${LINK_TOKEN:-}}" ]]; rpc=$(ensure_rpc "$RPC_URL_138") echo "Chain 138 (RPC: ${rpc%%\?*}...)" _gas138="--legacy --gas-limit 250000 --gas-price 2000000000 --timeout 120" + _n138=0 + [[ -n "${CCIPWETH9_BRIDGE_CHAIN138:-}" ]] && _n138=$((_n138 + 1)) + [[ -n "${CCIPWETH10_BRIDGE_CHAIN138:-}" ]] && _n138=$((_n138 + 1)) + _cap_once=0 + if [[ "${CAP_LINK_TO_DEPLOYER_BALANCE:-0}" == "1" ]]; then + _wei_chain138=$(per_bridge_cap_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_n138") + _cap_once=1 + fi if [[ -n "${CCIPWETH9_BRIDGE_CHAIN138:-}" ]]; then - if has_sufficient_link "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI"; then - run_or_echo "cast send $link \"transfer(address,uint256)\" ${CCIPWETH9_BRIDGE_CHAIN138,,} $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" $_gas138" + if [[ "$_cap_once" == "1" ]]; then _wei="$_wei_chain138"; else _wei=$(resolve_bridge_transfer_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_n138"); fi + if [[ "$_wei" == "0" ]]; then + print_skip_or_cap_zero "CHAIN138/WETH9" "$link" "$DEPLOYER_ADDR" "$rpc" else - print_skip "CHAIN138/WETH9" "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI" + log_capped_notice "CHAIN138/WETH9" "$_wei" + run_or_echo "cast send $link \"transfer(address,uint256)\" ${CCIPWETH9_BRIDGE_CHAIN138,,} $_wei --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" $_gas138" fi fi if [[ -n "${CCIPWETH10_BRIDGE_CHAIN138:-}" ]]; then - if has_sufficient_link "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI"; then - run_or_echo "cast send $link \"transfer(address,uint256)\" ${CCIPWETH10_BRIDGE_CHAIN138,,} $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" $_gas138" + if [[ "$_cap_once" == "1" ]]; then _wei="$_wei_chain138"; else _wei=$(resolve_bridge_transfer_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_n138"); fi + if [[ "$_wei" == "0" ]]; then + print_skip_or_cap_zero "CHAIN138/WETH10" "$link" "$DEPLOYER_ADDR" "$rpc" else - print_skip "CHAIN138/WETH10" "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI" + log_capped_notice "CHAIN138/WETH10" "$_wei" + run_or_echo "cast send $link \"transfer(address,uint256)\" ${CCIPWETH10_BRIDGE_CHAIN138,,} $_wei --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" $_gas138" fi fi echo "" @@ -119,18 +176,30 @@ if [[ -n "${ETHEREUM_MAINNET_RPC:-}" && -n "${MAINNET_LINK_TOKEN:-${CCIP_ETH_LIN rpc=$(ensure_rpc "$ETHEREUM_MAINNET_RPC") echo "Ethereum Mainnet" _pub_timeout="--timeout 300 --rpc-timeout 120" + _neth=0 + [[ -n "${MAINNET_CCIP_WETH9_BRIDGE:-}" ]] && _neth=$((_neth + 1)) + [[ -n "${MAINNET_CCIP_WETH10_BRIDGE:-}" ]] && _neth=$((_neth + 1)) + _cap_once_eth=0 + if [[ "${CAP_LINK_TO_DEPLOYER_BALANCE:-0}" == "1" ]]; then + _wei_chain_eth=$(per_bridge_cap_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_neth") + _cap_once_eth=1 + fi if [[ -n "${MAINNET_CCIP_WETH9_BRIDGE:-}" ]]; then - if has_sufficient_link "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI"; then - run_or_echo "cast send $link \"transfer(address,uint256)\" $MAINNET_CCIP_WETH9_BRIDGE $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy $_pub_timeout" + if [[ "$_cap_once_eth" == "1" ]]; then _wei="$_wei_chain_eth"; else _wei=$(resolve_bridge_transfer_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_neth"); fi + if [[ "$_wei" == "0" ]]; then + print_skip_or_cap_zero "ETH/WETH9" "$link" "$DEPLOYER_ADDR" "$rpc" else - print_skip "ETH/WETH9" "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI" + log_capped_notice "ETH/WETH9" "$_wei" + run_or_echo "cast send $link \"transfer(address,uint256)\" $MAINNET_CCIP_WETH9_BRIDGE $_wei --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy $_pub_timeout" fi fi if [[ -n "${MAINNET_CCIP_WETH10_BRIDGE:-}" ]]; then - if has_sufficient_link "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI"; then - run_or_echo "cast send $link \"transfer(address,uint256)\" $MAINNET_CCIP_WETH10_BRIDGE $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy $_pub_timeout" + if [[ "$_cap_once_eth" == "1" ]]; then _wei="$_wei_chain_eth"; else _wei=$(resolve_bridge_transfer_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_neth"); fi + if [[ "$_wei" == "0" ]]; then + print_skip_or_cap_zero "ETH/WETH10" "$link" "$DEPLOYER_ADDR" "$rpc" else - print_skip "ETH/WETH10" "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI" + log_capped_notice "ETH/WETH10" "$_wei" + run_or_echo "cast send $link \"transfer(address,uint256)\" $MAINNET_CCIP_WETH10_BRIDGE $_wei --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy $_pub_timeout" fi fi echo "" @@ -163,21 +232,43 @@ for label in BSC POLYGON BASE OPTIMISM ARBITRUM AVALANCHE CRONOS GNOSIS CELO WEM echo "$label" _pub_timeout_loop="--timeout 300 --rpc-timeout 120" - if [[ -n "$addr9" ]]; then - if has_sufficient_link "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI"; then - run_or_echo "cast send ${link,,} \"transfer(address,uint256)\" ${addr9,,} $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy $_pub_timeout_loop" + # Arbitrum: default cast fee fields can sit under base fee; bump legacy gas price from RPC. + if [[ "$label" == "ARBITRUM" ]]; then + _gp_try=$(cast gas-price --rpc-url "$rpc" 2>/dev/null | head -1 | tr -d '\r\n ' || true) + if [[ -n "$_gp_try" ]] && [[ "$_gp_try" =~ ^[0-9]+$ ]] && [[ "$_gp_try" -gt 0 ]]; then + _gp_arb=$(python3 -c "print(max(int(int('$_gp_try') * 3), 120000000))") else - print_skip "$label/WETH9" "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI" + _gp_arb="1200000000" + fi + _pub_timeout_loop="$_pub_timeout_loop --gas-price $_gp_arb" + fi + _nl2=0 + [[ -n "$addr9" ]] && _nl2=$((_nl2 + 1)) + [[ -n "$addr10" ]] && _nl2=$((_nl2 + 1)) + _cap_once_l2=0 + if [[ "${CAP_LINK_TO_DEPLOYER_BALANCE:-0}" == "1" ]]; then + _wei_chain_l2=$(per_bridge_cap_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_nl2") + _cap_once_l2=1 + fi + if [[ -n "$addr9" ]]; then + if [[ "$_cap_once_l2" == "1" ]]; then _wei="$_wei_chain_l2"; else _wei=$(resolve_bridge_transfer_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_nl2"); fi + if [[ "$_wei" == "0" ]]; then + print_skip_or_cap_zero "$label/WETH9" "$link" "$DEPLOYER_ADDR" "$rpc" + else + log_capped_notice "$label/WETH9" "$_wei" + run_or_echo "cast send ${link,,} \"transfer(address,uint256)\" ${addr9,,} $_wei --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy $_pub_timeout_loop" fi fi if [[ -n "$addr10" ]]; then - if has_sufficient_link "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI"; then - run_or_echo "cast send ${link,,} \"transfer(address,uint256)\" ${addr10,,} $LINK_AMOUNT_WEI --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy $_pub_timeout_loop" + if [[ "$_cap_once_l2" == "1" ]]; then _wei="$_wei_chain_l2"; else _wei=$(resolve_bridge_transfer_wei "$link" "$DEPLOYER_ADDR" "$rpc" "$_nl2"); fi + if [[ "$_wei" == "0" ]]; then + print_skip_or_cap_zero "$label/WETH10" "$link" "$DEPLOYER_ADDR" "$rpc" else - print_skip "$label/WETH10" "$link" "$DEPLOYER_ADDR" "$rpc" "$LINK_AMOUNT_WEI" + log_capped_notice "$label/WETH10" "$_wei" + run_or_echo "cast send ${link,,} \"transfer(address,uint256)\" ${addr10,,} $_wei --rpc-url \"$rpc\" --private-key \"\$PRIVATE_KEY\" --legacy $_pub_timeout_loop" fi fi echo "" done -echo "Done. Use --link and --dry-run to adjust." +echo "Done. Use --link , --cap-to-deployer, and --dry-run to adjust." diff --git a/scripts/lib/deployment/prompts.sh b/scripts/lib/deployment/prompts.sh index 1126bb3..87eb233 100644 --- a/scripts/lib/deployment/prompts.sh +++ b/scripts/lib/deployment/prompts.sh @@ -171,8 +171,11 @@ parse_lockbox_tag() { PARSE_LOCKBOX_REMAINING=("${args[@]}") } -# Parse --link (ETH or wei if --link-wei), --dry-run. Sets LINK_AMOUNT_WEI, DRY_RUN. +# Parse --link (ETH or wei if --link-wei), --dry-run, --cap-to-deployer. +# Sets LINK_AMOUNT_WEI, DRY_RUN, CAP_LINK_TO_DEPLOYER_BALANCE (0/1). # Default LINK_AMOUNT_WEI 10e18 (10 LINK) when unset. Unconsumed in PARSE_LINK_TAGS_REMAINING. +# --cap-to-deployer: callers (e.g. fund-ccip-bridges-with-link.sh) cap each bridge transfer to +# min(LINK_AMOUNT_WEI, deployer_LINK_balance // bridges_on_that_chain). link_to_wei() { local val="${1:-0}" if [[ -z "$val" || "$val" == "0" ]]; then echo "0"; return; fi @@ -189,6 +192,7 @@ link_to_wei() { parse_link_tags() { export LINK_AMOUNT_WEI="${LINK_AMOUNT_WEI:-10000000000000000000}" export DRY_RUN="${DRY_RUN:-0}" + export CAP_LINK_TO_DEPLOYER_BALANCE="${CAP_LINK_TO_DEPLOYER_BALANCE:-0}" local args=() local i=0 local argv=("$@") @@ -201,6 +205,7 @@ parse_link_tags() { --link-wei) [[ $((i+1)) -lt ${#argv[@]} ]] && LINK_AMOUNT_WEI="${argv[$((i+1))]}" i=$((i+2)); ;; + --cap-to-deployer) CAP_LINK_TO_DEPLOYER_BALANCE=1; i=$((i+1)); ;; --dry-run) DRY_RUN=1; i=$((i+1)); ;; *) args+=("$a"); i=$((i+1)); ;; esac