欢迎光临
我们一直在努力

智能合约评审如何识别隐性风险

智能合约评审如何识别隐性风险

封面信息图

AI 能很快补出 Solidity 的骨架,但它不理解这份合约在什么资产、什么升级路径和什么权限体系里运行。评审时,语法正确并不是通过理由。更可靠的起点是把需求拆成状态、不变量和外部边界:谁能改参数,资金总额如何变化,失败时哪些状态必须保持不变。

先看状态转换,再看函数写法

以领取奖励为例,评审者要先写清楚余额的来源、扣减时点、可领取额度的计算方式,以及同一笔份额能否重复领取。随后再检查代码是否遵循检查、更新状态、外部交互的顺序。nonReentrant 有用,但不是替代推理的印章;跨函数共享的余额、暂停状态和回调路径仍可能形成问题。

function withdraw(uint256 amount) external nonReentrant {
uint256 available = claimable[msg.sender];
require(amount <= available, "amount exceeds claimable");
claimable[msg.sender] = available – amount;
rewardToken.safeTransfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}

这段代码也不自动安全。还要确认 claimable 的更新是否与总奖励池一致,代币地址是否可被权限方替换,暂停后是否仍能调用,以及转账失败是否会连同状态修改一起回滚。测试应覆盖重入接收方、零金额、边界金额和异常代币,而不是只测一次正常领取。

预言机和价格单位要落到明确约束

模型常会写出 latestRoundData(),却漏掉价格为非正数、更新时间为空或数据过期等条件。合约需要定义自己可接受的时间窗口,并处理预言机 decimals 与资产 decimals 的换算。不要把某个固定轮次检查当成所有网络的通用规则;应以当前使用的喂价接口、网络和业务允许的延迟为依据。对于清算、抵押率等敏感动作,还要评审极端价格时是否有人工暂停、限额或二次确认路径。

升级和权限需要单独审

代理合约最容易被“只看本次 diff”漏掉。每次升级都应比较编译产物中的存储布局,确认没有改变既有变量的类型、顺序或继承结构。新变量的位置、初始化函数是否只能执行一次、实现合约是否能被直接初始化,都要进发布检查单。预留 gap 只是某些继承模式下的做法,不是可以不看布局的理由。

权限同样不能只搜索 onlyOwner。列出所有能升级、铸币、改费率、暂停和转出资产的入口,确认角色由谁持有、是否采用多签或时间锁、紧急权限是否有事件记录与撤销办法。权限越大,发布前越需要独立复核。

让工具做它擅长的事

静态分析、编译器检查、fuzz 和属性测试可以持续发现已知模式,但不能证明合约没有漏洞。CI 可以要求编译、测试、Slither 或等价工具通过,并把存储布局和关键权限变更作为人工审批项。自动规则应尽量基于语义或 AST;仅凭搜索 transfer、__gap 等字符串,误报和漏报都会很多。

主网上线前,团队至少应重新演练一次:升级回滚怎么做,预言机失效时谁能暂停,用户资金卡住时如何处理。AI 生成的代码可以进入候选方案,不能绕过这套评审。

赞(0)
未经允许不得转载:171主机测评 » 智能合约评审如何识别隐性风险
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址