Files
explorer-monorepo/scripts/deploy-via-rpc-json.sh

208 lines
6.8 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Deploy Smart Contract via eth_sendSignedTransaction (JSON-RPC)
# Bypasses forge and uses direct JSON-RPC calls
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}"
PRIVATE_KEY="${PRIVATE_KEY:-}"
GAS_PRICE="${1:-20000000000}" # 20 gwei
GAS_LIMIT="${2:-10000000}" # 10M gas
if [ -z "$PRIVATE_KEY" ]; then
echo "Error: PRIVATE_KEY not set"
exit 1
fi
DEPLOYER=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || echo "")
if [ -z "$DEPLOYER" ]; then
echo "Error: Invalid PRIVATE_KEY"
exit 1
fi
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ DEPLOY CONTRACT VIA eth_sendSignedTransaction ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
echo "RPC: $RPC_URL"
echo "Deployer: $DEPLOYER"
echo "Gas Price: $GAS_PRICE"
echo "Gas Limit: $GAS_LIMIT"
echo ""
# Step 1: Compile contract
echo "Step 1: Compiling contract..."
TEMP_DIR=$(mktemp -d)
cd "$TEMP_DIR"
forge init --no-git --force . > /dev/null 2>&1
# Create minimal test contract
cat > src/TestMinimal.sol << 'EOF'
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract TestMinimal {
uint256 public x = 1;
function setX(uint256 _x) external {
x = _x;
}
}
EOF
forge build > /dev/null 2>&1
# Get bytecode
BYTECODE=$(cat out/TestMinimal.sol/TestMinimal.json | jq -r '.bytecode.object' 2>/dev/null || echo "")
if [ -z "$BYTECODE" ] || [ "$BYTECODE" = "null" ]; then
echo "❌ Failed to compile contract"
exit 1
fi
echo "✅ Contract compiled (bytecode length: ${#BYTECODE} chars)"
echo ""
# Step 2: Get nonce
echo "Step 2: Getting deployer nonce..."
NONCE=$(cast nonce "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
NONCE_HEX=$(printf "0x%x" "$NONCE")
echo "Nonce: $NONCE ($NONCE_HEX)"
echo ""
# Step 3: Get chain ID
echo "Step 3: Getting chain ID..."
CHAIN_ID=$(cast chain-id --rpc-url "$RPC_URL" 2>/dev/null || echo "138")
CHAIN_ID_HEX=$(printf "0x%x" "$CHAIN_ID")
echo "Chain ID: $CHAIN_ID ($CHAIN_ID_HEX)"
echo ""
# Step 4: Create transaction
echo "Step 4: Creating transaction..."
echo "Transaction details:"
echo " From: $DEPLOYER"
echo " To: null (contract creation)"
echo " Value: 0"
echo " Data: $BYTECODE (first 100 chars: ${BYTECODE:0:100}...)"
echo " Gas: $GAS_LIMIT"
echo " Gas Price: $GAS_PRICE"
echo " Nonce: $NONCE"
echo " Chain ID: $CHAIN_ID"
echo ""
# Step 5: Deploy using cast send directly
echo "Step 5: Deploying contract using cast send..."
echo "This uses eth_sendTransaction internally..."
echo ""
TX_HASH=$(cast send --private-key "$PRIVATE_KEY" \
--rpc-url "$RPC_URL" \
--gas "$GAS_LIMIT" \
--gas-price "$GAS_PRICE" \
--nonce "$NONCE" \
--value 0 \
--data "$BYTECODE" \
--legacy \
--json 2>/dev/null | jq -r '.transactionHash // empty' 2>/dev/null || echo "")
if [ -z "$TX_HASH" ]; then
echo "❌ Failed to send transaction via cast send"
echo ""
echo "Trying alternative: Create raw transaction and send via JSON-RPC..."
# Create raw transaction
RAW_TX=$(cast tx --from "$DEPLOYER" \
--to "" \
--nonce "$NONCE" \
--gas "$GAS_LIMIT" \
--gas-price "$GAS_PRICE" \
--value 0 \
--data "$BYTECODE" \
--chain "$CHAIN_ID" \
--rpc-url "$RPC_URL" \
--json 2>/dev/null | jq -r '.raw // empty' 2>/dev/null || echo "")
if [ -n "$RAW_TX" ]; then
echo "✅ Created raw transaction"
echo "Sending via eth_sendRawTransaction..."
RESPONSE=$(curl -s -X POST -H "Content-Type: application/json" \
--data "{\"jsonrpc\":\"2.0\",\"method\":\"eth_sendRawTransaction\",\"params\":[\"$RAW_TX\"],\"id\":1}" \
"$RPC_URL" 2>&1)
TX_HASH=$(echo "$RESPONSE" | jq -r '.result // empty' 2>/dev/null || echo "")
if [ -z "$TX_HASH" ] || [ "$TX_HASH" = "null" ]; then
ERROR=$(echo "$RESPONSE" | jq -r '.error.message // empty' 2>/dev/null || echo "")
echo "❌ Error: $ERROR"
echo "Response: $RESPONSE"
fi
fi
fi
# Step 6: Wait for confirmation
if [ -n "$TX_HASH" ] && [ "$TX_HASH" != "null" ]; then
echo "✅ Transaction sent: $TX_HASH"
echo ""
echo "Waiting for confirmation..."
sleep 15
RECEIPT=$(cast receipt "$TX_HASH" --rpc-url "$RPC_URL" --json 2>/dev/null || echo "")
if [ -n "$RECEIPT" ]; then
STATUS=$(echo "$RECEIPT" | jq -r '.status // empty' 2>/dev/null || echo "")
CONTRACT=$(echo "$RECEIPT" | jq -r '.contractAddress // empty' 2>/dev/null || echo "")
GAS_USED=$(echo "$RECEIPT" | jq -r '.gasUsed // empty' 2>/dev/null || echo "")
echo "Transaction Receipt:"
echo " Status: $STATUS"
echo " Gas Used: $GAS_USED"
echo " Contract Address: $CONTRACT"
echo ""
if [ "$STATUS" = "0x1" ]; then
echo "✅ Contract deployed successfully!"
# Verify contract exists
CODE=$(cast code "$CONTRACT" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ -n "$CODE" ] && [ "$CODE" != "0x" ] && [ ${#CODE} -gt 100 ]; then
echo "✅ Contract verified on-chain (${#CODE} chars)"
echo ""
echo "Contract Address: $CONTRACT"
echo "Save this address for future use!"
else
echo "⚠️ Contract code not found on-chain"
fi
else
echo "❌ Transaction failed (status: $STATUS)"
echo "Contract Address: $CONTRACT"
echo ""
echo "If DEBUG API is enabled, get revert reason:"
echo " curl -X POST -H 'Content-Type: application/json' \\"
echo " --data '{\"jsonrpc\":\"2.0\",\"method\":\"debug_traceTransaction\",\"params\":[\"$TX_HASH\",{\"tracer\":\"callTracer\"}],\"id\":1}' \\"
echo " $RPC_URL | jq"
fi
else
echo "⏳ Transaction not yet confirmed"
echo "Transaction Hash: $TX_HASH"
echo "Check status later with: cast receipt $TX_HASH --rpc-url $RPC_URL"
fi
else
echo "❌ Could not deploy contract"
echo ""
echo "Troubleshooting:"
echo " 1. Check deployer balance: cast balance $DEPLOYER --rpc-url $RPC_URL"
echo " 2. Verify RPC is accessible: cast block-number --rpc-url $RPC_URL"
echo " 3. Check network allows contract creation"
fi
cd "$PROJECT_ROOT"
rm -rf "$TEMP_DIR"
echo ""