Ethereum Read Only

Polar Sponsor
爱发电 赞助
.NET 9.0

Walletless On-Chain State Reads Using Foundry Cast

Ethereum読み取り専用アクセス

功能概述

Ethereum読み取り専用アクセス是一项面向实际任务的技能,主要用于Foundryの cast コマンドを使用してウォレットなしでEthereumブロックチェーンの状態を読み取る方法;ブロック情報、コントラクト状態、イベントログ、ENS解決の実装ガイドです;

核心要点

  • セットアップ;
  • Foundryインストール;
  • RPC設定;

使用与执行

ブロック情報取得;基本的なブロック検査;ブロック範囲分析;コントラクト状態読み取り;基本的なコントラクト呼び出し。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。

结果检查与注意事项

从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。该技能适合用于一次性任务,也可以接入自动化工作流,与其他技能或上层代理配合完成更完整的业务链路;在组合使用时,应明确每一步的输入输出关系,并避免不同步骤之间出现参数冲突。

Ethereum 读取专用访问

使用 Foundry 的 cast 命令,在无需钱包的情况下读取 Ethereum 区块链状态。本指南涵盖区块信息查询、合约状态读取、事件日志检索以及 ENS 解析等实用场景。

设置

安装 Foundry

# 安装 Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup

# 验证安装
cast --version

RPC 配置

# 设置环境变量(写入 ~/.bashrc 或 ~/.zshrc)
export ETH_RPC_URL="https://eth-mainnet.alchemyapi.io/v2/YOUR-API-KEY"
export POLYGON_RPC_URL="https://polygon-mainnet.g.alchemy.com/v2/YOUR-API-KEY"
export ARB_RPC_URL="https://arb-mainnet.g.alchemy.com/v2/YOUR-API-KEY"

# 使用免费 RPC(含速率限制)
export ETH_RPC_URL="https://rpc.ankr.com/eth"
export POLYGON_RPC_URL="https://rpc.ankr.com/polygon"

# 验证配置
cast client --rpc-url $ETH_RPC_URL

获取区块信息

基础区块检查

#!/bin/bash
# block-inspector.sh

# 获取最新区块号
get_latest_block() {
    echo "最新区块号:"
    cast block-number --rpc-url $ETH_RPC_URL
}

# 查询区块基本信息
inspect_block() {
    local block_number="$1"
    
    echo "=== 区块 $block_number 基本信息 ==="
    cast block "$block_number" --rpc-url $ETH_RPC_URL
}

# 查询含交易的完整区块详情
inspect_block_full() {
    local block_number="$1"
    
    echo "=== 区块 $block_number 详细信息(含交易)==="
    cast block "$block_number" --full --rpc-url $ETH_RPC_URL
}

# 区块统计信息
block_stats() {
    local block_number="$1"
    
    echo "=== 区块 $block_number 统计信息 ==="
    
    # 交易数量
    local tx_count="$(cast block "$block_number" --rpc-url $ETH_RPC_URL | jq -r '.transactions | length')"
    echo "交易数量: $tx_count"
    
    # Gas 消耗量
    local gas_used="$(cast block "$block_number" --rpc-url $ETH_RPC_URL | jq -r '.gasUsed')"
    echo "Gas 消耗量: $gas_used"
    
    # 时间戳
    local timestamp="$(cast block "$block_number" --rpc-url $ETH_RPC_URL | jq -r '.timestamp')"
    echo "区块时间: $(date -d @$((timestamp)) +'%Y-%m-%d %H:%M:%S')"
}

# 示例用法
get_latest_block
inspect_block "latest"
block_stats "latest"

区块范围分析

# block-range-analyzer.sh

analyze_block_range() {
    local start_block="$1"
    local end_block="$2"
    
    echo "=== 区块范围分析: $start_block - $end_block ==="
    
    local total_tx=0
    local total_gas=0
    
    for ((block=$start_block; block<=$end_block; block++)); do
        echo "正在处理区块 $block..."
        
        local block_data="$(cast block "$block" --rpc-url $ETH_RPC_URL)"
        local tx_count="$(echo "$block_data" | jq -r '.transactions | length')"
        local gas_used="$(echo "$block_data" | jq -r '.gasUsed')"
        
        total_tx=$((total_tx + tx_count))
        total_gas=$((total_gas + gas_used))
        
        echo "  TX: $tx_count, Gas: $gas_used"
    done
    
    echo ""
    echo "=== 汇总 ==="
    echo "总交易数: $total_tx"
    echo "总 Gas 消耗量: $total_gas"
    echo "平均每区块交易数: $((total_tx / (end_block - start_block + 1)))"
}

# 示例用法
analyze_block_range 19000000 19000010

读取合约状态

基础合约调用

#!/bin/bash
# contract-reader.sh

