Cardano 的智能合约不自由, 但这正是它比以太坊安全的原因
研究 Cardano 时, 听到最多的开发者吐槽是: 在 Cardano 上写合约"束手束脚"。以太坊上随手就能"改一下余额", 到了 Cardano 得绕一大圈, 像是戴着镣铐跳舞。
我以前也觉得这是缺点。后来把账本模型吃透才发现: 这种"不自由", 恰恰是 Cardano 比以太坊安全的原因。这篇用最土的话讲清楚。
两种记账方式: 银行账本 vs 现金
以太坊和 Cardano 的差别, 本质是两种记账方式:
flowchart TB
subgraph 账户模型[以太坊: 银行账本]
A1[Alice 余额 100] --> B1[交易扣 10]
B1 --> C1[Alice 余额 90]
end
subgraph UTXO[Cardano: 现金]
A2[旧钞票 #1 100 ADA] --> B2[交易花掉它]
B2 --> C2[新钞票 #2 90 ADA<br/>新钞票 #3 10 ADA]
end- 账户模型(以太坊): 像银行柜台。每个人都有个余额变量, 交易就是"在账本上改数字"。改完这一笔, 全链都看到了这个新数字。
- UTXO 模型(Cardano): 像现金。不存在"余额", 只有一张张"钞票"(未花费输出)。要付款, 只能把手上某张钞票花掉, 找零, 再重新给出一批新钞票。
关键区别: 银行账本是共享的、可变的; 现金是彼此独立的、花出去就没了。
eUTXO: 给现金贴上"使用条件"
比特币就是纯 UTXO。Cardano 在此基础上加了脚本能力, 叫 eUTXO(Extended UTXO, 扩展 UTXO)。简单说, 每一张"钞票"可以附带一个使用条件:
flowchart TB
A[一张被锁的钞票<br/>含 datum 数据 + 锁定脚本] --> B[某笔交易想花它]
B --> C[脚本检查:<br/>输入的数据和证明<br/>合不合条件]
C -->|通过| D[按脚本规则<br/>造出新钞票]
C -->|拒绝| E[交易无效]比如想做一个限时存款: 这张钞票上写着"只有满 30 天, 或者有钥匙的人, 才能花它"。脚本就是这段规则, 每次想花这张钞票, 都得让脚本验一遍。
这套设计来自一篇 2020 年发表在金融密码学会议上的论文《The Extended UTXO Model》, 它回答的问题正是: 能不能既保留 UTXO 的简单语义, 又写出够用的智能合约。
为什么"不自由"反而安全
现在讲重点: 为什么这个模型从设计上就比账户模型安全。
没有共享状态, 重入攻击无处下手
以太坊最经典的漏洞是重入攻击, 2016 年 TheDAO 事件就是它, 几百万枚 ETH 被抽走。原理是这样:
flowchart TB
subgraph EVM[以太坊: 重入发生的土壤]
E1[合约 A 先转钱给 B] --> E2[B 的代码回调 A]
E2 --> E3[A 的余额还没更新<br/>于是再转一次]
end
subgraph Cardano[Cardano: 没有中间态]
C1[输入是一张确定的旧钞票] --> C2[脚本一次性验完]
C2 --> C3[没有任何<br/>可回调的中间状态]
end重入能成立, 靠的是账户模型里"先改状态再调用外部, 或者先调用再改状态"的时序漏洞——执行到一半, 状态还停在旧值, 攻击者钻空子。
Cardano 没有这个土壤: 一笔交易花哪些旧输出、产生哪些新输出, 是一开始就写死的。脚本验证是纯函数, 一次性跑完, 不存在"执行到一半等着被回调"的窗口。想重入, 也没有可重入的东西。
手续费和结果都是确定的
账户模型里, gas 费随网络拥堵波动, 交易失败也可能白花手续费。Cardano 因为每张钞票、每笔输入输出都是确定的, 手续费在交易创建那一刻就算死, 不会变; 交易能不能成功, 提交前就能预判。对普通用户, 这体验差别很实在。
不自由的代价
当然, 硬币有另一面。UTXO 模型表达力受限: 想写一个需要大量共享状态的应用(比如复杂交易所的撮合), 得用"状态机 + 锁仓脚本"的套路绕, 开发成本高, 生态里早期 DeFi 也因此偏少。
这就是 Cardano 的取舍: 宁可用起来麻烦, 也要让漏洞从设计上不存在。它没有承诺"什么都能写", 而是承诺"写出来的东西, 很难被经典方式攻破"。
这个取舍在长期会带来什么? 如果一套账本模型能让一整类经典攻击从设计上不存在, 那么链上沉淀的协议价值(锁仓、合约、资产)就少了一整条被批量攻破的路径。DeFi 要能长期存在, 靠的不只是跑得快, 更是"出了事能兜得住"。Cardano 选择的, 是后者。