智能合约到底是什么,能做什么
上一篇 Gas 结尾留了一个问题:余额检查、nonce 递增、费用扣除这些规则由谁写、由谁执行?答案是智能合约——部署在链上的程序,规则写在链上,没有任何人可以单方面修改或关掉它。本文讲清「代码即规则」的准确含义(部署后字节码上链不可变)、确定性执行与全网验证如何衔接 EVM、智能合约的能力边界(能做代币/DAO/借贷,做不了链下数据与真随机),并用一个 ERC-20 转账的端到端实例把账户模型、Gas、合约执行串成一条线——这也是阶段 2 的收官。
引言:规则由谁写,由谁执行?
上一篇(Gas:世界计算机的计价系统)结尾留了一个问题:到目前为止我们讲的都是「交易的执行规则」——转账怎么计价、区块怎么装满,可这些规则本身是程序:余额检查、nonce 递增、费用扣除……它们是谁写的?普通用户能不能也往链上放一段自己的程序,让全网节点替你执行?
能。这就是 智能合约 ——「智能合约」这个名字容易让人联想到法律文书,但它的本质很朴素:一段部署在区块链上的程序代码,当满足预设条件时自动执行。没有产品经理改需求,没有运维半夜重启,没有「服务器被关停」这种事。
研究报告对它的概括只有一句:**规则即法律——规则写在链上,没有任何人可以单方面修改或关掉它。**这一篇就把这句话拆开验证:规则为什么改不了(代码即规则)、谁来执行(确定性执行 + 全网验证)、它能做什么和做不了什么(能力边界),最后用一个 ERC20 转账的端到端实例,把阶段 2 的四块拼图合上。
代码即规则:部署之后,就没有「改代码」这回事了
回忆 账户模型 里的那张全局状态表:以太坊的每个地址对应一条状态,普通账户(EOA)存余额和 nonce,合约账户多两样——代码和存储。你写给合约的 Solidity 源码,编译成 字节码 后,作为一笔特殊交易部署上链:从那一刻起,这段字节码就长在合约账户的状态里,成为全网共享的一份「规则文本」。
关键在「部署」这个词的分量:
- **部署即定稿。**上链的不是「最新版本」,而是唯一版本。传统软件里改代码是常态——发个新版本、热修个 bug;在这里,部署动作本身不可逆。
- 不可变是协议级的。不是说运维没权限改,而是没有任何人有权限改——包括作者自己。没有后台、没有管理员密钥能触碰已部署的字节码(除非合约代码里预先写了升级机制,后面单说)。
- **透明可审计。**字节码公开存在链上,任何人都可以反编译检查它在做什么——没有隐藏后门这回事。
所以「规则即法律」的准确表述是:规则以字节码形式写在链上,执行不依赖任何人的配合,修改不依赖任何人的允许——因为它压根不能修改。
确定性执行 + 全网验证:上千台机器替你跑同一段代码
规则改不了,那谁来执行?答案在 EVM 深度解析 里讲过:每个节点都在自己机器的沙盒里运行同样的程序,得出同样的状态改动。
把这套机制对准智能合约:
你调用合约(发起一笔交易)
│
▼
打包进区块的验证者:在 EVM 里逐条执行合约字节码
│
▼
其余全部节点:独立重放同一段字节码
(同样的初始状态 + 同样的交易输入)
│
├── 每个节点算出的状态改动完全一致 → 通过验证
│
└── 某节点结果不一致 → 它的状态被拒绝,等于自我驱逐
这依赖 EVM 的根本性质:EVM 是确定性的——同样输入必得同样输出。合约代码里没有 Math.random(),没有系统时间,没有任何「每次执行结果可能不一样」的东西。正因为如此,上千个互不信任的节点重放同一段代码,才可能得到同一个结果,并以此达成共识。
这也回答了一个隐蔽的问题:**「自动执行」到底是谁在执行?**不是某个服务器,而是整个网络。你调用一个合约,等于付费(上一篇的 Gas )让全网节点替你跑这段代码并共同记下结果——这就是「世界计算机」的字面含义。
能力边界:它能做什么,做不了什么
确定性、不可变、全网执行——这套组合拳能打到哪里?先看能做的:
- 代币。ERC20 定义了同质化代币的标准接口(转账、授权、查余额),ERC721 定义了唯一性资产(NFT)的标准。一段几百行的合约,就能发行全网可验证的资产。
- 借贷。DeFi 协议的核心就是合约:超额抵押、清算、利息计算全部写成代码,由合约按规则自动执行——不存在「平台单方面冻结你的借款」。
- 组织。DAO (去中心化自治组织)把治理规则写成合约:提案、投票、执行都按代码走,没有中心化管理层能绕过表决结果。
再看做不了的——合约的世界以链上为边界:
- **拿不到链下数据。**合约无法主动发起 HTTP 请求去查行情、看天气、读比赛结果——确定性执行要求所有节点得到同样输入,而链外世界对每个节点的「样子」并不保证一致。需要链下数据时,得靠 预言机 这类中间服务把数据「喂」进来。注意这不是免费的午餐:合约信任了喂价,就引入了「喂价是否可信」的新信任假设——边界从代码转移到了数据源。
- 产生不了真随机数。「确定性」和「随机」天然矛盾:同样的输入必得同样的输出,而链上所有数据(区块高度、区块哈希)对试图预测它的攻击者都是可观察、甚至可影响的。链上抽奖如果直接用区块哈希做随机源,验证者理论上可以操纵出块来左右结果。可行的路子(如 commit-reveal、门限签名)本质上都是把随机性来源搬到链外再喂回来——又一次越过边界。
一句话总结边界:合约能保证「规则执行不走样」,不能保证「输入是真的」。规则的确定性,换不来外部世界的确定性。
端到端实例:一笔 ERC-20 转账都发生了什么
概念够了,走一遍实例。场景:你用钱包把 100 USDT 转给朋友——注意,这里转的不是 ETH,是** ERC-20 代币**。
1. 发起:你的 EOA 构造一笔交易
目标地址 = USDT 合约地址(不是朋友的钱包地址!)
calldata = transfer(朋友地址, 100)
│
▼
2. 执行:EVM 在 USDT 合约账户里跑 transfer 的字节码
balances[你的地址] 1000 → 900 (余额 mapping 改写,SSTORE)
balances[朋友地址] 500 → 600 (余额 mapping 改写,SSTORE)
记录一条 Transfer(你, 朋友, 100) 事件日志
│
▼
3. 验证:其余节点重放同一段字节码
同样的初始状态 + 同样的 calldata
→ 每个节点都算出同样的两笔余额改写 → 共识达成
│
▼
4. 两端看到的结果
你:USDT 余额 -100(ETH 余额还要扣 Gas 费)
朋友:USDT 余额 +100(无需签名、无需在线,「到账」即状态改写)
三个细节值得停下来看:
**交易的目标是合约,不是收款人。**ERC-20 代币没有自己的链,只是合约存储里的一串数字。所谓「转 USDT」,实际是调用 USDT 合约的 transfer 方法,让它改写自己账本上的两个余额——这正是 账户模型 里「合约账户有代码和存储」的落地。
**「到账」是一次状态改写,不是价值搬运。**朋友不需要在线签名,余额改写经共识确认后生效——和 UTXO 模型「转走一枚硬币、收到一枚新硬币」是两种完全不同的世界观。
**Gas 按「合约调用」计价。**EOA 之间转 ETH 是协议固定定价的 21000 gas;这笔转账要执行合约字节码、做两次存储写入,gasUsed 高于该基准(量级上通常数万 gas,具体随合约实现和网络而波动)。你在为计算付费——上一篇的计价系统在这里接管。
总结:阶段 2 收官——从「理解」到「动手写」
这一篇把智能合约拆成了四块:
- 代码即规则:字节码部署上链后不可变——无人可单方面修改或关掉(升级代理是预先写进规则的例外,且自带新风险)
- 确定性执行 + 全网验证:上千个节点重放同一段代码得同样结果,衔接 EVM 篇「同样输入必得同样输出」
- 能力边界:能做代币、借贷、DAO(规则执行不走样);做不了链下数据(需预言机)与真随机数(输入的真伪不在保证范围内)
- ERC-20 转账实例:EOA 发起 → 合约改写余额 mapping + 记录事件 → 全网验证,Gas 按合约调用计价、高于 21000 基准
到这里,阶段 2 的四块拼图齐了:账户模型给了状态的形状,EVM 给了执行的引擎,Gas 给了执行的计价,智能合约给了往这台机器上放程序的能力。以太坊为什么叫「世界计算机」——现在可以完整回答:它是一台上千节点共同运行、按代码规则改写状态、执行即计价的机器。
但到目前为止,我们始终是这台计算机的用户:转账、付 Gas、等共识。下一阶段换角色——从「理解」到「动手写」:怎么用 Solidity 写出第一个合约,怎么部署、怎么测试、怎么和前端连起来。第一个课题:Solidity 基础。
相关文章:
- Gas:世界计算机的计价系统 — 前篇:本文的每笔合约调用都在它的计价体系里
- EVM 深度解析:驱动世界计算机的虚拟机 — 确定性执行的引擎细节
- 账户模型 vs UTXO:以太坊换了一种记账方式 — 合约账户的「代码 + 存储」从哪来
- UTXO 模型:比特币的会计学 — 对照:比特币为什么长不出智能合约
- 工作量证明 — 验证者打包合约交易的经济激励
- 比特币白皮书精读 — 一切的原始蓝图
- 比特币网络实际运行 — 对照:没有图灵完备性的网络如何运转