You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solidity合约越界测试的必要性及实现方法咨询

Solidity合约越界错误测试的实际价值

这类测试完全具备实际意义,甚至是合约安全测试里投入产出比极高的一类:

  • Solidity本身的类型规则存在不少容易踩坑的点:0.8版本之前默认不做整数溢出/下溢检查,越界赋值会直接截断不会抛出异常;即便是0.8之后自带溢出检查,跨合约低级调用(比如call、delegatecall)不会做参数类型校验,参数类型被误改、漏加边界判断的情况下,越界值可以直接进入业务逻辑,引发存储覆盖、权限绕过、资金计算错误等高危问题。
  • 能低成本拦住迭代过程中的低级失误:就像你提到的参数类型被误改的场景,这类问题代码评审不一定能100%覆盖,但是测试用例一旦写好,每次改完代码跑测试就能第一时间发现问题,避免问题留到主网。
  • 覆盖业务逻辑的边界场景:很多业务参数本身就有明确的取值范围(比如费率基数是10000、配置项ID上限是255),越界测试本质也是在校验业务规则的有效性,避免非法参数进入核心逻辑。
落地实现方法

核心逻辑非常简单,不需要特殊工具,用日常开发用的Foundry、Hardhat等测试框架就能实现:

  1. 先梳理所有涉及数值类型的入参、状态变量的合法取值区间,明确每个值的上下边界,比如uint8的合法范围是0~255。
  2. 针对每个边界写两类用例:一类是临界合法值(比如255),验证传入后合约可以正常执行,避免误加过严的校验影响正常功能;另一类是越界值(比如256、类型最大值、低于类型最小值的数值),验证传入后合约必须触发回滚。
  3. 针对你提到的「防范参数类型被误从uint8改成uint256」的场景,越界回滚的用例可以直接覆盖这个风险:如果后续开发真的把参数类型改成了uint256又漏加边界校验,传入256的时候合约不会触发回滚,测试用例会直接失败,第一时间暴露问题。

举个可直接复用的实现示例:
首先是待测试的业务合约:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract ValueStore {
    mapping(uint8 => uint256) public store;

    // 原设计inputVal为uint8类型,取值范围0~255
    function set(uint8 inputVal, uint256 val) external {
        store[inputVal] = val;
    }
}

对应的Foundry测试用例:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../src/ValueStore.sol";

contract ValueStoreTest is Test {
    ValueStore public app;

    function setUp() public {
        app = new ValueStore();
    }

    // 验证边界合法值可正常执行
    function test_set_validMaxVal() public {
        app.set(255, 999);
        assertEq(app.store(255), 999);
    }

    // 验证越界值必须回滚,拦截类型误改、漏加校验的问题
    function test_set_revertWhenOverUint8Range() public {
        // 传入刚好超过uint8上限的256
        vm.expectRevert();
        app.set(256, 999);

        // 传入uint256最大值,覆盖极端越界场景
        vm.expectRevert();
        app.set(type(uint256).max, 999);
    }
}

如果后续有人把set函数的inputVal参数从uint8改成uint256,又没加require(inputVal <= type(uint8).max)的边界校验,test_set_revertWhenOverUint8Range用例就会因为没有触发预期的回滚直接失败,刚好达到你要的校验效果。如果用Hardhat,逻辑完全一致,把回滚断言换成Hardhat常用的.to.be.reverted写法即可。

注意:如果你的合约用的是0.8之前的Solidity版本,因为没有默认溢出检查,越界传入参数不会自动触发回滚,这种情况一定要手动在合约里加边界校验,再配合上述用例测试,不要依赖编译器的自动检查。

内容的提问来源于stack exchange,提问作者Tarasko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:15:41