コンテンツへスキップ

Constellationのミニプール作成を自動化

Constellationはミニプールの1人あたりの個数上限があるものの、上限に達していない人同士では早いもの勝ちです。

xrETHのデポジットプールに8ETH以上溜まったら、一番早くトランザクションを送信した人がミニプールの作成に成功します。1ブロックでも出遅れ、デポジットプールが8ETH以下になってしまったらトランザクションは失敗し、約400円の手数料を無駄にします。成功時のガス代も高く(9gweiで約7千円)、できるだけ6gwei以下でミニプールを作成したいです。

手動では各ブロックおき(約12秒おき)にコマンドを打たないと勝ち目がないため、シェルスクリプトで自動化しました。

下記のスクリプトでは、ローカルの実行クライアントからデポジットプールの残量と現在のガス代を取得し、デポジットプールが8ETH以上、且つ現在のガス代+1gweiが9以下の時、現在のガス代+1gweiでミニプール作成のコマンドを実行します。

#!/bin/bash

# ============================================================================
# Ethereum Gas Price Monitor and Minipool Launcher
# ============================================================================

# Define the Parameters
RPC_URL="http://localhost:8545"
OPR_DIST_CONTRACT_ADDR=0x102809fe582ecaa527bb316dcc4e99fc35fbabb9
MIN_POOL_SIZE=8 # in ETH
ADDITIONAL_GAS=2 # in gwei
GAS_THRESHOLD=9.1 # in ETH


# End of Parameters ==========================================================
# Start of Functions =========================================================

# Function to get the latest block number
get_latest_block() {
    local latest_block_response
    local latest_block
    latest_block_response=$(curl -s -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' -H "Content-Type: application/json" $RPC_URL)
    latest_block=$(echo $latest_block_response | jq -r '.result' | xargs printf "%d\n")
    echo "$latest_block"
}

# Function to fetch the current gas price
get_gas() {
    local gas_price_response
    local gas_price_hex
    local gas_price_decimal
    local gas_price_gwei
    gas_price_response=$(curl -s -X POST --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}' -H "Content-Type: application/json" $RPC_URL)
    gas_price_hex=$(echo $gas_price_response | jq -r '.result')
    gas_price_decimal=$(printf "%d\n" $gas_price_hex)
    gas_price_gwei=$(echo "scale=9; $gas_price_decimal / 1000000000" | bc)
    echo "$gas_price_gwei"
}

# Function to get ETH balance for a contract address from local Nethermind node
get_pool_eth_balance() {
    local response
    local balance
    local ether_balance

    # Use JSON-RPC to get the balance of the contract address
    response=$(curl -s -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["'"$OPR_DIST_CONTRACT_ADDR"'", "latest"],"id":1}' -H "Content-Type: application/json" $RPC_URL)

    # Check if the response contains a result
    if [[ $(echo "$response" | jq -r '.result') != "null" ]]; then
        balance=$(echo "$response" | jq -r '.result')
        # Convert the hex balance to decimal wei, then to ether
        ether_balance=$(echo "scale=9; $(printf "%d\n" $balance) / 1000000000000000000" | bc)
        echo "$ether_balance"
    else
        echo "-1"
    fi
}


# End of Functions ===========================================================
# Start of Main ==============================================================

echo "$(date "+%Y-%m-%d %H:%M:%S") Minipool Launcher Started"
LAST_BLOCK=""

# Main loop
while true; do

    # Loop until block number changes
    while true; do
        CURRENT_BLOCK=$(get_latest_block)
        if [ "$LAST_BLOCK" != "$CURRENT_BLOCK" ]; then
            # echo "$(date "+%Y-%m-%d %H:%M:%S") New block detected: $CURRENT_BLOCK"
            LAST_BLOCK=$CURRENT_BLOCK
            break
        fi
        sleep 1
    done

    # Get current xrETH deposit pool size
    CURRENT_POOL=$(get_pool_eth_balance)

    # Try to make minipool if pool size is above threshhold
    if (( $(echo "$CURRENT_POOL >= $MIN_POOL_SIZE" | bc -l) )); then

        # Get gas price and set transaction gas
        GAS_PRICE=$(get_gas)
        TRANSACTION_GAS=$(echo "$GAS_PRICE + $ADDITIONAL_GAS" | bc | awk '{printf "%.1f", $0}')

        # Check if transaction gas is below threshold
        if (( $(echo "$TRANSACTION_GAS < $GAS_THRESHOLD" | bc -l) )); then

            # Try minipool creation
            echo "$(date "+%Y-%m-%d %H:%M:%S") Block $CURRENT_BLOCK: Trying minipool creation with gas price $TRANSACTION_GAS"
            COMMAND="hyperdrive -f $TRANSACTION_GAS -i 0.1 cs m c -y"
            # echo "hyperdrive -f $TRANSACTION_GAS -i 0.1 cs m c -y"

            # Show output
            OUTPUT=$($COMMAND | sed '/^$/d')
            echo "$OUTPUT"

            # Determine if minipool creation was successful
            if [[ "$OUTPUT" =~ "Minipool created successfully" ]]; then
                echo "$(date "+%Y-%m-%d %H:%M:%S") Minipool creation successful. Ending script."
                echo "$(date "+%Y-%m-%d %H:%M:%S") Ending script"
                exit 0
            elif [[ "$OUTPUT" =~ "Cannot create" ]]; then
                : # Continue the loop
            else
                echo "$(date "+%Y-%m-%d %H:%M:%S") Unexpected output. Ending script."
                exit 0
            fi
        else
            echo "$(date "+%Y-%m-%d %H:%M:%S") Block $CURRENT_BLOCK: Transaction gas ($TRANSACTION_GAS) is above the threshold ($GAS_THRESHOLD)"
        fi
    else
        echo "$(date "+%Y-%m-%d %H:%M:%S") Block $CURRENT_BLOCK: Current xrETH pool size ($CURRENT_POOL) is lower than $MIN_POOL_SIZE"
    fi

done