教程区块链区块链技术ch1212.6 形式化验证:用数学证明合约无懈可击

本页目录

graph LR
    Spec[规范定义<br/>合约行为声明] --> Model[数学模型<br/>状态机/霍尔逻辑]
    Model --> Tool[验证工具<br/>TLA+/Coq/SMT]
    Tool --> Proof[形式化证明<br/>自动/半自动推导]
    Proof --> Correct{满足规范?}
    Correct -->|是| Safe[可信合约<br/>部署上链]
    Correct -->|否| Bug[发现属性违反<br/>修复后重证]
    Bug --> Spec
    style Tool fill:#e3f2fd
    style Safe fill:#c8e6c9
    style Bug fill:#ffcdd2

测试只能证明 bug 存在,不能证明其不存在。形式化验证(Formal Verification)用数学声明和证明推导,在编译之前就证明合约满足其规范。


12.6.1 "指定即认知":规范的三种层次

规范层次形式工具案例
类型系统类型签名Solidity 0.8+uint256 防溢出
断言与不变式require / assert所有编译器运行时检查
形式化规范一阶逻辑 / 时序逻辑Coq / Lean / TLA+数学证明

时序逻辑(TLA+)的状态机视角

text
合约核心 = 状态机 (S, S₀, Next, Invariant)

S   = 所有可能状态的集合(合约变量赋值)
S₀  = 所有可能初始状态
Next ⊆ S × S  合法转移关系

Invariant ⊆ S  必须在所有可达状态中被满足的谓词

Safety 定理: ∀ s ∈ Reachable(S₀, Next), Invariant(s) = true

12.6.2 Solidity 形式化工具入门

12.6.2.1 符号执行(Mythril)

SMT 求解器 约束所有路径,查找偏离规范的路径。

12.6.2.2 首个形式化验证工具:Coq + Serokell

text
Coq 逻辑:
Theorem no_reentrancy:
  forall s s' old_bal caller target amount,
    old_bal = s.balances[caller] /\
    s.balances[contract] >= amount /\
    step(s, withdraw(caller, amount), s') ->
    s'.balances[caller] = 0.

Proof.
  intros. unfold step, withdraw.
  apply state_before_transfer.  // 核心:先扣减再转出的不变式
  contradiction.  // 任何重入路径都导致矛盾
Qed.

12.6.2.3 Certora:工业级验证框架

Certora 使用 CTL(计算树逻辑) 表达规范:

cvl
// 指定 ERC20 Transfer 语义
rule transfer_invariant {
    env e;
    address from; address to; uint amount;
    
    require e.msg.sender == from;
    mathint fromBal_before = balanceOf(e, from);
    mathint toBal_before = balanceOf(e, to);
    
    transfer(e, to, amount);
    
    mathint fromBal_after = balanceOf(e, from);
    mathint toBal_after = balanceOf(e, to);
    
    // 不变式:from 的余额减少 amount,to 的余额增加 amount
    assert from == to 
        => fromBal_after == fromBal_before,
        "transfer:self-transfer balance shouldn't change";
    assert from != to 
        => toBal_after == toBal_before + amount 
        && fromBal_after == fromBal_before - amount,
        "transfer:balance conservation";
}

12.6.3 验证的范围与局限

可验证难/不可验证
余额守恒(转账前后总量不变)外部预言机行为
调用顺序约束(先 A 后 B)经济均衡(代币价格稳定)
溢出不可能性51% 攻击概率
权限不变式(只有 owner 可暂停)矿工/验证者行为

形式化验证假设:

  • EVM 语义正确
  • 字节码正确对应源码
  • 外部依赖(预言机)按规范行为

12.6.4 形式化验证在项目中的实践

项目验证工具验证范围发现漏洞?
OpenZeppelinCertoraERC20/ERC721 核心 invariant未发现新 bug
Uniswap V2TLA+储备关系不变式K = X*Y
CompoundCertora清算不变式、借贷关系发现边界条件
MakerDAOK framework整系统形式化规约发现装饰用

> ← 上一节:12.5 可升级合约 | 前往 → ch12-summary(本章总结) |*

评论

0

评论加载中…

发表评论

0/2000