Skip to content

附录 — 速查参考(Appendix)

本附录汇总 Solidity 各版本破坏性变更、常用工具资源、关键字列表、EVM 操作码及 ERC 标准速查,供日常开发随时查阅。


附录 A:版本破坏性变更速查

升级旧合约或阅读历史代码时,以下速查表可以帮助你快速定位各版本之间的关键差异。

A.1 Solidity 0.5.0

0.5.0 是 Solidity 第一次大规模"显式化"改造,核心思想是消除隐式行为、强制开发者写出意图明确的代码

变更项说明升级注意事项
强制 address payableaddress 拆分为 addressaddress payable,只有 address payable 才能调用 transfer / send需要转账的地址必须声明为 address payable,通过 payable(addr) 转换
强制函数可见性所有函数必须显式标注 public / external / internal / private为所有未标注的函数添加可见性修饰符
强制数据位置struct、array、mapping 类型的变量必须显式声明 memory / storage / calldata函数参数和返回值也需要标注数据位置
移除 var 关键字不再允许类型推断,必须显式声明变量类型将所有 var x = ... 替换为具体类型
构造函数语法必须使用 constructor 关键字,不再允许同名函数作为构造函数旧的 function ContractName() 必须改为 constructor()
.call() 返回值变更.call() / .delegatecall() / .staticcall() 返回 (bool, bytes memory)bool success = addr.call(...) 改为 (bool success, bytes memory data) = addr.call(...)
移除 throw不再支持 throw,使用 revert() / require() / assert()全局替换 throwrevert()
移除 sha3改用 keccak256全局替换 sha3(...)keccak256(...)
移除 suicide改用 selfdestruct全局替换
移除 callcode改用 delegatecall全局替换
C99 作用域规则变量只能在声明之后且同一或嵌套作用域中使用检查变量在 for 循环等结构中的声明位置
移除 years 单位因闰年问题不再支持 years 时间单位使用具体的秒数计算替代
移除空 struct不再允许声明空的 struct确保 struct 至少包含一个成员
pure / view 使用 STATICCALL纯函数和视图函数在 Byzantium 及之后使用 STATICCALL 调用EVM 层面禁止状态变更

A.2 Solidity 0.6.0

0.6.0 引入了面向对象的核心机制,使继承体系更加清晰,同时增强了错误处理能力。

变更项说明升级注意事项
virtual / override 关键字可被重写的函数必须标记 virtual,重写函数必须标记 override为所有接口/可重写函数加 virtual,重写时加 override(Base1, Base2)
abstract 合约未完全实现的合约必须标记为 abstract无法用 new 实例化 abstract 合约
try / catch新增对外部调用失败的结构化捕获可替代底层 .call() 返回值检查,代码更可读
数组 length 只读存储数组不再能通过赋值 .length 调整大小使用 push() / push(value) / pop() 替代 array.length = n
push(value) 不返回长度push(value) 返回值变为 void如需新长度,调用后通过 array.length 获取
receive / fallback 拆分匿名 fallback 函数拆分为 receive() external payablefallback() externalreceive 处理纯 ETH 转账(calldata 为空),fallback 处理无匹配函数的调用
禁止状态变量遮蔽派生合约不能声明与基合约同名的状态变量重命名冲突的状态变量
payable(x) 转换addressaddress payable 可通过 payable(x) 转换替代 0.5.0 中 address(uint160(x)) 的写法
文件级 struct/enumstruct 和 enum 可在合约外部(文件级)声明提升代码组织灵活性
数组切片calldata 数组支持切片操作,如 msg.data[4:]仅限 calldata 数组
内联汇编变量名限制变量名不能以 _slot / _offset 结尾使用 .slot / .offset 访问存储指针
Yul 优化器默认启用使用 --optimize 时 Yul 优化器默认启用可通过 --no-optimize-yul 禁用

A.3 Solidity 0.7.0

0.7.0 是一次"清理"版本,移除了大量历史遗留语法,使语言更加简洁。

变更项说明升级注意事项
新的函数调用选项语法x.f{gas: 10000, value: 2 ether}(arg) 替代旧的 x.f.gas(10000).value(2 ether)(arg)必须使用花括号语法
now 弃用全局变量 now 改为 block.timestamp全局替换 nowblock.timestamp
移除 finney / szabo不再支持这两个很少使用的面额单位使用 1e15(finney)或 1e12(szabo)或直接使用 gwei
gwei 成为关键字gwei 不能再用作标识符重命名与 gwei 冲突的变量名
构造函数不再需要可见性移除 public / internal 构造函数,使用 abstract 代替删除构造函数的 public/internal 修饰符
移除库函数 virtual库函数不能标记为 virtual,因为库不可被继承删除库函数上的 virtual
using A for B 不再继承必须在每个需要使用的合约中重复声明在所有派生合约中重新声明 using 语句
移位运算禁止有符号类型移位量必须为无符号整数x >> y 中的 y 转为 uint
含 mapping 的结构体限制包含 mapping 的 struct/array 只能在 storage 中使用不能在 memory 中复制包含 mapping 的结构体
字符串字面量限制字符串只能包含可打印 ASCII 字符非 ASCII 内容使用 unicode"..." 前缀
内联汇编 .slot / .offset存储变量访问从 x_slot 改为 x.slot全局替换后缀语法
同名事件禁止同一继承层级中禁止同名同参数事件重命名冲突的事件

