Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
基础设施与运维阅读约 11 分钟

区块链审计:范围界定、证据收集与验证的实用指南

以方法论为先的区块链审计指南:审计对象、如何从节点和 RPC 收集可复现证据,以及如何验证发现。

TL;DR

区块链审计是对链、协议或应用的安全性、正确性和合规状况进行结构化评估,并以可复现的证据为支撑。审计分为不同范围:协议与共识、智能合约、基础设施与节点运维,以及财务或合规审查。本指南解释思维模型,展示如何从节点和 RPC 端点收集可验证证据,并提供可适配的可运行诊断流程。它将文档化行为、建议以及你必须针对自身基础设施运行的测量区分开来。

区块链审计实际涵盖的内容

区块链审计是对区块链系统的安全性、功能性和合规状况进行系统性评估,并由第三方可复现的证据支撑。该术语含义宽泛:它可以指智能合约审查、协议与共识评估、基础设施与节点运维审查,或对链上活动的财务与合规审计。在任何工具发挥作用之前,范围必须明确,因为这些类别之间的证据、技能和验收标准差异很大。

本文聚焦工程侧:如何定义范围、从节点和 RPC 收集证据、运行可复现检查并报告发现。它不认证任何特定审计师或链。凡依赖你环境的论断,均以你必须运行的测量形式呈现,而非在此断言具体数值。

  • 协议审计:共识规则、网络、状态转换、密码学、升级与治理路径。
  • 智能合约审计:逻辑、访问控制、重入、算术、预言机与外部调用假设、可升级性。
  • 基础设施审计:节点配置、密钥管理、RPC 暴露、监控、备份与恢复。
  • 财务/合规审计:交易追踪、余额验证、制裁与报告义务。

开始前的先决条件与假设

假设你对目标链至少有一个支持归档的节点或 RPC 端点具有读取权限,能够在本地运行脚本,并拥有测试任何非生产环境的书面授权。对于合约审计,假设你拥有源代码、编译器设置和已部署字节码,以便确认它们匹配。对于基础设施审查,假设你可以检查节点配置和日志。

记录链 ID、审查的区块范围以及你正在审计的确切提交或部署。没有固定目标的审计不可复现。如果你需要可靠的端点来收集证据,RPC 端点指南和多链 RPC 端点指南解释了端点之间的差异;对于具体的提供商选择,RPC Assistant 提供简短建议,而非本页内容。

思维模型:主张、证据与复现

将每次审计视为一组必须用证据检验的主张。主张可能是“只有管理员角色可以暂停合约”或“节点拒绝无效状态转换”。证据是支持或反驳该主张的工件:交易追踪、存储槽读取、日志行、签名报告,或当主张为假时会失败的测试。

优秀区块链审计的显著特征是可复现性。由于链是仅追加且公开的(或至少可观测),大多数主张可以绑定到特定区块高度并在之后重新检查。记录区块号、使用的端点、工具版本和确切命令。正是这份记录将意见转化为可审计的发现。

  • 主张:关于行为、访问或状态的可证伪陈述。
  • 证据:绑定到区块高度和可复现命令的数据。
  • 发现:主张加证据加严重性和修复指导。
  • 复测:修复后重新运行相同命令并比较。

通过 RPC 收集可复现证据

大多数只读证据可以通过标准 JSON-RPC 方法收集。固定区块号以免结果漂移,并存储原始响应。以下 Python 示例在固定高度读取区块、合约字节码和存储槽。将 RPC_URL 替换为你的端点,并调整地址和槽位。

对同一区块高度运行两次并确认输出完全相同。如果不同,说明你的端点未提供一致的历史状态,这本身就是关于你证据管道的一个发现。

import json, urllib.request

RPC_URL = "RPC_URL"
BLOCK = 19000000
ADDR = "0x0000000000000000000000000000000000000000"
SLOT = "0x0"

def rpc(method, params):
    body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode()
    req = urllib.request.Request(RPC_URL, data=body, headers={"Content-Type":"application/json"})
    with urllib.request.urlopen(req, timeout=30) as r:
        out = json.loads(r.read())
    if "error" in out:
        raise RuntimeError(out["error"])
    return out["result"]

block = rpc("eth_getBlockByNumber", [hex(BLOCK), False])
code = rpc("eth_getCode", [ADDR, hex(BLOCK)])
slot = rpc("eth_getStorageAt", [ADDR, SLOT, hex(BLOCK)])
print(json.dumps({"block": BLOCK, "hash": block["hash"], "code_len": len(code), "slot": slot}, indent=2))