# 检查 ERC20 代币余额
check_erc20_balance() {
    local token_address="$1"
    local wallet_address="$2"
    
    echo "=== ERC20 余额检查 ==="
    echo "代币地址: $token_address"
    echo "钱包地址: $wallet_address"
    
    # 调用 balanceOf(address) 函数
    local balance="$(cast call "$token_address" \
        "balanceOf(address)(uint256)" \
        "$wallet_address" \
        --rpc-url $ETH_RPC_URL)"
    
    echo "余额: $balance"
    
    # 获取代币名称
    local name="$(cast call "$token_address" \
        "name()(string)" \
        --rpc-url $ETH_RPC_URL)"
    
    # 获取代币符号
    local symbol="$(cast call "$token_address" \
        "symbol()(string)" \
        --rpc-url $ETH_RPC_URL)"
    
    # 获取小数位数
    local decimals="$(cast call "$token_address" \
        "decimals()(uint8)" \
        --rpc-url $ETH_RPC_URL)"
    
    echo "代币名称: $name"
    echo "符号: $symbol"
    echo "小数位数: $decimals"
    
    # 转换为人类可读格式
    local human_balance="$(cast to-dec "$balance")"
    local scaled_balance="$(echo "scale=6; $human_balance / 10^$decimals" | bc -l)"
    echo "显示余额: $scaled_balance $symbol"
}

# 获取 Uniswap V3 流动性池信息
check_uniswap_pool() {
    local pool_address="$1"
    
    echo "=== Uniswap V3 流动性池信息 ==="
    echo "池地址: $pool_address"
    
    # 获取池基础信息
    local token0="$(cast call "$pool_address" "token0()(address)" --rpc-url $ETH_RPC_URL)"
    local token1="$(cast call "$pool_address" "token1()(address)" --rpc-url $ETH_RPC_URL)"
    local fee="$(cast call "$pool_address" "fee()(uint24)" --rpc-url $ETH_RPC_URL)"
    
    echo "Token0: $token0"
    echo "Token1: $token1"
    echo "手续费: $(cast to-dec "$fee") (0.01% = 100)"
    
    # 获取当前流动性与价格
    local liquidity="$(cast call "$pool_address" "liquidity()(uint128)" --rpc-url $ETH_RPC_URL)"
    echo "流动性: $(cast to-dec "$liquidity")"
    
    # 获取 slot0 信息(价格、tick 等)
    local slot0="$(cast call "$pool_address" "slot0()(uint160,int24,uint16,uint16,uint16,uint8,bool)" --rpc-url $ETH_RPC_URL)"
    echo "Slot0: $slot0"
}

# ENS 反向解析
resolve_ens() {
    local address="$1"
    
    echo "=== ENS 解析 ==="
    echo "地址: $address"
    
    # 执行 ENS 名称解析
    local ens_name="$(cast lookup-address "$address" --rpc-url $ETH_RPC_URL 2>/dev/null || echo "无")"
    echo "ENS 名称: $ens_name"
}

# 示例用法
check_erc20_balance "0xA0b86a33E6441b04B9b73f9251e9b49Cd2B3a64" "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"  # USDC, Vitalik
check_uniswap_pool "0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8"  # USDC/ETH 0.3%
resolve_ens "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

事件日志检索

日志检索系统

#!/bin/bash
# event-log-searcher.sh

# 搜索 Transfer 事件
search_transfer_events() {
    local contract_address="$1"
    local from_block="$2"
    local to_block="$3"
    local sender="${4:-}"
    local receiver="${5:-}"
    
    echo "=== Transfer 事件搜索 ==="
    echo "合约地址: $contract_address"
    echo "区块范围: $from_block - $to_block"
    
    # Transfer(address,address,uint256) 事件签名
    local transfer_sig="0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
    
    # 构建基础搜索命令
    local cmd="cast logs --rpc-url $ETH_RPC_URL"
    cmd="$cmd --address $contract_address"
    cmd="$cmd --from-block $from_block"
    cmd="$cmd --to-block $to_block"
    cmd="$cmd $transfer_sig"
    
    # 添加过滤器
    if [[ -n "$sender" ]]; then
        cmd="$cmd $sender"
    fi
    
    if [[ -n "$receiver" ]]; then
        if [[ -z "$sender" ]]; then
            cmd="$cmd '' $receiver"  # 若未指定 sender,则传空字符串
        else
            cmd="$cmd $receiver"
        fi
    fi
    
    echo "执行命令: $cmd"
    
    # 执行日志查询并解析结果
    eval "$cmd" | jq -r '.[] | "区块: (.blockNumber), TX: (.transactionHash), 日志索引: (.logIndex)"'
}

