原文作者:PaperMoon团队
引言
Polkadot 的智能合约平台支持两种不同的虚拟机执行后端:
• Rust Ethereum Virtual Machine(REVM)
• 基于 RISC-V 架构的 PVM
这两种后端在合约部署方式与优化策略上存在明显差异。
REVM 提供了与以太坊高度兼容的单步部署体验,几乎无需修改即可迁移现有合约;而基于 RISC-V 架构设计的 PVM,则采用了更加结构化的两阶段部署模型,以适配其底层执行架构。
理解这两种后端在部署机制上的差异,有助于开发者在不同执行环境中顺利部署和运行智能合约。
REVM 部署机制
REVM 后端支持无需修改即可部署以太坊合约,实现真正意义上的无缝迁移。
在 REVM 环境下,合约的部署流程与以太坊保持完全一致,包括:
• 合约字节码在单笔交易中打包并部署
• 工厂合约可在运行时动态创建新合约
• 支持运行时代码生成,包括内联汇编(inline assembly)
• Hardhat、Foundry、Remix 等主流工具可直接使用,无需适配
因此,对于以太坊开发者而言,在 REVM 上部署合约几乎没有额外学习成本。
PVM 部署机制
PVM 采用了与 EVM 完全不同的部署模型,其设计针对 RISC-V 架构进行了深度优化。
对于简单合约部署场景,PVM 的使用体验同样顺畅;但在涉及工厂模式等高级部署结构时,则需要理解其两阶段部署流程。
标准合约部署
对于大多数常见使用场景,例如:
• ERC-20 代币
• NFT 合集
• 独立业务合约
PVM 的部署过程对开发者是透明的,不需要额外操作。
在使用标准 Solidity 编程模式时,Revive 编译器会自动处理底层部署流程,开发者无需关心内部细节。
两阶段部署模型
PVM 将合约部署拆分为两个相互独立的阶段:
1. 代码上传(Code Upload)
合约字节码必须首先上传至链上,并进行存储。
该阶段只负责保存代码,不会创建具体合约实例。
2. 合约实例化(Contract Instantiation)
随后,通过引用已上传代码的哈希值,在链上创建具体合约实例。
每个实例都基于同一份已存储代码生成。
架构差异说明
这种模式与 EVM 将代码与实例打包在同一笔交易中的方式明显不同,并对部分部署模式产生重要影响。
工厂模式的适配要求
在 EVM 中,常见的工厂模式允许合约在运行时动态创建其他合约。例如:
EVM 工厂示例:
// 在 REVM 上可直接运行,在 PVM 上需调整
contract Factory {
function createToken() public returns (address) {
// EVM 中可直接内嵌字节码
return address(new Token());
}
}
该模式在 REVM 中可以直接使用,但在 PVM 中需要进行适配。
PVM 的部署要求
在 PVM 环境下,工厂合约需要满足以下条件:
1. 预先上传依赖合约
所有可能在运行时被实例化的合约,必须提前上传到链上。
2. 使用代码哈希引用
工厂合约通过已上传代码的哈希值进行实例化,而不是直接嵌入字节码。
3. 禁止运行时代码生成
由于 PVM 采用 RISC-V 格式,不支持动态生成字节码。
工厂合约迁移策略
当从以太坊迁移工厂合约到 PVM 时,建议按照以下流程进行调整:
1. 识别所有依赖合约
明确哪些合约会在运行时被动态创建。
2. 优先部署依赖项
在部署工厂合约前,先将所有依赖合约上传到链上。
3. 使用链上构造函数
充分利用 PVM 提供的链上构造函数功能,实现灵活初始化逻辑。
4. 避免使用汇编创建合约
不要在汇编代码中使用 create 或 create2 操作码进行手动部署。
架构层面的限制
由于 PVM 的部署模型设计,其在部分低层级模式上存在明确限制:
1. EXTCODECOPY 限制
使用 EXTCODECOPY 在运行时读取或操作代码的合约可能出现兼容问题。
2. 运行时代码修改受限
动态构造、修改合约字节码的模式不被支持。
3. 汇编工厂模式限制
使用 YUL 汇编动态生成代码的工厂合约,可能会触发 CodeNotFound 错误。
实际影响说明
上述模式通常需要深入使用汇编才能实现,在标准 Solidity 开发中较为少见,因此对大多数开发者影响较小。
链上构造函数(On-Chain Constructors)
PVM 提供了链上构造函数机制,作为运行时代码生成的替代方案,其优势包括:
• 支持在不生成新字节码的前提下创建实例
• 提供灵活的初始化能力
• 保持代码上传与实例创建的分离
• 提供更可预测的部署成本
该机制在保证安全性的同时,提高了部署模型的可维护性。
Gas 预估与实际消耗差异
无论是 REVM 还是 PVM,在部署合约时,都可能出现 Gas 预估值与实际消耗存在较大差异的情况。
常见表现为:
• 预估值明显高于真实消耗
• 实际消耗通常仅为预估值的约 30%
产生原因
该现象属于正常行为,主要原因在于:
• 预执行阶段无法精确区分计算权重与存储押金
• 系统采用保守估算策略避免失败
• 合约部署涉及大量代码存储押金
因此,系统往往会显著高估成本。
部署模式对比
| 特性 | REVM 后端 | PVM 后端 |
|---|---|---|
| 部署模型 | 单步打包部署 | 两阶段部署 |
| 工厂模式 | 支持直接创建 | 需预上传代码 |
| 代码组织 | 交易中携带字节码 | 使用代码哈希引用 |
| 运行时代码生成 | 完全支持 | 不支持 |
| 简单合约 | 无需修改 | 无需修改 |
| 汇编部署 | 支持 | 不推荐,受限 |
总结
REVM 与 PVM 均可高效支持智能合约部署,但侧重点不同:
• REVM 提供即插即用式的以太坊兼容体验
• PVM 提供结构化、可预测的两阶段部署体系
对于大多数场景(如代币合约、应用合约部署),两种后端都可无缝使用。
对于涉及工厂模式等高级架构的项目,在 PVM 上可能需要进行一定适配,但只要提前规划部署流程,迁移成本通常较低。
整体而言,该双后端设计使 Polkadot 能够同时满足:
• 以太坊生态迁移需求
• 高性能架构长期演进需求
为开发者提供了兼顾兼容性与可扩展性的部署基础。
原文链接:https://docs.polkadot.com/smart-contracts/for-eth-devs/contract-deployment/