A.4 Solidity 0.8.0

0.8.0 是最重大的安全升级,默认算术溢出检查极大降低了整数溢出漏洞的风险。

变更项说明升级注意事项
默认算术溢出检查加减乘除默认在溢出时 revert,不再静默回绕性能敏感处使用 unchecked { ... } 恢复旧行为;可移除 SafeMath 库
ABI coder v2 默认启用不再需要 pragma experimental ABIEncoderV2如需旧行为使用 pragma abicoder v1;
指数运算右结合a**b**c 解析为 a**(b**c) 而非 (a**b)**c检查连续指数运算的逻辑
Panic(uint256) 错误码assert 失败、除零等内部错误使用 revert Panic(code) 代替 invalid 操作码节省 gas,require 失败仍使用 Error(string)
移除 byte 类型别名byte 不再是 bytes1 的别名全局替换 bytebytes1
msg.sender / tx.origin 类型变更类型从 address payable 变为 address需要转账时使用 payable(msg.sender)
显式类型转换限制一次转换只允许改变 sign、width、type-category 中的一项需要多步转换,如 address(uint160(uint256))
address 字面量类型变更地址字面量类型为 address(非 address payable使用 payable(0x...) 获取 address payable
函数调用选项不可重复c.f{gas: 10000}{value: 1}()c.f{gas: 10000, value: 1}()合并函数调用选项
移除 log0 ~ log4全局函数移除,需通过内联汇编实现使用 assembly { log0(...) } 替代
枚举最多 256 成员ABI 底层类型固定为 uint8超过 256 成员的枚举需拆分
chainid 变为 view内联汇编中 chainid 不再是 pure标记为 view 而非 pure
禁止对无符号整数取反-uint 不再合法使用 type(uint256).max - x + 1 替代

附录 B:外部学习资源与工具

B.1 官方资源

资源链接推荐理由
Solidity 官方文档https://docs.soliditylang.org/最权威的语言参考,版本更新及时
Remix IDEhttps://remix.ethereum.org/零配置浏览器 IDE,适合快速原型和学习
Ethereum 开发者门户https://ethereum.org/en/developers/以太坊生态全景导航,涵盖教程和工具
Ethereum StackExchangehttps://ethereum.stackexchange.com/技术问答社区,搜索常见问题首选
Solidity by Examplehttps://solidity-by-example.org/简洁的代码示例,按主题分类
Solidity 语言论坛https://forum.soliditylang.org/参与语言设计讨论的官方渠道
awesome-solidityhttps://github.com/bkrem/awesome-solidity社区维护的资源合集

B.2 开发框架

框架语言说明推荐场景
HardhatJavaScript / TypeScript插件生态丰富,调试体验好,社区活跃JS/TS 开发者首选
FoundryRust (CLI) / Solidity (测试)编译速度极快,用 Solidity 写测试,内置模糊测试高性能需求、Solidity 原生测试
TruffleJavaScriptConsensys 已于 2023 年 9 月宣布停止维护⚠️ 不推荐新项目使用,现有项目建议迁移至 Hardhat

建议:新项目优先选择 Hardhat(前端/全栈团队)或 Foundry(合约密集型项目)。

B.3 前端交互库

说明推荐场景
ethers.js轻量级,API 设计清晰,文档完善大多数 DApp 项目推荐
web3.js最早的以太坊 JS 库,社区历史资源丰富遗留项目维护
viemTypeScript-first,类型安全,与 wagmi 深度集成TypeScript 新项目推荐

B.4 测试与安全工具

工具类型说明
Slither静态分析Trail of Bits 出品,检测常见漏洞模式,速度快,集成 CI 方便
Mythril符号执行ConsenSys 出品,深度分析执行路径,发现复杂漏洞
Echidna模糊测试 (Fuzzing)基于属性的测试,自动生成输入探索边界条件
Aderyn静态分析Cyfrin 出品,支持 Hardhat 和 Foundry 项目
SolhintLinter代码风格与安全规则检查
Sourcify合约验证去中心化的合约源码验证服务

附录 C:Solidity 关键字完整列表

类型关键字

关键字说明
bool布尔类型
int / int8 ~ int256有符号整数(8 位到 256 位,步长 8)
uint / uint8 ~ uint256无符号整数
address地址类型(20 字节)
address payable可接收 ETH 的地址类型
bytes1 ~ bytes32固定长度字节数组
bytes动态长度字节数组
string动态长度 UTF-8 字符串
mapping映射类型
struct自定义结构体
enum枚举类型

可见性关键字

关键字说明
public外部和内部均可访问
private仅当前合约可访问
internal当前合约及派生合约可访问
external仅外部调用可访问

状态可变性关键字

关键字说明
pure不读取也不修改状态
view读取但不修改状态
payable可接收 ETH
constant编译时常量(用于状态变量)
immutable部署时赋值后不可变

控制流关键字

关键字说明
if / else条件分支
for计数循环
while条件循环
dodo-while 循环
break跳出循环
continue跳到下一轮循环
return返回值
try / catch外部调用异常捕获(≥ 0.6.0)

合约相关关键字

关键字说明
contract声明合约
interface声明接口
library声明库
abstract声明抽象合约(≥ 0.6.0)
constructor构造函数
function声明函数
modifier声明函数修饰器
event声明事件
error声明自定义错误(≥ 0.8.4)
using ... for附加库函数到类型
is继承声明
virtual标记可被重写(≥ 0.6.0)
override标记重写(≥ 0.6.0)
new创建合约实例
delete重置变量为默认值
type用户定义值类型(≥ 0.8.8)

特殊关键字与保留字

关键字说明
memory数据位置:内存
storage数据位置:持久存储
calldata数据位置:调用数据(只读)
transient瞬态存储(EIP-1153)
indexed事件参数索引标记
anonymous匿名事件
emit触发事件
revert回滚交易
require条件检查(失败则回滚)
assert内部断言
receive接收 ETH 的特殊函数(≥ 0.6.0)
fallback回退函数(≥ 0.6.0)
selfdestruct销毁合约
this当前合约实例
super父合约引用
unchecked禁用溢出检查块(≥ 0.8.0)
assembly内联汇编块
pragma编译指示
import导入声明
wei / gwei / etherETH 面额单位
seconds / minutes / hours / days / weeks时间单位

附录 D:常用 EVM 操作码速查

以下列出开发中最常遇到的 EVM 操作码,完整列表参见 evm.codes

栈操作

操作码助记符Gas说明
0x50POP2弹出栈顶元素
0x60~0x7FPUSH1~PUSH323压入 1~32 字节的值
0x80~0x8FDUP1~DUP163复制栈中第 1~16 个元素到栈顶
0x90~0x9FSWAP1~SWAP163交换栈顶与第 2~17 个元素

算术运算

操作码助记符Gas说明
0x01ADD3加法
0x02MUL5乘法
0x03SUB3减法
0x04DIV5无符号除法
0x05SDIV5有符号除法
0x06MOD5取模
0x0AEXP10+指数运算
0x0BSIGNEXTEND5符号扩展

比较与位运算

操作码助记符Gas说明
0x10LT3小于比较
0x11GT3大于比较
0x14EQ3相等比较
0x15ISZERO3是否为零
0x16AND3按位与
0x17OR3按位或
0x18XOR3按位异或
0x19NOT3按位取反
0x1ABYTE3取指定字节
0x1BSHL3左移
0x1CSHR3逻辑右移
0x1DSAR3算术右移

内存操作

操作码助记符Gas说明
0x51MLOAD3+从内存加载 32 字节
0x52MSTORE3+向内存写入 32 字节
0x53MSTORE83+向内存写入 1 字节
0x59MSIZE2当前已分配内存大小

存储操作

操作码助记符Gas说明
0x54SLOAD2100 (cold) / 100 (warm)从 storage 加载
0x55SSTORE2900~20000向 storage 写入
0x5CTLOAD100从瞬态存储加载(EIP-1153)
0x5DTSTORE100向瞬态存储写入(EIP-1153)

流程控制

操作码助记符Gas说明
0x56JUMP8无条件跳转
0x57JUMPI10条件跳转
0x5BJUMPDEST1标记有效跳转目标
0x00STOP0停止执行
0xFDREVERT0+回滚并返回数据
0xFEINVALID所有 gas非法指令(消耗所有 gas)
0xF3RETURN0+返回数据并停止

环境信息

操作码助记符Gas说明
0x30ADDRESS2当前合约地址
0x31BALANCE2600 (cold) / 100 (warm)查询地址余额
0x32ORIGIN2交易发起者(tx.origin
0x33CALLER2调用者(msg.sender
0x34CALLVALUE2附带的 ETH(msg.value
0x35CALLDATALOAD3加载 calldata
0x36CALLDATASIZE2calldata 长度
0x37CALLDATACOPY3+复制 calldata 到内存
0x3AGASPRICE2当前 gas 价格
0x5AGAS2剩余 gas

区块信息

操作码助记符Gas说明
0x40BLOCKHASH20获取区块哈希
0x41COINBASE2矿工/验证者地址
0x42TIMESTAMP2区块时间戳
0x43NUMBER2区块号
0x44PREVRANDAO2前一区块的随机值(原 DIFFICULTY
0x45GASLIMIT2区块 gas 上限
0x46CHAINID2链 ID
0x48BASEFEE2基础费(EIP-1559)

调用相关

操作码助记符Gas说明
0xF1CALL2600+调用外部合约
0xF4DELEGATECALL2600+委托调用(使用调用者的上下文)
0xFASTATICCALL2600+静态调用(禁止状态修改)
0xF0CREATE32000+创建合约
0xF5CREATE232000+用盐值创建合约(地址可预测)

日志操作

操作码助记符Gas说明
0xA0LOG0375+无主题日志
0xA1LOG1750+1 个主题日志
0xA2LOG21125+2 个主题日志
0xA3LOG31500+3 个主题日志
0xA4LOG41875+4 个主题日志

哈希

操作码助记符Gas说明
0x20KECCAK25630+Keccak-256 哈希

附录 E:ERC 标准速查

标准名称用途核心函数/接口
ERC-20同质化代币最基础的代币标准,适用于货币、积分等可互换资产totalSupply() balanceOf(address) transfer(address,uint256) approve(address,uint256) transferFrom(address,address,uint256) allowance(address,address)
ERC-721非同质化代币 (NFT)每个代币唯一,适用于数字艺术、游戏物品、身份凭证balanceOf(address) ownerOf(uint256) safeTransferFrom(...) approve(address,uint256) setApprovalForAll(address,bool) getApproved(uint256)
ERC-1155多代币标准单合约管理多种代币类型(同质化 + 非同质化),节省部署成本balanceOf(address,uint256) balanceOfBatch(...) safeTransferFrom(...) safeBatchTransferFrom(...) setApprovalForAll(address,bool)
ERC-4626代币化金库DeFi 收益聚合器标准接口,统一存取款操作deposit(uint256,address) withdraw(uint256,address,address) mint(uint256,address) redeem(uint256,address,address) totalAssets() convertToShares(uint256) convertToAssets(uint256)
ERC-2612Permit(链下授权)通过签名实现无 gas 授权,消除 approve + transferFrom 两步交互permit(address,address,uint256,uint256,uint8,bytes32,bytes32) nonces(address) DOMAIN_SEPARATOR()
ERC-165接口检测标准化查询合约是否实现某接口supportsInterface(bytes4) — 返回 true 表示支持该接口

常用 ERC 标准关系图

ERC-165 (接口检测)
  ├── ERC-721 (必须实现 ERC-165)
  │     └── ERC-721Enumerable / ERC-721Metadata (可选扩展)
  ├── ERC-1155 (必须实现 ERC-165)
  └── ERC-4626 (继承 ERC-20)

ERC-20
  ├── ERC-4626 (代币化金库,扩展 ERC-20)
  └── ERC-2612 (Permit,扩展 ERC-20)

附录 F:社区与贡献

Solidity 是一个开源项目,欢迎社区参与贡献。以下是参与方式的简要指南。

参与方式

类型说明入口
报告问题提交 Bug 报告时请附上 Solidity 版本、源代码、操作系统和复现步骤GitHub Issues
修复 Buggood first issue 标签开始,适合新贡献者Good First Issues
改进文档修正错误、补充说明、改进示例Solidity Docs Repo
翻译文档将文档翻译为更多语言solidity-docs
语言设计提出新特性或改进建议Solidity Forum
回答问题在社区帮助其他开发者Ethereum StackExchange

提交 Pull Request 流程

  1. Fork develop 分支
  2. 在你的分支上进行修改
  3. commit message 描述为什么改(不仅仅是改了什么)
  4. 需要同步上游时使用 git rebase(不要用 git merge
  5. 新功能必须在 test/ 下添加测试用例
  6. 更新 Changelog.md
  7. 遵循项目的 Coding Style
  8. 提交前检查 Review Checklist

团队会议

Solidity 团队每周三 15:00 CET/CEST 举行公开电话会议,可通过 Jitsi 参加。任何人都可以在议程中添加讨论话题。


系列导航返回第一章 — 区块链与智能合约基础