# 通用事件搜索
search_custom_events() {
    local contract_address="$1"
    local event_signature="$2"
    local from_block="$3"
    local to_block="$4"
    
    echo "=== 自定义事件搜索 ==="
    echo "签名: $event_signature"
    
    cast logs \
        --address "$contract_address" \
        --from-block "$from_block" \
        --to-block "$to_block" \
        "$event_signature" \
        --rpc-url $ETH_RPC_URL \
        | jq '.'
}

# DEX 交易分析
analyze_dex_trades() {
    local pool_address="$1"
    local from_block="$2"
    local to_block="$3"
    
    echo "=== DEX 交易分析 ==="
    
    # Swap 事件 (Uniswap V3: Swap(address,address,int256,int256,uint160,uint128,int24))
    local swap_sig="0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67"
    
    cast logs \
        --address "$pool_address" \
        --from-block "$from_block" \
        --to-block "$to_block" \
        "$swap_sig" \
        --rpc-url $ETH_RPC_URL \
        | jq -r '.[] | "交易: 区块 (.blockNumber), TX (.transactionHash), Gas 消耗: (.gasUsed)"'
}

# 示例用法
search_transfer_events "0xA0b86a33E6441b04B9b73f9251e9b49Cd2B3a64" "19000000" "19000100"  # USDC transfers
search_custom_events "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984" "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" "19000000" "19000050"  # UNI Approval

ENS 操作

ENS 解析系统

#!/bin/bash
# ens-resolver.sh

# 从 ENS 名称解析地址
resolve_ens_to_address() {
    local ens_name="$1"
    
    echo "=== ENS → 地址解析 ==="
    echo "ENS 名称: $ens_name"
    
    # 基础地址解析
    local address="$(cast resolve-name "$ens_name" --rpc-url $ETH_RPC_URL)"
    echo "地址: $address"
    
    # 获取内容哈希(如 IPFS)
    local content_hash="$(cast call 0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63 \
        "contenthash(bytes32)(bytes)" \
        "$(cast namehash "$ens_name")" \
        --rpc-url $ETH_RPC_URL 2>/dev/null || echo "无")"
    echo "内容哈希: $content_hash"
    
    # 获取文本记录
    echo "文本记录:"
    for key in "email" "url" "avatar" "description" "notice" "keywords" "com.github" "com.twitter"; do
        local value="$(cast call 0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63 \
            "text(bytes32,string)(string)" \
            "$(cast namehash "$ens_name")" \
            "$key" \
            --rpc-url $ETH_RPC_URL 2>/dev/null || echo "")"
        if [[ -n "$value" && "$value" != '""' ]]; then
            echo "  $key: $value"
        fi
    done
}

# 从地址解析 ENS 名称
resolve_address_to_ens() {
    local address="$1"
    
    echo "=== 地址 → ENS 解析 ==="
    echo "地址: $address"
    
    local ens_name="$(cast lookup-address "$address" --rpc-url $ETH_RPC_URL 2>/dev/null || echo "无")"
    echo "ENS 名称: $ens_name"
    
    # 检查是否为主域名
    if [[ "$ens_name" != "无" ]]; then
        local reverse_address="$(cast resolve-name "$ens_name" --rpc-url $ETH_RPC_URL)"
        if [[ "$reverse_address" == "$address" ]]; then
            echo "主域名: 是"
        else
            echo "主域名: 否($reverse_address)"
        fi
    fi
}

# ENS 域名详细信息
ens_domain_info() {
    local ens_name="$1"
    
    echo "=== ENS 域名详细信息 ==="
    
    # 所有者信息
    local owner="$(cast call 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e \
        "owner(bytes32)(address)" \
        "$(cast namehash "$ens_name")" \
        --rpc-url $ETH_RPC_URL)"
    echo "所有者: $owner"
    
    # 注册商信息(仅限 .eth 域名)
    if [[ "$ens_name" == *.eth ]]; then
        local registrar="0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85"
        local token_id="$(cast keccak "$(echo -n "${ens_name%.eth}")")"
        
        local registrant="$(cast call "$registrar" \
            "ownerOf(uint256)(address)" \
            "$token_id" \
            --rpc-url $ETH_RPC_URL 2>/dev/null || echo "无")"
        echo "注册人: $registrant"
        
        # 到期时间
        local expires="$(cast call "$registrar" \
            "nameExpires(uint256)(uint256)" \
            "$token_id" \
            --rpc-url $ETH_RPC_URL 2>/dev/null || echo "0")"
        if [[ "$expires" != "0" ]]; then
            echo "到期时间: $(date -d @$((expires)) +'%Y-%m-%d %H:%M:%S')"
        fi
    fi
}

# 示例用法
resolve_ens_to_address "vitalik.eth"
resolve_address_to_ens "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
ens_domain_info "uniswap.eth"

ABI 解码

交易与日志解析

#!/bin/bash
# abi-decoder.sh

