201 lines
6.8 KiB
Bash
201 lines
6.8 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# Deploy LINK Token and Verify Confirmation
|
||
|
|
# This script actually waits for network confirmation
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
|
|
|
||
|
|
source "$PROJECT_ROOT/.env" 2>/dev/null || source "$PROJECT_ROOT/../.env" 2>/dev/null || true
|
||
|
|
|
||
|
|
RPC_URL="${RPC_URL_138:-http://192.168.11.250:8545}"
|
||
|
|
GAS_PRICE="${1:-$(cast --to-wei 20 gwei)}"
|
||
|
|
ACCOUNT=$(cast wallet address "$PRIVATE_KEY")
|
||
|
|
|
||
|
|
echo "╔══════════════════════════════════════════════════════════════╗"
|
||
|
|
echo "║ DEPLOY AND VERIFY LINK TOKEN ║"
|
||
|
|
echo "╚══════════════════════════════════════════════════════════════╝"
|
||
|
|
echo ""
|
||
|
|
echo "Account: $ACCOUNT"
|
||
|
|
echo "RPC: $RPC_URL"
|
||
|
|
echo "Gas: $(echo "scale=2; $GAS_PRICE / 1000000000" | bc) gwei"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
TEMP_DIR=$(mktemp -d)
|
||
|
|
trap "rm -rf $TEMP_DIR" EXIT
|
||
|
|
|
||
|
|
cd "$TEMP_DIR"
|
||
|
|
forge init --no-git --force . > /dev/null 2>&1
|
||
|
|
|
||
|
|
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
|
||
|
|
|
||
|
|
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));
|
||
|
|
link.mint(vm.addr(deployerPrivateKey), 1_000_000e18);
|
||
|
|
vm.stopBroadcast();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EOF
|
||
|
|
|
||
|
|
export PRIVATE_KEY
|
||
|
|
|
||
|
|
echo "=== Compiling ==="
|
||
|
|
forge build > /dev/null 2>&1
|
||
|
|
echo "✓ Compiled"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
echo "=== Deploying ==="
|
||
|
|
DEPLOY_OUTPUT=$(forge script script/DeployLink.s.sol:DeployLink \
|
||
|
|
--rpc-url "$RPC_URL" \
|
||
|
|
--private-key "$PRIVATE_KEY" \
|
||
|
|
--broadcast \
|
||
|
|
--skip-simulation \
|
||
|
|
--gas-price "$GAS_PRICE" \
|
||
|
|
--legacy \
|
||
|
|
-vv 2>&1) || true
|
||
|
|
|
||
|
|
# Extract address from console output
|
||
|
|
LINK_ADDRESS=$(echo "$DEPLOY_OUTPUT" | grep -oE "LINK_TOKEN_ADDRESS[[:space:]]+0x[0-9a-fA-F]{40}" | awk '{print $2}' || echo "")
|
||
|
|
|
||
|
|
if [ -z "$LINK_ADDRESS" ] || [ ${#LINK_ADDRESS} -ne 42 ]; then
|
||
|
|
echo "❌ Failed to extract deployment address"
|
||
|
|
echo "Output:"
|
||
|
|
echo "$DEPLOY_OUTPUT" | tail -20
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "✓ Transaction sent: $LINK_ADDRESS"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
echo "=== Waiting for Network Confirmation ==="
|
||
|
|
echo "This may take 1-5 minutes..."
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
MAX_WAIT=300 # 5 minutes
|
||
|
|
ELAPSED=0
|
||
|
|
CONFIRMED=false
|
||
|
|
|
||
|
|
while [ $ELAPSED -lt $MAX_WAIT ]; do
|
||
|
|
CODE=$(cast code "$LINK_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||
|
|
|
||
|
|
if [ -n "$CODE" ] && [ "$CODE" != "0x" ] && [ ${#CODE} -gt 100 ]; then
|
||
|
|
echo "✅✅✅ CONFIRMED!"
|
||
|
|
echo "Address: $LINK_ADDRESS"
|
||
|
|
echo "Bytecode: ${#CODE} chars"
|
||
|
|
CONFIRMED=true
|
||
|
|
break
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ $((ELAPSED % 30)) -eq 0 ]; then
|
||
|
|
echo " Waiting... (${ELAPSED}s / ${MAX_WAIT}s)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
sleep 10
|
||
|
|
ELAPSED=$((ELAPSED + 10))
|
||
|
|
done
|
||
|
|
|
||
|
|
if [ "$CONFIRMED" != "true" ]; then
|
||
|
|
echo ""
|
||
|
|
echo "⏳ Deployment not confirmed after ${MAX_WAIT} seconds"
|
||
|
|
echo "Address: $LINK_ADDRESS"
|
||
|
|
echo "Check manually: cast code $LINK_ADDRESS --rpc-url $RPC_URL"
|
||
|
|
echo ""
|
||
|
|
echo "Possible reasons:"
|
||
|
|
echo "1. Network is slow to confirm"
|
||
|
|
echo "2. Transaction may have failed"
|
||
|
|
echo "3. RPC node may be out of sync"
|
||
|
|
echo ""
|
||
|
|
echo "Check block explorer: https://explorer.d-bis.org/address/$ACCOUNT"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "=== Updating .env ==="
|
||
|
|
sed -i "s|^LINK_TOKEN=.*|LINK_TOKEN=$LINK_ADDRESS|" "$PROJECT_ROOT/.env" 2>/dev/null || \
|
||
|
|
echo "LINK_TOKEN=$LINK_ADDRESS" >> "$PROJECT_ROOT/.env"
|
||
|
|
echo "✓ Updated .env"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
echo "=== Verifying Token Functions ==="
|
||
|
|
NAME=$(cast call "$LINK_ADDRESS" "name()" --rpc-url "$RPC_URL" 2>/dev/null | cast --to-ascii 2>/dev/null | tr -d '\0' || echo "")
|
||
|
|
SYMBOL=$(cast call "$LINK_ADDRESS" "symbol()" --rpc-url "$RPC_URL" 2>/dev/null | cast --to-ascii 2>/dev/null | tr -d '\0' || echo "")
|
||
|
|
BALANCE=$(cast call "$LINK_ADDRESS" "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 "Name: $NAME"
|
||
|
|
echo "Symbol: $SYMBOL"
|
||
|
|
echo "Account Balance: $BALANCE_ETH LINK"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
if (( $(echo "$BALANCE_ETH < 20" | bc -l 2>/dev/null || echo 1) )); then
|
||
|
|
echo "=== Minting Additional Tokens ==="
|
||
|
|
MINT_AMOUNT="1000000000000000000000000"
|
||
|
|
cast send "$LINK_ADDRESS" "mint(address,uint256)" "$ACCOUNT" "$MINT_AMOUNT" \
|
||
|
|
--rpc-url "$RPC_URL" \
|
||
|
|
--private-key "$PRIVATE_KEY" \
|
||
|
|
--gas-price "$GAS_PRICE" \
|
||
|
|
--legacy \
|
||
|
|
2>&1 | tail -3
|
||
|
|
|
||
|
|
echo "Waiting 20 seconds for mint confirmation..."
|
||
|
|
sleep 20
|
||
|
|
|
||
|
|
BALANCE=$(cast call "$LINK_ADDRESS" "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 "New Balance: $BALANCE_ETH LINK"
|
||
|
|
echo ""
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "✅✅✅ LINK TOKEN DEPLOYMENT COMPLETE!"
|
||
|
|
echo "Address: $LINK_ADDRESS"
|
||
|
|
echo ""
|
||
|
|
|