231 lines
8.3 KiB
Bash
Executable File
231 lines
8.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Force Deploy LINK Token - All Methods
|
|
# Tries multiple approaches to force forge to broadcast
|
|
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}"
|
|
FORCE_GAS="${1:-5000000000}" # Default 5 gwei (increased for better confirmation)
|
|
|
|
# Export variables to ensure they're available in subshells
|
|
export RPC_URL
|
|
export PRIVATE_KEY
|
|
|
|
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
echo "║ FORCE DEPLOY LINK TOKEN - ALL METHODS ║"
|
|
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
echo "RPC: $RPC_URL"
|
|
echo "Forced Gas: $(echo "scale=2; $FORCE_GAS / 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
|
|
|
|
cat > foundry.toml << EOF
|
|
[profile.default]
|
|
gas_price = $FORCE_GAS
|
|
legacy = true
|
|
|
|
[rpc_endpoints]
|
|
chain138 = "$RPC_URL"
|
|
EOF
|
|
|
|
export PRIVATE_KEY
|
|
|
|
echo "=== Method 1: forge script with --broadcast --skip-simulation ==="
|
|
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) || true
|
|
|
|
LINK_ADDRESS=$(echo "$DEPLOY_OUTPUT" | grep -oE "LINK_TOKEN_ADDRESS[[:space:]]+0x[0-9a-fA-F]{40}" | awk '{print $2}' || echo "")
|
|
|
|
# Verify broadcast actually happened
|
|
if echo "$DEPLOY_OUTPUT" | grep -qi "dry run\|simulation only\|not broadcasting"; then
|
|
echo "⚠️ WARNING: Script may have run in dry-run mode despite --broadcast flag"
|
|
echo "Output contains dry-run indicators"
|
|
LINK_ADDRESS="" # Clear address if dry-run detected
|
|
fi
|
|
|
|
# Verify deployment actually happened on-chain (not just simulation)
|
|
if [ -n "$LINK_ADDRESS" ] && [ ${#LINK_ADDRESS} -eq 42 ]; then
|
|
echo "Address extracted: $LINK_ADDRESS"
|
|
echo "Verifying on-chain deployment (waiting 15 seconds)..."
|
|
sleep 15 # Wait for transaction to propagate
|
|
CODE=$(cast code "$LINK_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
|
if [ -n "$CODE" ] && [ "$CODE" != "0x" ] && [ ${#CODE} -gt 100 ]; then
|
|
echo "✓✓✓ SUCCESS! LINK deployed and CONFIRMED: $LINK_ADDRESS"
|
|
echo "$LINK_ADDRESS" > /tmp/link_address.txt
|
|
exit 0
|
|
else
|
|
echo "⚠️ Address extracted but contract not yet on-chain"
|
|
echo "This may be from simulation. Trying Method 2..."
|
|
LINK_ADDRESS="" # Clear to force Method 2
|
|
fi
|
|
fi
|
|
|
|
echo "Method 1 failed, trying Method 2..."
|
|
echo ""
|
|
|
|
echo "=== Method 2: forge create with explicit gas and verify ==="
|
|
# Ensure RPC_URL is set and not empty
|
|
if [ -z "$RPC_URL" ]; then
|
|
echo "ERROR: RPC_URL is not set!"
|
|
RPC_URL="http://192.168.11.250:8545"
|
|
echo "Using default: $RPC_URL"
|
|
export RPC_URL
|
|
fi
|
|
|
|
# Ensure PRIVATE_KEY is set
|
|
if [ -z "$PRIVATE_KEY" ]; then
|
|
echo "ERROR: PRIVATE_KEY is not set!"
|
|
echo "Cannot deploy without private key"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Deploying with forge create (this may take a moment)..."
|
|
DEPLOY_OUTPUT=$(forge create src/MockLinkToken.sol:MockLinkToken \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--gas-price "$FORCE_GAS" \
|
|
--gas-limit 10000000 \
|
|
--legacy \
|
|
--broadcast \
|
|
2>&1) || true
|
|
|
|
echo "Deployment output:"
|
|
echo "$DEPLOY_OUTPUT" | head -20
|
|
|
|
LINK_ADDRESS=$(echo "$DEPLOY_OUTPUT" | grep -oE "Deployed to: 0x[0-9a-fA-F]{40}" | awk '{print $3}' || echo "")
|
|
|
|
# Also check for errors
|
|
if echo "$DEPLOY_OUTPUT" | grep -qi "error\|fail\|revert"; then
|
|
echo "⚠️ Deployment errors detected in output above"
|
|
fi
|
|
|
|
if [ -n "$LINK_ADDRESS" ] && [ ${#LINK_ADDRESS} -eq 42 ]; then
|
|
echo "✓✓✓ SUCCESS! LINK deployed: $LINK_ADDRESS"
|
|
echo "$LINK_ADDRESS" > /tmp/link_address.txt
|
|
exit 0
|
|
fi
|
|
|
|
echo "Method 2 failed, trying Method 3..."
|
|
echo ""
|
|
|
|
echo "=== Method 3: Get bytecode and deploy via cast send ==="
|
|
forge build > /dev/null 2>&1
|
|
BYTECODE=$(cat out/MockLinkToken.sol/MockLinkToken.json | jq -r '.bytecode.object' 2>/dev/null || echo "")
|
|
|
|
if [ -n "$BYTECODE" ] && [ "$BYTECODE" != "null" ] && [ ${#BYTECODE} -gt 100 ]; then
|
|
ACCOUNT=$(cast wallet address "$PRIVATE_KEY")
|
|
NONCE=$(cast nonce "$ACCOUNT" --rpc-url "$RPC_URL")
|
|
|
|
echo "Deploying via cast send..."
|
|
TX_OUTPUT=$(timeout 60 cast send --create "$BYTECODE" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--gas-price "$FORCE_GAS" \
|
|
--nonce "$NONCE" \
|
|
--legacy \
|
|
2>&1) || true
|
|
|
|
LINK_ADDRESS=$(echo "$TX_OUTPUT" | grep -oE "contractAddress[[:space:]]+0x[0-9a-fA-F]{40}" | awk '{print $2}' || echo "")
|
|
|
|
if [ -z "$LINK_ADDRESS" ]; then
|
|
LINK_ADDRESS=$(echo "$TX_OUTPUT" | grep -oE "0x[0-9a-fA-F]{40}" | head -1 || echo "")
|
|
fi
|
|
|
|
if [ -n "$LINK_ADDRESS" ] && [ ${#LINK_ADDRESS} -eq 42 ]; then
|
|
echo "✓✓✓ SUCCESS! LINK deployed: $LINK_ADDRESS"
|
|
echo "$LINK_ADDRESS" > /tmp/link_address.txt
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
echo "║ ALL METHODS FAILED ║"
|
|
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
echo "Possible issues:"
|
|
echo "1. Network RPC not responding"
|
|
echo "2. Stuck transaction at nonce 37 blocking new transactions"
|
|
echo "3. Network requires different gas configuration"
|
|
echo "4. Private key or account issues"
|
|
echo ""
|
|
echo "Recommendation: Use Remix IDE to deploy"
|
|
echo " https://remix.ethereum.org"
|
|
echo ""
|
|
exit 1
|
|
|