第 9 章 · Smart Contract 改变了什么
当规则本身变成软件,会发生什么?
- 练习的能力
- Protocol LiteracyMental Model
- 动手
- 在浏览器上打开一个已验证源码的合约,找到它的 owner 和可升级入口。
- AI Lab
- 让 AI 解释一份陌生合约的三个核心函数,再自己找出它没提到的权限风险。
一个现实问题
你租了一间房,交了三个月房租作为押金。
合同上写得清清楚楚:租期结束,房屋无损坏,押金三日内全额退还。
租期结束那天,房东说墙上有几个钉子眼,扣八百;说厨房要做一次深度清洁,扣六百;说要等下一个租客交了钱才有现金,让你再等等。
你手里那份合同一个字都没变,但执行它的是房东。
你可以去仲裁,可以去起诉。假设你都赢了,算上时间和精力,为了两千块钱,值不值?
这件事的结构比它看起来更普遍。大多数合同的问题不在于写得不够清楚,而在于执行它的是某一个有立场的人。 为了解决这个问题,社会发明了中介、托管方、公证处、法院——每一层都在收费,而且每一层本身也需要被信任。
那么问题来了:如果执行这一步也不需要人呢?
思想实验
从一台自动售货机开始。
投三块钱,按下按钮,可乐掉下来。没有店员,没有议价,没有「今天机器心情不好」。规则写在机器里,执行也在机器里。
现在把这台机器放大成一个思想实验,一步一步加条件。
第一步:规则公开可查。 任何人都能看到机器内部的接线图,确认投三块真的会出可乐,而不是出一罐空气。你不需要相信厂商,你可以自己看。
第二步:任何人都能接线。 有人把这台机器的出货口,接到了另一台机器的投币口:投六块,第一台出一罐可乐,第二台自动把可乐换成一张电影票。两台机器的主人互不相识,谁也没有谈过合作,也不需要谁批准。
第三个人看到了,又在后面接了第三台。一条谁也没有设计过的流水线长了出来。
第三步:装好之后没有钥匙。 机器焊死了,厂商自己也打不开。
这一条同时是最大的优点和最大的风险。优点是:没有人能在半夜偷偷改规则,你今天看到的接线图,十年后还是这样。风险是:如果接线图上少了一个零——本该是三块的可乐标成了三毛——这个错误也将永远存在,直到里面的可乐被搬空。
第四步:厂商留了一把后门钥匙。 为了能在出错时修好,厂商保留了一把能打开后盖的钥匙。
于是它变成了另一种东西:只要那把钥匙还在,所有关于「谁也改不了」的承诺都要加上一句「除了拿钥匙的那个人」。
请停在这里想一想:第三步和第四步,你更愿意把自己的押金放进哪一台?
你来决定
你要用这台机器托管你的两千块押金。规则很简单:三个月后自动退还给你;如果这期间房东提出了争议并且你同意,按你们协商的金额分配。
市面上有四个版本。
观察结果
四个选项指向同一个交换:
把规则交给软件,你换来的是「执行不依赖任何人的立场」,付出的是「写错了也照样执行」。
这个交换一旦成立,问题立刻从「他会不会赖账」变成了两个新问题:规则写对了吗,以及谁能改它。
先把新旧两种规则放在一起看:
| 写在纸上的合同 | 写成软件的规则 | |
|---|---|---|
| 谁来执行 | 某一方,或者第三方 | 链按规则自动执行 |
| 什么时候执行 | 需要有人发起、同意、确认 | 条件满足就执行 |
| 有立场吗 | 有 | 没有 |
| 写错了怎么办 | 可以解释、协商、走法律程序 | 照样执行 |
| 能不能被别人接上用 | 需要双方同意 | 任何人都可以直接调用 |
| 能不能被改 | 双方签字就能改 | 取决于当初留没留钥匙 |
最后一行是本章真正的分水岭,也是整章最容易被讲成口号的地方。
「不可篡改」不是一个开关,而是一条光谱。 现实中的每一份链上规则,都落在下面某个位置上:
| 位置 | 谁能改 | 你需要相信什么 |
|---|---|---|
| 完全改不了 | 没有人 | 相信当初的代码写对了 |
| 需要多人同意,且改完要等几天才生效 | 一组人,而且你能提前看见 | 相信在等待期里你来得及退出 |
| 需要多人同意,立刻生效 | 一组人 | 相信这组人不会串通、钥匙不会同时丢 |
| 一个地址随时能改 | 一个人 | 相信这个人,以及他的私钥安全 |
绝大多数人以为自己在用第一种,实际上大多数时候用的是第三种或第四种。这一章的 Lab 就是去亲眼确认一次。
建立模型
模型一:链是一台状态机
把整条链想成一个只做一件事的机器:
- 当前状态
- 一笔交易进来
- 按规则计算
- 新状态
有了这个模型,Bitcoin 和 Ethereum 的差别就能说清了:
| 规则能处理什么 | 谁来写规则 | 结果 | |
|---|---|---|---|
| Bitcoin | 主要是「这笔钱能不能花、花给谁」 | 协议本身,由社区极慎重地修改 | 可编程的钱 |
| Ethereum | 任何人上传的一段程序,可以记录和修改任意数据 | 任何人,随时,不需要许可 | 可编程的状态 |
这一句是本章的核心:
Bitcoin 是可编程的钱,Ethereum 是可编程的状态。
差别不在于谁更强,而在于规则由谁来写。Bitcoin 把规则留在协议层,所以改一次要几年;Ethereum 把规则开放给所有人,于是任何人都能在上面定义新的资产、新的市场、新的组织——也包括任何人都能部署一份有漏洞或者有恶意的规则。
模型二:可以互相接线的规则
第二个变化比第一个更深远,但它不写在任何白皮书的第一页上。
因为每一份规则都在同一条链上、都公开、都能被任何人直接调用,它们可以像积木一样互相接起来,而且不需要任何人授权。
一个借贷规则可以直接调用一个交易规则来处理清算;一个新产品可以在上线第一天就接上已有的全部流动性;一个人写的东西可以被另一个从未联系过的人组装进更大的系统。
这解释了为什么链上的金融产品能在几年内长出传统金融几十年的品类。它也解释了为什么这里的事故会传染:
你的安全,等于你所依赖的那一串规则里最弱的那一环。 你可能从没听说过其中某一环的名字。
模型三:升级权限的四个问题
拿到任何一份链上规则,问这四个问题,顺序不要变:
- 有没有人能改它? 找到那个入口,或者确认没有。
- 是谁? 一个地址、一组人、还是一次治理投票?
- 改完多久生效? 有没有等待期让用户来得及退出?
- 改了以后你能不能察觉? 有没有事件、公告、监控?
前两个问题大多数人会问,后两个问题几乎没有人问。而后两个问题决定了你在出事的时候有没有机会离场。
它叫什么
部署在链上、由链按既定规则自动执行的一段程序。
这个名字有两处误导:它既不智能,也不是法律意义上的合约。它更像一台焊死的自动售货机:条件满足就执行,不理解意图,不做判断,不接受解释。
它能做的事有一条硬边界:它只能读到链上的数据。 墙上有没有钉子眼,它不知道。所有关于现实世界的信息都要靠外部喂进来,这是第 24 章里单独一类风险。
「当前状态 + 一笔输入 = 新状态」这个循环。
这是理解任何一条链最省力的模型:链不是一个数据库,是一台所有人都能验证其每一步计算的机器。 所有人跑同样的规则、同样的输入,必然得到同样的结果——这是「不需要信任记账员」在技术上的落点。
任何一份链上规则都可以被另一份直接调用,不需要对方授权、不需要商务合作、不需要接口对接。
它是链上创新速度极快的根本原因,也是风险传染极快的根本原因。这两件事是同一件事。
判断一个协议时,值得多花十分钟画出它依赖了哪些外部规则。你会经常发现自己承担着从没听说过的东西的风险。
规则部署之后不能被修改的性质。
真正要记住的是:它是一条光谱,不是一个开关。 一份「不可篡改」的合约,如果留着一个能替换核心逻辑的入口,那么它的不可篡改只是措辞。
这也是为什么本章的 Lab 要你自己去找那个入口,而不是相信任何一份宣传材料。
通过预留的机制替换合约逻辑的能力。
它不是缺陷,是一个真实的取舍:不能升级就修不了 bug,能升级就存在被滥用的入口。 目前行业里比较成熟的做法是把它们折中——需要多人同意,并且加上一段公开的等待期。
看到「多签管理」四个字时,继续追问:几个人、都是谁、钥匙分别存在哪里、有没有时间锁。这四个问题问完,你才算真的知道谁能改它。
动手
这个 Lab 全程只读。不要在任何页面上连接钱包,也不要签任何名。 你只是在看一份公开的源码。
找一份已验证源码的合约。 在区块浏览器上打开一个你听说过的协议的合约地址,进入源码页面。
如果页面上显示的是一堆十六进制字节码而不是可读代码,说明这份合约没有公开验证源码——这件事本身就是一个重要发现,记下来,然后换一个。
找所有者。 在读取接口里找 owner、admin 这类字段,把返回的地址记下来。
然后点进那个地址:它是一个普通地址,还是一个多签?如果是多签,它需要几个人签名?这些信息通常能在这个地址的页面上看到。
找升级入口。 看这份合约是不是一个代理:页面上常见的线索包括 implementation 字段、一个指向另一份合约的地址、或者浏览器直接提示「这是一个代理合约」。
找到被代理的那份逻辑合约,记下它的地址,以及谁有权把这个地址换掉。
找时间锁。 如果所有者是一个时间锁合约,去读它的延迟参数:一次改动从提出到生效要等多久?
这是整个 Lab 最有价值的一格。 有等待期意味着你有机会在改动生效前退出,没有等待期意味着一次交易就能改变规则。
填完这张表,并给出一句判断。
| 问题 | 你查到的 |
|---|---|
| 源码有没有公开验证 | |
| 所有者是什么(单地址 / 多签 / 治理) | |
| 如果是多签,几人中几人 | |
| 有没有升级入口 | |
| 有没有时间锁,延迟多久 | |
| 改动发生时你能不能察觉 |
最后一句判断:如果这份合约的所有者明天做一次最坏的操作,你会损失什么?
如果你在某一格写下了「未找到」,不要跳过它。查不到「谁能改」这件事本身,就是一个结论。
AI Lab
把你在上一个 Lab 里找到的那份源码交给 AI:
这是一份部署在链上的合约源码。请做三件事:
1. 找出其中最核心的三个函数,逐个解释:谁可以调用、它改变了什么状态、
调用它需要满足什么前置条件。
2. 列出这份合约里所有带权限限制的函数,说明限制来自哪一行代码。
3. 列出这份合约调用的所有外部合约地址或接口。
规则:只依据我给你的源码回答。凡是源码里没有的信息,写「源码中未体现」,
不要根据同类协议的常见做法补齐。拿到回答之后,你的工作是找它漏掉的那一类东西,而不是检查它的解释对不对。
模型在这类任务上有一个稳定的行为模式:它擅长解释代码在做什么,不擅长指出代码允许谁做什么。 它会把一个只有管理员能调用的函数解释得很清楚,却不去问这个管理员是谁、这把钥匙存在哪里、能不能被一次交易换掉。
具体去找这五件事,它们是最常见的遗漏:
- 有没有一个函数能把资金转到任意地址
- 有没有一个函数能修改关键参数(费率、上限、价格来源)
- 所有者能不能被转移,转移需不需要接收方确认
- 有没有暂停功能,暂停期间用户能不能取回资产
- 合约依赖的外部数据来自哪里,谁能改它
每找到一条,就写清楚最坏情况下它会导致什么。这份清单会在第 24 章变成一套完整的风险模型。
AI 说完之后,你必须自己验证
- 它解释的每个函数,你能在源码里找到同名的那一段
- 它有没有提到访问控制:哪些函数只有特定地址能调用
- 它有没有找出可升级入口,还是把一份代理合约当成了最终逻辑
- 它说的「只有所有者能调用」,所有者到底是什么,它查了吗
- 它有没有把外部依赖列出来:这份合约调用了哪些别人的合约
- 它有没有把「已审计」当成「安全」——审计报告的时间和范围是什么
- 凡是它说「这是标准实现,没有风险」的地方,你自己再读一遍那一段
真实案例
一个把募集到的大量资金交给链上规则管理的项目,被人利用合约里的一处逻辑缺陷持续提走资金。
规则本身在正常执行——攻击者没有「黑进」任何系统,他只是按照写好的规则做了一连串操作。这正是焊死的机器最可怕的地方:错误的规则也会被忠实执行。
最终的处理方式是修改链的历史,社区为此分裂成两条链。这件事之后,行业里「代码即法律」这句口号从未被完全兑现过。
多起大额损失事件的根源不是合约有漏洞,而是可升级合约的管理密钥被拿到:钓鱼邮件、被攻破的开发机、离职员工手里的备份。
攻击者把逻辑合约替换成自己的版本,然后一次调用清空资金池。
合约审计报告在这类事故里完全帮不上忙,因为被审计的那份代码一行都没错。这提醒我们:审计覆盖的是代码,不是钥匙的保管方式。
有些协议出于理念选择完全不可升级。当社区发现一处非致命但会持续造成损失的缺陷时,唯一能做的是公开呼吁用户自行撤出,然后眼看着资金被慢慢取走。
这是不可篡改的另一面。它不是一个错误的选择,但它要求代码在部署前就是对的,而这个要求在复杂系统里极难满足。
几个协议共同依赖同一个外部价格来源。当这个来源在剧烈波动中给出了一个错误的价格时,所有依赖它的协议同时按错误价格执行了清算。
这些协议之间没有任何合作关系,它们的用户大多不知道彼此存在。
可组合性带来的连接,在赚钱时是网络效应,在出事时是传染路径。 第 24 章会把它单列为一类风险。
改一个变量
所有关于「钥匙被偷」的风险消失了,「谁能改它」这个问题也不存在了。
代价是整个行业的迭代方式要重写:部署前的验证成本极高,任何功能变化都要重新部署并迁移用户和资金,而迁移本身就是一次巨大的风险敞口。
更现实的后果是:能上线的东西会少得多,而上线的东西里 bug 造成的损失会大得多。
这几乎是本章能给出的最实用的一条建议。
它不消除升级权限,但它把「你来不及反应」变成了「你有七天可以退出」。恶意升级从一次交易变成一次所有人都看得见的公告。
代价是应急响应变慢:真的发现严重漏洞时,你也要等七天才能修。所以现实中的做法通常是:日常改动走时间锁,紧急暂停单独授权。 这时要追问的就变成了:暂停权限在谁手里,暂停期间用户能不能取钱。
部署者可以隐藏逻辑,也就能隐藏后门。
有意思的是,这不会让链本身变得不可用——所有的交易记录还是公开的,你依然能看到钱去了哪里。但你失去了事前判断的能力,只剩下事后追踪。
这正是「源码已验证」这个小标签的真实价值。它不保证代码是对的,它只保证你有机会自己去看。
链上的可组合性消失了。新协议不能直接接上已有的流动性,必须像传统行业一样一家一家谈合作、做接口对接。
好处很明显:风险传染的路径被切断了,你能清楚地知道自己依赖谁。
坏处也很明显:过去几年链上出现的大部分创新,都建立在「不需要许可就能接上去」这一条上。 关掉它,这里就变成了一个接口更难用的传统金融系统。
带走的问题
智能合约解决的是「执行合同的那个人有立场」这个问题,不是「合同写得不清楚」这个问题。
所以判断一个要上链的场景时,先问:它的争议是出在执行环节,还是出在对现实的判断上? 后者链解决不了,墙上有没有钉子眼它永远不知道。
这一章给了一个很具体的答案:因为你需要规则被执行时不依赖任何人的立场。
如果一个应用的规则由一家公司定、由这家公司执行、用户也接受这一点,那它用一台服务器就够了,上链只是增加了成本和风险。
在可组合的环境里,这一问有了新的难度:你承担的风险包括你依赖的每一环。
回答它的正确做法是把依赖画出来——这个协议调用了谁,谁又调用了谁。画不出来,说明你不知道自己在承担什么。
升级权限就是这个行业版本的「人在回路」。
完全去掉它,bug 就修不了;完全放开它,用户的资产就依赖一个人的私钥。行业目前的共识大致是:保留干预能力,但给它加上多人同意、公开等待期和可监控的痕迹。
这个取舍在第 34 章给 AI Agent 设计钱包权限时,会以几乎一模一样的形式再出现一次。
本章自测
不智能:它不理解意图,不做判断,不接受解释。条件满足就执行,写错了也执行。它更接近一台焊死的自动售货机。
不是合约:法律意义上的合约可以被解释、协商、由法院裁决。链上规则没有这些余地,它只有一种行为,就是按写好的方式运行。
还有一条硬边界值得记住:它只能读到链上的数据。 所有现实世界的信息都要靠外部喂进来,这本身是一类独立的风险。
两者都是「当前状态 + 交易 = 新状态」的机器,区别在于规则由谁来写。
Bitcoin 的规则写在协议里,主要处理「这笔钱能不能花、花给谁」,修改一次需要极长时间的社区共识。
Ethereum 把写规则的权力开放给了所有人:任何人都能部署一段程序,定义任意的资产、市场和组织,不需要许可。
代价也在这里:任何人都能部署,意味着任何人都能部署一份有漏洞的或者有恶意的规则。
因为它们是同一件事:任何人都能直接调用任何人的规则,不需要授权。
往好处说,新产品上线第一天就能接上已有的全部流动性和功能,这是链上创新速度的根本来源。
往坏处说,你的安全等于你依赖的那一串规则里最弱的一环,而这一串里可能有你从没听说过的名字。一个外部数据源出错,几个互不相干的协议会同时出事。
至少四个问题:
- 这五个人分别是谁? 是五个独立实体,还是同一个团队的五个账号?
- 钥匙存在哪里? 如果都在同一台设备或同一套流程里,5 选 3 只是写给外人看的。
- 有没有时间锁? 改动从提出到生效要等多久,有没有等待期让用户退出。
- 它能改什么? 只能改参数,还是能替换整个逻辑、把资金转走。
第三个问题最关键。有等待期,你有机会离场;没有等待期,一次交易就能改变一切。
没有标准答案。检查你的流程里有没有这几步:
- 源码有没有公开验证?没有的话,后面都不用查了。
- 有没有可升级入口?找到代理和逻辑合约的关系。
- 所有者是什么?单地址、多签,还是治理合约?
- 有没有时间锁,延迟多久?
- 它依赖了哪些外部合约和数据源?
- 有没有一个函数能把资金转到任意地址?
最后再问一句:如果这些权限的持有者明天做出最坏的操作,你会损失多少? 说不出这个数字,说明还没查完。
一句话带走
Bitcoin 是可编程的钱,Ethereum 是可编程的状态。