跳转到内容

以太坊到 Aptos 迁移指南

Aptos 旨在帮助您快速原型开发并扩展安全的生产级应用。它结合了一个快速、低成本且稳定的区块链层,以及 Move 语言的编译时安全特性,可以在部署前捕获潜在漏洞利用(exploit)。此外,Aptos 还提供完善的开发工具(tooling)生态,并与各类交易所和跨链桥深度集成,便于无缝接入。

功能以太坊Aptos
账户地址160-bit256-bit
存储模型基于合约的存储以账户为中心的代码和数据模型
调用者 IDmsg.sender&signer 引用
智能合约Solidity, EVMMove, MoveVM
优势成熟,应用广泛可扩展性、低延迟、可预测的费用
交易费用(gas 费用)可变,可能很高更低且更可预测
Sponsored Transactions需要第三方服务或 EIP-7702 wallet 支持 (2025+)通过 fee payer 字段 原生支持Geomi Gas Stations 提供生产级基础设施
账户结构余额在单个字段中,使用 nonce 计数模块和 resources,使用 sequence_number 序列号
数据存储Patricia Merkle 树带有 resources 和模块的全局存储
可升级性Proxy 模式直接模块升级
安全性易受 reentrancy 等攻击减轻常见漏洞
Dispatch 类型Dynamic dispatchStatic dispatch
Frontend SDKEthers.js 库Aptos Typescript SDK
NFT 标准ERC-721, ERC-1155Digital Asset
FT 标准ERC-20, factory pattern查看 Fungible Asset,在您的模块中复制粘贴:use aptos_framework::fungible_asset...
示例代码ERC-20 (每次部署新合约)Fungible Asset (单一可重用模块)

旧版 Coin 文档仍涵盖原始标准;大多数新部署应优先使用上面引用的 Fungible Asset 模块。


SolidityMove (Aptos)
代币结构每个代币都是独立的合约。每个代币是类型化的 FungibleAsset 实例化,重用相同的已发布模块。
代币标准必须符合 ERC-20 等标准;每次部署的实现可能不同。由共享模块强制执行的统一接口和实现;新代币只需注册新类型,而不是重新部署代码。
余额存储余额使用 mapping(映射)结构存储在合约中。面向 Resource 的余额:余额存在于用户账户拥有的可扩展对象中。
转账机制Token 可以在没有接收方明确许可的情况下转移。转账可以跳过接收方权限,但前提是 FA 明确启用 primary-store 自动创建(在代币的创建代码中可见)。

  • EVM:以其灵活性和**动态分发(dynamic dispatch)**而闻名,这使得智能合约能够实现广泛的行为。然而,这种灵活性可能会导致并行执行和网络操作的复杂性。
  • Move VM:专注于安全性和效率,在 VM 和编程语言之间采用了更高集成度的设计。其数据存储模型支持更好的并行化,而**静态分发(static dispatch)**提升了安全性和可预测性。

EVM (Ethereum Virtual Machine)Move VM (Move Virtual Machine)
数据存储数据存储在智能合约的 storage 空间中。数据存储在智能合约、用户账户和对象(Objects)之间。
并行化由于共享 storage 空间,并行执行受限。灵活的分割存储设计支持更多的并行执行。
VM 与语言集成EVM 和智能合约语言(例如 Solidity)是分离的层次。VM 层和 Move 语言之间无缝集成,用 Rust 编写的原生函数可以在 Move 中执行。
关键网络操作网络操作的实现可能复杂且不直接。验证者集管理等关键操作在 Move 中原生实现,允许直接执行。
函数调用Dynamic dispatch 允许任意的智能合约调用。Static dispatch 符合对安全性和可预测行为的关注。
类型安全合约类型提供了一定程度的类型安全。Move 中的模块 structs 和泛型提供了强大的类型安全。
交易安全使用 nonces 来保证交易顺序和安全。使用 sequence numbers 来保证交易顺序和安全。
认证存储支持,通过智能合约 storage。支持,利用 Move 的 resource 模型。
对象可访问性Objects 不是全局可访问的;受限于智能合约的 scope。保证 objects 的全局可访问性。

为以太坊开发者准备的迁移技巧

Section titled “为以太坊开发者准备的迁移技巧”

以太坊使用 mapping(映射)将所有数据存储在合约的存储(storage)中。Aptos 采用以账户为中心的模型,每个账户存储自己的 resources。不是由一个合约维护一个 mapping(address => T),而是每个用户在自己的地址存储自己的 T resource。

module my_hackathon_account::prototype {
use std::string;
use std::signer;
// Unlike Solidity's mapping(address => string), each account stores their own resource
struct MessageHolder has key, store, drop {
message: string::String,
}
entry fun set_message(account: &signer, message: string::String) acquires MessageHolder {
let addr = signer::address_of(account);
// Check if resource exists at this account (like checking mapping[addr])
if (exists<MessageHolder>(addr)) {
move_from<MessageHolder>(addr); // Remove old resource
};
// Store resource at the user's address (in their account, not in contract storage!)
move_to(account, MessageHolder { message });
}
#[view]
public fun get_message(addr: address): string::String acquires MessageHolder {
assert!(exists<MessageHolder>(addr), 0);
// Read message stored at the user's address
borrow_global<MessageHolder>(addr).message
}
}

默认情况下,模块会部署到您的账户地址。对于生产级应用,请考虑部署到 对象(Objects),这会为每次部署创建一个唯一的地址,并实现可转移的代码所有权。有关实现细节,请参阅 使用 Objects

了解更多: 全局存储(global storage)操作符, structs and resources