# 解码函数调用
decode_function_call() {
    local tx_hash="$1"
    local abi_file="$2"  # JSON 文件或 Etherscan 签名

    echo "=== 函数调用解码 ==="
    echo "TX: $tx_hash"
    
    # 获取交易详情
    local tx_data="$(cast tx "$tx_hash" --rpc-url $ETH_RPC_URL)"
    local input_data="$(echo "$tx_data" | jq -r '.input')"
    local to_address="$(echo "$tx_data" | jq -r '.to')"
    
    echo "目标地址: $to_address"
    echo "输入数据: ${input_data:0:50}..."
    
    # 提取 4 字节选择器
    local selector="${input_data:2:8}"
    echo "函数选择器: 0x$selector"
    
    # 从 4byte.directory 查询函数名
    local function_sig="$(curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x$selector" | jq -r '.results[0].text_signature')"
    echo "函数签名: $function_sig"
    
    # 若提供 ABI 文件则进行解码
    if [[ -f "$abi_file" ]]; then
        cast 4byte-decode "$input_data" --abi-path "$abi_file"
    fi
}

# 解码事件日志
decode_event_log() {
    local tx_hash="$1"
    local log_index="$2"
    local abi_file="$3"
    
    echo "=== 事件日志解码 ==="
    
    # 获取日志条目
    local logs="$(cast receipt "$tx_hash" --rpc-url $ETH_RPC_URL | jq ".logs[$log_index]")"
    local topics="$(echo "$logs" | jq -r '.topics[]')"
    local data="$(echo "$logs" | jq -r '.data')"
    
    echo "主题: $topics"
    echo "数据: $data"
    
    # 解析事件签名
    local event_sig="$(echo "$topics" | head -1 | cut -c3-)"
    local event_name="$(curl -s "https://www.4byte.directory/api/v1/event-signatures/?hex_signature=0x$event_sig" | jq -r '.results[0].text_signature')"
    echo "事件签名: $event_name"
    
    # ABI 解码(Foundry 对日志解码支持有限,需额外工具辅助)
    if [[ -f "$abi_file" ]]; then
        echo "详细解码需配合 ABI 文件及额外工具完成"
    fi
}

# 常用函数选择器字典
common_selectors() {
    echo "=== 常用函数选择器 ==="
    cat << 'EOF'
0xa9059cbb: transfer(address,uint256)
0x095ea7b3: approve(address,uint256)
0x23b872dd: transferFrom(address,address,uint256)
0x70a08231: balanceOf(address)
0x18160ddd: totalSupply()
0xdd62ed3e: allowance(address,address)
0x40c10f19: mint(address,uint256)
0x42966c68: burn(uint256)
0x7ff36ab5: swapExactETHForTokens(uint256,address[],address,uint256)
0x38ed1739: swapExactTokensForTokens(uint256,uint256,address[],address,uint256)
EOF
}

# 示例用法
common_selectors
# decode_function_call "0x..." "./erc20.abi.json"

实用脚本示例

DeFi 投资组合检查器

#!/bin/bash
# defi-portfolio-checker.sh

check_defi_portfolio() {
    local wallet="$1"
    
    echo "=== DeFi 投资组合: $wallet ==="
    
    # ETH 余额
    local eth_balance="$(cast balance "$wallet" --rpc-url $ETH_RPC_URL)"
    echo "ETH: $(cast to-ether "$eth_balance") ETH"
    
    # 主流代币余额
    local tokens=(
        "0xA0b86a33E6441b04B9b73f9251e9b49Cd2B3a64:USDC:6"
        "0xdAC17F958D2ee523a2206206994597C13D831ec7:USDT:6" 
        "0x6B175474E89094C44Da98b954EedeAC495271d0F:DAI:18"
        "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984:UNI:18"
    )
    
    for token in "${tokens[@]}"; do
        IFS=':' read -r address symbol decimals <<< "$token"
        local balance="$(cast call "$address" "balanceOf(address)(uint256)" "$wallet" --rpc-url $ETH_RPC_URL)"
        local human_balance="$(echo "scale=4; $(cast to-dec "$balance") / 10^$decimals" | bc -l)"
        echo "$symbol: $human_balance"
    done
}

# 示例用法
check_defi_portfolio "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

包含钱包管理与交易发送功能的完整 cast CLI 指南,可在 kairyuu.net/exchange/ 交易中获取。

相关专题

更多
Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

0

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

0

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

0

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

0

12

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

2026.11.05

0

12

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

2026.11.04

0

16

XORM框架结构体映射与表结构同步
XORM框架结构体映射与表结构同步

本专题围绕XORM框架的结构体映射展开,说明表名与字段的命名策略、xorm标签常用属性、主键自增与时间字段自动填充,并演示Sync2自动建表、增量字段升级、索引声明与反向生成结构体的完整流程。

2026.11.04

0

15

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

2026.11.04

0

15

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

2026.11.04

0

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习