Vyper
0.4.xEVM 系
为可审计性而生的 Python 风格语言,刻意砍掉了继承与修饰器
Vyper 的设计哲学是「让审计变简单」:没有继承、没有函数重载、没有修饰器、没有内联汇编,所有状态的读写边界都要显式声明。代价是表达能力弱、生态与工具链不如 Solidity 丰富,适合逻辑简单、安全性优先的合约(金库、Curve 类 AMM、简单代币)。
3 个语法章节5 段可复制代码含在线练习
从 Solidity 视角看差异
如果已经会 Solidity,这张表比从头读语法快得多。
| 差异点 | 说明 |
|---|---|
| 缩进与注解 | 用 Python 式缩进代替大括号;类型用 @decorator 声明(@external / @view / @payable)。 |
| 没有继承与修饰器 | 用模块(import)与接口组合代替继承;重入保护有内置的 @nonreentrant("lock")。 |
| 溢出默认检查 | 所有算术默认检查溢出,不需要 unchecked 块;想省 Gas 要用 unsafe_add 显式标注。 |
| 存储声明 | 状态变量必须在模块级用 name: public(uint256) 声明,类型在后、名字在前。 |
1
模块级声明与函数
1 段代码状态变量在文件顶部声明,函数用装饰器标注外部可见性与可变性。
- @external 是唯一对外暴露的函数类型,@internal 只能内部调用
- 返回值用 -> 声明,多返回值写成 -> (uint256, bool)
- 常量用 constant(类型),不可变值用 immutable(类型) 在部署时确定
- 没有构造函数关键字,用 @deploy def __init__() 代替
最小可部署合约
最小可部署合约Vyper
@view 与 @external 可叠加;顺序不影响语义,但社区惯例是 @view 在前。
2
映射、数组与结构体
2 段代码HashMap 是唯一的内置映射,动态数组必须有长度上限。
- HashMap[K, V] 不可遍历,必须自己维护索引数组或计数
- DynArray[T, N] 需要在类型里写死最大长度,长度随合约一起上链
- struct 不自动提供公开 getter,要么手写 @view 函数,要么用 public 变量
- 不存在 mapping 的嵌套糖:HashMap[address, HashMap[address, uint256]] 要显式写出来
HashMap 与 DynArray
HashMap 与 DynArrayVyper
结构体与接口调用
结构体与接口调用Vyper
接口里每个函数都必须写可变性标注(view / nonpayable / payable),否则编译不过。
3
安全特性
2 段代码Vyper 把重入锁、边界检查都做成了语言级能力,这是它最大的卖点。
- @nonreentrant("key") 是内置重入锁,必须在所有相关函数上用同一个 key
- raw_call 是唯一的外部调用方式之一,可以控制 revert_on_failure 与返回数据长度上限
- assert 与 raise 都会 revert;raise 可带自定义错误对象,Gas 更省
- send / raw_call 转账不会自动检查成功,必须看返回值
内置重入锁与安全转账
内置重入锁与安全转账Vyper
自定义错误与溢出控制
自定义错误与溢出控制Vyper
本章练习
这一段要让你看懂:Vyper 不是「另一种语法的 Solidity」:它砍掉了继承、修饰器、重载与内联汇编,把可变性与重入保护做成语言级装饰器,代价是表达能力更弱。迁移前先确认目标合约是否真的需要这些能力。
▶
试一试 · Solidity ↔ Vyper 写法对照翻译
可直接改代码 · 在浏览器沙箱里真跑playground.jsJavaScript
运行环境:iframe 沙箱(无 cookie 权限)。只支持纯 JS 片段,不支持 import / require;需要模块请用下方的完整示例复制到项目里。
检查点(跑完后逐条核对)
- uint256 public total; 被翻译成 total: public(uint256)
- mapping 被翻译成 HashMap[address, uint256]
- require(...) 被翻译成 assert(注意 Vyper 的参数字符串反了位置)
- 输出末尾列出三处必须手工重写的差异