节点与 RPC 基础设施的诊断流程

基础设施审计的失败往往不在代码,而在运维假设:端点在不同高度的节点之间静默负载均衡、节点缺少归档数据,或速率限制破坏监控任务。以下流程检查链 ID、区块高度一致性和归档可用性。对技术栈中的每个端点运行并记录结果。

预期的验证结果是每个端点报告相同的链 ID、高度在小的、有记录的容差范围内,并且对审查的区块范围成功进行历史读取。任何未通过这些检查的端点应被排除在证据收集之外或标记为可靠性风险。

RPC_URL="RPC_URL"

curl -s -X POST "$RPC_URL" -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'

curl -s -X POST "$RPC_URL" -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"eth_blockNumber","params":[]}'

curl -s -X POST "$RPC_URL" -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":3,"method":"eth_getBlockByNumber","params":["0x1",false]}'

在可比较的表格中记录结果

保留结果表,使发现可在端点和时间之间比较。不要填写未测量的数字;在运行检查前留空单元格。像下面这样的模板,在报告中渲染为 Markdown 表格,能让审计对观察到的与假设的内容保持诚实。

端点标签链 ID检查时高度归档读取正常延迟(毫秒,实测)备注
主端点
备用端点

从上述诊断流程填充每一行。如果你运营专用基础设施,专用节点概述解释了隔离节点如何改变你正在测量的可靠性特征。关于证据收集的容量和成本规划,请参阅 RPC 定价。

智能合约范围:匹配源代码、字节码与行为

对于合约审计,第一项检查是已部署字节码与你审查的源代码和编译器设置匹配。不匹配会使所有下游结论无效。之后,针对分叉或测试环境(绝不对生产资金)进行定向调用,测试访问控制、状态转换和外部调用假设。

以下 JavaScript 示例在固定区块读取角色检查函数和暂停标志。将 ABI 片段、地址和函数选择器替换为你的目标。将任何回滚或意外值视为调查线索,而非已确认漏洞。

const RPC_URL = "RPC_URL";
const ADDR = "0x0000000000000000000000000000000000000000";
const BLOCK = "0x1220000";

async function call(data) {
  const res = await fetch(RPC_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_call", params: [{ to: ADDR, data }, BLOCK] })
  });
  return res.json();
}

(async () => {
  console.log(await call("0x5c975abb")); // paused()
  console.log(await call("0x91d14854" + "00".repeat(12) + "0000000000000000000000000000000000000000" + "00".repeat(32)));
})();

排查常见的审计证据故障

当证据收集中断时,原因通常是环境性的,而非真正的漏洞。在撰写任何内容之前,区分工具故障与发现。eth_call 的回滚可能意味着你的 calldata 格式错误,而不是合约损坏。缺失历史区块通常意味着端点不支持归档。

检查错误对象,而不仅仅是结果缺失。记录原始请求和响应。确认区块高度存在于规范链上。如果端点在不同调用间返回不一致的高度,停止将其用于证据并切换到已验证的端点。

  • calldata 格式错误:验证函数选择器和参数编码。
  • 历史缺失:确认对区块范围的归档支持。
  • 高度不一致:端点可能在滞后的节点之间负载均衡。
  • 速率限制:批量请求并添加带退避的重试,然后重新验证。
  • 链不匹配:在信任任何结果前确认链 ID。

局限性与权衡

没有审计能证明不存在缺陷。某一时间点的协议审计不覆盖未来升级,合约审计不覆盖为其提供服务的基础设施。公共 RPC 端点便于证据收集,但可能限速、滞后或提供不一致状态;专用节点以更高成本和运维负担降低该风险。

工具也存在信任权衡。自动化扫描器能捕捉模式但错过逻辑和经济假设;人工审查能捕捉更多但更慢且依赖审查者专业知识。最强的审计结合两者,并发布足够细节以便第三方重新运行关键检查。

可信审计计划的后续步骤

将上述流程转化为与区块高度和工具版本绑定的可重复检查清单,并在每次重大变更后重新运行。维护一组经过验证的端点用于证据收集,并记录每个发现使用了哪些端点。如果你正在为此工作选择基础设施,先从网络目录确认链支持,然后使用 RPC Assistant获取具体的端点推荐。

最后,在发布发现的同时发布范围、区块范围和方法论。可复现性是区块链审计与安全意见的区别所在,也是大多数团队投入不足的部分。

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始