182 lines
5.8 KiB
Bash
182 lines
5.8 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# Update Oracle Contract with Current ETH/USD Price
|
||
|
|
# This script fetches the current ETH price from CoinGecko and updates the oracle contract
|
||
|
|
# Usage: ./scripts/update-oracle-price.sh [rpc-url] [oracle-address] [private-key]
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
# Colors
|
||
|
|
RED='\033[0;31m'
|
||
|
|
GREEN='\033[0;32m'
|
||
|
|
YELLOW='\033[1;33m'
|
||
|
|
BLUE='\033[0;34m'
|
||
|
|
NC='\033[0m'
|
||
|
|
|
||
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||
|
|
|
||
|
|
RPC_URL="${1:-https://rpc-http-pub.d-bis.org}"
|
||
|
|
ORACLE_ADDRESS="${2:-0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6}"
|
||
|
|
PRIVATE_KEY="${3:-${DEPLOYER_PRIVATE_KEY:-}}"
|
||
|
|
|
||
|
|
if [ -z "$PRIVATE_KEY" ]; then
|
||
|
|
log_error "Private key required"
|
||
|
|
log_info "Usage: $0 [rpc-url] [oracle-address] [private-key]"
|
||
|
|
log_info " OR: Set DEPLOYER_PRIVATE_KEY environment variable"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "========================================="
|
||
|
|
echo "Update Oracle Price Feed"
|
||
|
|
echo "========================================="
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
log_info "RPC URL: $RPC_URL"
|
||
|
|
log_info "Oracle Address: $ORACLE_ADDRESS"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Check RPC connectivity
|
||
|
|
log_info "Checking RPC connectivity..."
|
||
|
|
if ! curl -s -X POST -H "Content-Type: application/json" \
|
||
|
|
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||
|
|
"$RPC_URL" >/dev/null 2>&1; then
|
||
|
|
log_error "RPC is not accessible at $RPC_URL"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
log_success "RPC is accessible"
|
||
|
|
|
||
|
|
# Fetch current ETH price from CoinGecko
|
||
|
|
log_info "Fetching ETH/USD price from CoinGecko..."
|
||
|
|
ETH_PRICE=$(curl -s 'https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd' | \
|
||
|
|
python3 -c "import sys, json; data = json.load(sys.stdin); print(data.get('ethereum', {}).get('usd', '0'))" 2>/dev/null || echo "0")
|
||
|
|
|
||
|
|
if [ "$ETH_PRICE" = "0" ] || [ -z "$ETH_PRICE" ]; then
|
||
|
|
log_error "Failed to fetch ETH price from CoinGecko"
|
||
|
|
log_info "Trying Binance API as fallback..."
|
||
|
|
ETH_PRICE=$(curl -s 'https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT' | \
|
||
|
|
python3 -c "import sys, json; data = json.load(sys.stdin); print(data.get('price', '0'))" 2>/dev/null || echo "0")
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ "$ETH_PRICE" = "0" ] || [ -z "$ETH_PRICE" ]; then
|
||
|
|
log_error "Failed to fetch ETH price from all sources"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
log_success "ETH/USD Price: \$$ETH_PRICE"
|
||
|
|
|
||
|
|
# Convert to 8 decimals (oracle format)
|
||
|
|
PRICE_DECIMALS=$(python3 << PYEOF
|
||
|
|
price = float("$ETH_PRICE")
|
||
|
|
decimals = int(price * 100000000)
|
||
|
|
print(decimals)
|
||
|
|
PYEOF
|
||
|
|
)
|
||
|
|
|
||
|
|
log_info "Price in 8 decimals: $PRICE_DECIMALS"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Check current oracle price
|
||
|
|
log_info "Checking current oracle price..."
|
||
|
|
CURRENT_ORACLE_DATA=$(cast call "$ORACLE_ADDRESS" \
|
||
|
|
"latestRoundData()" \
|
||
|
|
--rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||
|
|
|
||
|
|
if [ -n "$CURRENT_ORACLE_DATA" ] && [ "$CURRENT_ORACLE_DATA" != "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ]; then
|
||
|
|
# Parse current price
|
||
|
|
CURRENT_ANSWER=$(echo "$CURRENT_ORACLE_DATA" | cut -c 131-194) # Extract answer field
|
||
|
|
CURRENT_PRICE=$(python3 << PYEOF
|
||
|
|
answer_hex = "$CURRENT_ANSWER"
|
||
|
|
answer_int = int(answer_hex, 16)
|
||
|
|
# Handle negative (if signed)
|
||
|
|
if answer_int > 2**255:
|
||
|
|
answer_int = answer_int - 2**256
|
||
|
|
price = answer_int / 100000000
|
||
|
|
print(price)
|
||
|
|
PYEOF
|
||
|
|
)
|
||
|
|
log_info "Current oracle price: \$$(printf '%.2f' $CURRENT_PRICE)"
|
||
|
|
|
||
|
|
# Check if update is needed (only update if difference > 1%)
|
||
|
|
PRICE_DIFF=$(python3 << PYEOF
|
||
|
|
current = float("$CURRENT_PRICE")
|
||
|
|
new = float("$ETH_PRICE")
|
||
|
|
diff = abs(new - current) / current * 100
|
||
|
|
print(diff)
|
||
|
|
PYEOF
|
||
|
|
)
|
||
|
|
|
||
|
|
if (( $(echo "$PRICE_DIFF < 1" | bc -l) )); then
|
||
|
|
log_warn "Price difference is less than 1% (${PRICE_DIFF}%)"
|
||
|
|
log_info "Skipping update to save gas"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Update oracle contract
|
||
|
|
log_info "Updating oracle contract..."
|
||
|
|
log_info "This will send a transaction to update the price feed..."
|
||
|
|
|
||
|
|
# Check if updateAnswer function exists, if not try transmit
|
||
|
|
if cast sig "updateAnswer(int256)" >/dev/null 2>&1; then
|
||
|
|
UPDATE_METHOD="updateAnswer"
|
||
|
|
elif cast sig "transmit(int256)" >/dev/null 2>&1; then
|
||
|
|
UPDATE_METHOD="transmit"
|
||
|
|
else
|
||
|
|
log_error "Could not determine oracle update method"
|
||
|
|
log_info "Please check the oracle contract ABI"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
log_info "Using method: $UPDATE_METHOD"
|
||
|
|
|
||
|
|
# Send transaction
|
||
|
|
TX_HASH=$(cast send "$ORACLE_ADDRESS" \
|
||
|
|
"$UPDATE_METHOD(int256)" \
|
||
|
|
"$PRICE_DECIMALS" \
|
||
|
|
--rpc-url "$RPC_URL" \
|
||
|
|
--private-key "$PRIVATE_KEY" \
|
||
|
|
--json 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('transactionHash', ''))" || echo "")
|
||
|
|
|
||
|
|
if [ -z "$TX_HASH" ]; then
|
||
|
|
log_error "Failed to send transaction"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
log_success "Transaction sent: $TX_HASH"
|
||
|
|
|
||
|
|
# Wait for confirmation
|
||
|
|
log_info "Waiting for transaction confirmation..."
|
||
|
|
sleep 5
|
||
|
|
|
||
|
|
# Verify update
|
||
|
|
log_info "Verifying oracle update..."
|
||
|
|
NEW_ORACLE_DATA=$(cast call "$ORACLE_ADDRESS" \
|
||
|
|
"latestRoundData()" \
|
||
|
|
--rpc-url "$RPC_URL" 2>/dev/null || echo "")
|
||
|
|
|
||
|
|
if [ -n "$NEW_ORACLE_DATA" ]; then
|
||
|
|
NEW_ANSWER=$(echo "$NEW_ORACLE_DATA" | cut -c 131-194)
|
||
|
|
NEW_PRICE=$(python3 << PYEOF
|
||
|
|
answer_hex = "$NEW_ANSWER"
|
||
|
|
answer_int = int(answer_hex, 16)
|
||
|
|
if answer_int > 2**255:
|
||
|
|
answer_int = answer_int - 2**256
|
||
|
|
price = answer_int / 100000000
|
||
|
|
print(price)
|
||
|
|
PYEOF
|
||
|
|
)
|
||
|
|
log_success "Oracle updated successfully!"
|
||
|
|
log_info "New oracle price: \$$(printf '%.2f' $NEW_PRICE)"
|
||
|
|
else
|
||
|
|
log_warn "Could not verify oracle update (may need more time for confirmation)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
log_success "========================================="
|
||
|
|
log_success "Oracle Price Update Complete!"
|
||
|
|
log_success "========================================="
|
||
|
|
echo ""
|
||
|
|
|