Add full monorepo: virtual-banker, backend, frontend, docs, scripts, deployment
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
297
scripts/diagnose-link-deployment.sh
Executable file
297
scripts/diagnose-link-deployment.sh
Executable file
@@ -0,0 +1,297 @@
|
||||
#!/bin/bash
|
||||
# Diagnose and fix LINK token deployment issues
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
|
||||
source .env 2>/dev/null || true
|
||||
|
||||
RPC_URL="${RPC_URL_138:-http://192.168.11.250:8545}"
|
||||
ACCOUNT=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$ACCOUNT" ]; then
|
||||
echo "Error: PRIVATE_KEY not set or invalid"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ LINK TOKEN DEPLOYMENT DIAGNOSTIC ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "Account: $ACCOUNT"
|
||||
echo "RPC: $RPC_URL"
|
||||
echo ""
|
||||
|
||||
# Check network
|
||||
echo "=== Network Status ==="
|
||||
BLOCK=$(cast block-number --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
CHAIN_ID=$(cast chain-id --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
echo "Block: $BLOCK"
|
||||
echo "Chain ID: $CHAIN_ID"
|
||||
echo ""
|
||||
|
||||
# Check account nonce and recent transactions
|
||||
echo "=== Account Status ==="
|
||||
NONCE=$(cast nonce "$ACCOUNT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
BALANCE=$(cast balance "$ACCOUNT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
BALANCE_ETH=$(cast --from-wei "$BALANCE" ether 2>/dev/null || echo "0")
|
||||
echo "Nonce: $NONCE"
|
||||
echo "Balance: $BALANCE_ETH ETH"
|
||||
echo ""
|
||||
|
||||
# Check CCIP Router for fee token
|
||||
echo "=== Checking CCIP Router for Fee Token ==="
|
||||
CCIP_ROUTER="0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e"
|
||||
ROUTER_CODE=$(cast code "$CCIP_ROUTER" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$ROUTER_CODE" ] && [ "$ROUTER_CODE" != "0x" ]; then
|
||||
echo "✓ CCIP Router exists"
|
||||
FEE_TOKEN_RAW=$(cast call "$CCIP_ROUTER" "feeToken()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$FEE_TOKEN_RAW" ] && [ "$FEE_TOKEN_RAW" != "0x" ]; then
|
||||
LINK_FROM_ROUTER=$(echo "$FEE_TOKEN_RAW" | sed 's/0x000000000000000000000000//' | sed 's/^0x//' | sed 's/^/0x/')
|
||||
echo "Router fee token: $LINK_FROM_ROUTER"
|
||||
CODE=$(cast code "$LINK_FROM_ROUTER" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$CODE" ] && [ "$CODE" != "0x" ] && [ ${#CODE} -gt 100 ]; then
|
||||
echo "✓✓✓ LINK token EXISTS at router address!"
|
||||
FOUND_LINK="$LINK_FROM_ROUTER"
|
||||
else
|
||||
echo "✗ Router references LINK, but contract not deployed"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check if LINK token exists at any known address
|
||||
echo "=== Checking Known LINK Addresses ==="
|
||||
KNOWN_LINKS=(
|
||||
"0x0cb0192C056aa425C557BdeAD8E56C7eEabf7acF"
|
||||
"0x07dE1f489E1bfCE2c326066a9DFc10e731CBA0CB"
|
||||
"0x514910771AF9Ca656af840dff83E8264EcF986CA"
|
||||
)
|
||||
|
||||
if [ -z "$FOUND_LINK" ]; then
|
||||
for LINK_ADDR in "${KNOWN_LINKS[@]}"; do
|
||||
CODE=$(cast code "$LINK_ADDR" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$CODE" ] && [ "$CODE" != "0x" ] && [ ${#CODE} -gt 100 ]; then
|
||||
echo "✓ Found LINK at: $LINK_ADDR"
|
||||
NAME=$(cast call "$LINK_ADDR" "name()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
SYMBOL=$(cast call "$LINK_ADDR" "symbol()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
echo " Name: $NAME"
|
||||
echo " Symbol: $SYMBOL"
|
||||
FOUND_LINK="$LINK_ADDR"
|
||||
break
|
||||
else
|
||||
echo "✗ No contract at: $LINK_ADDR"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# If found, use it
|
||||
if [ -n "$FOUND_LINK" ]; then
|
||||
echo "=== Using Existing LINK Token ==="
|
||||
echo "LINK Token: $FOUND_LINK"
|
||||
sed -i "s|^LINK_TOKEN=.*|LINK_TOKEN=$FOUND_LINK|" .env 2>/dev/null || echo "LINK_TOKEN=$FOUND_LINK" >> .env
|
||||
echo "✓ Updated .env"
|
||||
|
||||
# Check balance
|
||||
BALANCE=$(cast call "$FOUND_LINK" "balanceOf(address)" "$ACCOUNT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
BALANCE_ETH=$(cast --from-wei "$BALANCE" ether 2>/dev/null || echo "0")
|
||||
echo "Account Balance: $BALANCE_ETH LINK"
|
||||
|
||||
# Try to mint if balance is low
|
||||
if (( $(echo "$BALANCE_ETH < 20" | bc -l 2>/dev/null || echo 1) )); then
|
||||
echo ""
|
||||
echo "=== Attempting to Mint ==="
|
||||
FORCE_GAS="3000000000"
|
||||
CURRENT_NONCE=$(cast nonce "$ACCOUNT" --rpc-url "$RPC_URL")
|
||||
echo "Minting 1M LINK with nonce $CURRENT_NONCE..."
|
||||
MINT_OUTPUT=$(cast send "$FOUND_LINK" "mint(address,uint256)" "$ACCOUNT" $(cast --to-wei 1000000 ether) \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--gas-price "$FORCE_GAS" \
|
||||
--nonce "$CURRENT_NONCE" \
|
||||
--legacy 2>&1 || echo "FAILED")
|
||||
|
||||
if echo "$MINT_OUTPUT" | grep -qE "(blockHash|transactionHash)"; then
|
||||
echo "✓ Mint transaction sent"
|
||||
TX_HASH=$(echo "$MINT_OUTPUT" | grep -oE "0x[0-9a-f]{64}" | head -1)
|
||||
echo "Transaction: $TX_HASH"
|
||||
echo "Waiting 15 seconds for confirmation..."
|
||||
sleep 15
|
||||
else
|
||||
echo "⚠ Mint may not be available (standard LINK token)"
|
||||
echo "You may need to acquire LINK from another source"
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# If not found, try fresh deployment
|
||||
echo "=== No Existing LINK Found - Deploying Fresh ==="
|
||||
echo ""
|
||||
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
# Create minimal project
|
||||
forge init --no-git --force . > /dev/null 2>&1
|
||||
|
||||
# Create MockLinkToken
|
||||
cat > src/MockLinkToken.sol << 'EOF'
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
contract MockLinkToken {
|
||||
string public name = "Chainlink Token";
|
||||
string public symbol = "LINK";
|
||||
uint8 public decimals = 18;
|
||||
|
||||
mapping(address => uint256) public balanceOf;
|
||||
mapping(address => mapping(address => uint256)) public allowance;
|
||||
uint256 public totalSupply;
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
|
||||
function mint(address to, uint256 amount) external {
|
||||
balanceOf[to] += amount;
|
||||
totalSupply += amount;
|
||||
emit Transfer(address(0), to, amount);
|
||||
}
|
||||
|
||||
function transfer(address to, uint256 amount) external returns (bool) {
|
||||
require(balanceOf[msg.sender] >= amount, "insufficient balance");
|
||||
balanceOf[msg.sender] -= amount;
|
||||
balanceOf[to] += amount;
|
||||
emit Transfer(msg.sender, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transferFrom(address from, address to, uint256 amount) external returns (bool) {
|
||||
require(balanceOf[from] >= amount, "insufficient balance");
|
||||
require(allowance[from][msg.sender] >= amount, "insufficient allowance");
|
||||
balanceOf[from] -= amount;
|
||||
balanceOf[to] += amount;
|
||||
allowance[from][msg.sender] -= amount;
|
||||
emit Transfer(from, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function approve(address spender, uint256 amount) external returns (bool) {
|
||||
allowance[msg.sender][spender] = amount;
|
||||
emit Approval(msg.sender, spender, amount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create deployment script
|
||||
cat > script/DeployLink.s.sol << 'EOF'
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {MockLinkToken} from "../src/MockLinkToken.sol";
|
||||
|
||||
contract DeployLink is Script {
|
||||
function run() external {
|
||||
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
|
||||
vm.startBroadcast(deployerPrivateKey);
|
||||
|
||||
MockLinkToken link = new MockLinkToken();
|
||||
console.log("LINK_TOKEN_ADDRESS", address(link));
|
||||
|
||||
// Mint 1M LINK to deployer
|
||||
link.mint(vm.addr(deployerPrivateKey), 1_000_000e18);
|
||||
console.log("Minted 1M LINK");
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Build
|
||||
echo "Building contract..."
|
||||
forge build > /dev/null 2>&1
|
||||
|
||||
# Deploy with very high gas
|
||||
FORCE_GAS="5000000000" # 5 gwei
|
||||
CURRENT_NONCE=$(cast nonce "$ACCOUNT" --rpc-url "$RPC_URL")
|
||||
|
||||
echo "Deploying with:"
|
||||
echo " Gas: $FORCE_GAS wei ($(echo "scale=2; $FORCE_GAS / 1000000000" | bc) gwei)"
|
||||
echo " Nonce: $CURRENT_NONCE"
|
||||
echo ""
|
||||
|
||||
DEPLOY_OUTPUT=$(forge script script/DeployLink.s.sol:DeployLink \
|
||||
--rpc-url "$RPC_URL" \
|
||||
--private-key "$PRIVATE_KEY" \
|
||||
--broadcast \
|
||||
--skip-simulation \
|
||||
--gas-price "$FORCE_GAS" \
|
||||
--legacy \
|
||||
-vv 2>&1 || echo "FAILED")
|
||||
|
||||
NEW_LINK=$(echo "$DEPLOY_OUTPUT" | grep -oE "LINK_TOKEN_ADDRESS[[:space:]]+0x[0-9a-fA-F]{40}" | awk '{print $2}')
|
||||
|
||||
if [ -z "$NEW_LINK" ]; then
|
||||
NEW_LINK=$(echo "$DEPLOY_OUTPUT" | grep -oE "0x[0-9a-fA-F]{40}" | head -1)
|
||||
fi
|
||||
|
||||
if [ -n "$NEW_LINK" ] && [ ${#NEW_LINK} -eq 42 ]; then
|
||||
echo "✓✓✓ LINK deployed: $NEW_LINK"
|
||||
echo "$NEW_LINK" > /tmp/link_address.txt
|
||||
|
||||
# Update .env
|
||||
cd "$SCRIPT_DIR/.."
|
||||
sed -i "s|^LINK_TOKEN=.*|LINK_TOKEN=$NEW_LINK|" .env 2>/dev/null || echo "LINK_TOKEN=$NEW_LINK" >> .env
|
||||
echo "✓ Updated .env"
|
||||
|
||||
# Wait and verify
|
||||
echo ""
|
||||
echo "Waiting 30 seconds for network confirmation..."
|
||||
sleep 30
|
||||
|
||||
CODE=$(cast code "$NEW_LINK" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
if [ -n "$CODE" ] && [ "$CODE" != "0x" ] && [ ${#CODE} -gt 100 ]; then
|
||||
echo "✓✓✓ Contract CONFIRMED!"
|
||||
NAME=$(cast call "$NEW_LINK" "name()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
SYMBOL=$(cast call "$NEW_LINK" "symbol()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||||
echo " Name: $NAME"
|
||||
echo " Symbol: $SYMBOL"
|
||||
|
||||
BALANCE=$(cast call "$NEW_LINK" "balanceOf(address)" "$ACCOUNT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
BALANCE_ETH=$(cast --from-wei "$BALANCE" ether 2>/dev/null || echo "0")
|
||||
echo " Balance: $BALANCE_ETH LINK"
|
||||
|
||||
if (( $(echo "$BALANCE_ETH < 20" | bc -l 2>/dev/null || echo 1) )); then
|
||||
echo ""
|
||||
echo "⚠ Balance low, waiting for mint to confirm..."
|
||||
for i in {1..12}; do
|
||||
sleep 5
|
||||
BALANCE=$(cast call "$NEW_LINK" "balanceOf(address)" "$ACCOUNT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
||||
BALANCE_ETH=$(cast --from-wei "$BALANCE" ether 2>/dev/null || echo "0")
|
||||
if (( $(echo "$BALANCE_ETH >= 20" | bc -l 2>/dev/null || echo 0) )); then
|
||||
echo "✓ Balance confirmed: $BALANCE_ETH LINK"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
echo "⚠ Contract not yet confirmed"
|
||||
echo "Code length: ${#CODE}"
|
||||
echo "This may take additional time. Check again with:"
|
||||
echo " cast code $NEW_LINK --rpc-url $RPC_URL"
|
||||
fi
|
||||
else
|
||||
echo "✗ Deployment failed"
|
||||
echo "Output:"
|
||||
echo "$DEPLOY_OUTPUT" | grep -E "(Error|error|FAILED|revert)" | head -10
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
Reference in New Issue
Block a user