这篇文章从安全角度对比了Solidity、Rust (Solana) 和 Move (Aptos/Sui) 三种 Layer 1 区块链编程语言的架构、资产模型、重入攻击防范、访问控制及升级模式。它深入探讨了这些语言在安全性、性能和开发者复杂性之间的权衡,并强调 Move 的资源导向编程在防止漏洞方面的优势。
Layer 1 (L1) 区块链的架构格局在过去十年中经历了彻底的变革,这主要是由从 对抗性攻击 中吸取的严峻教训所驱动。在智能合约开发的早期阶段,主要目标是表达性,为开发者提供一个图灵完备的画布来构建去中心化应用 (dApps)。以太坊及其原生语言 Solidity 开创了这个时代,建立了一个基于可变全局状态和同步可组合性的主导范式。
然而,这种灵活性带来了惊人的代价。“代码即法律”的信条在 2016 年的 DAO 攻击中受到了严峻考验,随后的几年中,数十亿美元因重入攻击、整数溢出和未初始化代理而损失。这些事件凸显了早期区块链架构中的一个根本性不协调:用于管理不可变金融价值的语言继承自优先考虑灵活性而非严格安全性的 Web 开发范式。
随着行业成熟,第二代架构应运而生,优先考虑性能和吞吐量。Solana 采用 Rust 编程语言,引入了一种无状态执行模型,旨在通过并行化最大化硬件利用率。这使得瓶颈从网络转移到开发者管理复杂并发和账户验证逻辑的能力。尽管 Rust 提供了内存安全,但它并未从根本上解决区块链状态管理的逻辑缺陷,导致了一类新的漏洞,如账户混淆和签名者检查缺失。
最近,源自 Meta Diem 项目的 Move 编程语言引入了第三种范式:资源导向架构。被 Aptos 和 Sui 采用的 Move 从设计之初就旨在通过类型系统强制执行数字稀缺性和访问控制。通过将资产视为遵循线性逻辑的“资源”,这意味着它们永远不能被隐式复制或丢弃,Move 试图消除困扰 Solidity 和 Rust 的所有类型漏洞。
对于 L1 架构师来说,在 Solidity (EVM)、Rust (SVM) 和 Move (MoveVM) 之间做出选择不再仅仅是对语法的偏好;这是一个关于网络安全拓扑、状态模型和风险概况的根本性决定。本报告提供了对这三种范式的详尽的、安全优先的比较。
区块链的安全状况取决于其编程语言的设计哲学。虽然 Solidity、Rust 和 Move 都支持图灵完备,但它们优化了截然不同的约束。
Solidity 目标是 以太坊虚拟机 (EVM),一个作为单例计算机运行的准图灵完备堆栈机器。它的主要抽象是智能合约,它将逻辑和状态封装在一个可寻址的实体中。
EVM 利用可变 Merkle Patricia Trie 作为全局状态。这种模型实现了同步的原子可组合性,这是 DeFi 生态系统的引擎,允许在单个区块中进行闪电贷等复杂交互。然而,Solidity 默认情况下是“隐式不安全”的。函数历史上是 public 的,状态变量是可变的,并且外部调用可以通过 fallback 函数劫持控制流。Solidity 中的资产表示为数据(映射中的整数),而不是物理资源,这创建了一种“账本式”模型,其中质量守恒是逻辑要求,而非系统保证。
Rust 是一种系统语言,适用于 Solana 虚拟机 (SVM)。Solana 程序是无状态的;它们只包含逻辑。状态存储在单独的账户中,这些账户是在执行期间传递给程序的数据缓冲区。
这种解耦允许通过识别不重叠的交易进行大规模并行化。Rust 的借用检查器在编译时保证内存安全,防止空指针解引用和缓冲区溢出。然而,这并不能转化为逻辑安全性。验证输入账户的来源和权限的负担完全落在开发者身上,将风险转向“账户混淆”和“签名者检查缺失”。
Move 引入了资源导向编程,在类型系统内实现了线性逻辑。被定义为资源的 struct 表现得像一个物理对象:它必须且只能被使用一次,不能被隐式复制或丢弃。
安全性在源代码级别和字节码级别都得到强制执行。Move 字节码验证器在执行前在链上运行,确保即使是恶意的字节码也无法违反类型安全或资源线性。历史上,Move 还限制了动态调度以防止重入,确保调用图在编译时确定。
| 特性 | Solidity (EVM) | Rust (Solana/SVM) | Move (Aptos/Sui) |
|---|---|---|---|
| 主要抽象 | 智能合约 (代码 + 状态) | 程序 (逻辑) + 账户 (状态) | 模块 (逻辑) + 资源 (状态) |
| 资产表示 | 映射中的整数 (数据) | 账户中的数据 (缓冲区) | 线性类型 (资源) |
| 安全强制 | 运行时检查 (Gas, 回滚) | 编译时 (借用检查器) | 编译时 + 字节码验证 |
| 默认访问 | Public / 开放 | 手动检查签名 | 受模块可见性限制 |
| 状态模型 | 全局可变 Trie | 外部账户缓冲区 | 全局存储 / 对象存储 |
| 重入风险 | 高 | 低 (CPI 深度限制) | 极低 (资源锁定) |
资产的表示方式决定了网络中理论上可能出现的错误类型。

在 EVM 中,资产是哈希表中的一个逻辑条目:
1mapping(address => uint256) balances;
VM 本身不理解这些整数代表价值。这导致:
MAX_UINT。Move 将资产视为一等资源。对于 token,开发者省略了 copy 和 drop 能力:
1struct Coin<phantom CoinType> has store {
2 value: u64
}
因为它缺少 copy,let c2 = c1; 是一个移动操作;c1 变得无效。因为它缺少 drop,Coin 不能在没有被显式处理(存入或销毁)的情况下超出范围。
“烫手山芋”模式:开发者可以创建没有能力的 struct。这些 struct 必须在交易结束前由特定函数消费,从而在类型系统层面强制执行复杂操作(如闪电贷)的原子性。
在 Solana 中,资产是 Token Program 拥有的账户中的数据。开发者必须手动验证:
重入发生在外部代码劫持控制流,在第一次执行完成之前重复执行某个函数。

Solidity 的 call 函数将控制流转发给接收方,通常会触发恶意的 fallback 函数。
1// Vulnerable Solidity Code Example
2function withdraw() public {
3 uint bal = balances[msg.sender];
4 require(bal > 0);
5
6 (bool sent, ) = msg.sender.call{value: bal}(""); // 外部调用
7 require(sent, "Failed to send Ether");
8
9 balances[msg.sender] = 0; // 状态更新发生得太晚了!
10}
只读重入:一种变体,重入调用目标是一个 view 函数(如预言机价格),该函数返回“脏”状态,因为父交易尚未完成其更新。
Solana 通过以下方式缓解了这个问题:
Move 在 VM 级别解决了重入问题:
1let balance = borrow_global_mut<Balance>(addr);
2// balance 现在已被锁定。
如果外部调用尝试重入并再次借用 Balance,VM 将以 EALREADY_BORROWED 终止。这也解决了只读重入问题,因为借用检查器阻止了在可变引用活动时存在不可变引用。
Aptos 采用以账户为中心的模型。资源通过 borrow_global<T>(address) 存储在地址下。它通过 Block-STM 实现并行化,Block-STM 乐观地执行交易,并在检测到冲突时重新运行它们。
Sui 将一切视为具有唯一 ID 的对象。交易预先声明对象依赖项。拥有对象绕过全局共识以实现即时最终性,而共享对象则通过共识。
| 特性 | Aptos Move | Sui Move |
|---|---|---|
| 状态存储 | 全局映射 (地址, 类型) | 对象存储 (ObjectID) |
| 并发性 | 乐观 (Block-STM) | 确定性 (DAG / 输入) |
| 访问控制 | 签名者检查 | 能力 (对象持有) |
| 升级 | 兼容策略 | 不可变包 + UpgradeCap |
| 最佳用例 | 深度 DeFi / 可组合性 | 游戏 / NFT / 高吞吐量 |
依赖 msg.sender。这通常导致中心化的“上帝模式”角色,并且如果 tx.origin 使用不当,容易受到网络钓鱼攻击。
权限是一个对象(能力),而不是身份。
1struct AdminCap has key, store { id: UID }
2
3public entry fun mint(_: &AdminCap,...) { ... }
mint 函数不检查是谁调用的它;它检查调用者是否提供了 AdminCap。这允许在不改变合约逻辑的情况下将权限转移或由 MultiSigs 持有。
使用 delegatecall 将代理指向逻辑合约。这容易发生存储冲突(变量未对齐)和未初始化代理的问题。
VM 根据旧字节码验证新字节码。它确保内存布局安全(不改变现有 struct)和 API 安全(public 签名必须保持),通过设计防止存储冲突。
虽然 Solidity 依赖于 Slither 或 Certora 等外部工具,但 Move 将 Move Prover (MVP) 集成到其工具链中。通过这种方式,Move 将 形式化验证 更接近开发者工作流程。开发者直接在代码中编写规范(不变量):
1invariant balance >= 0;
2invariant global<Supply>(addr).total == sum(all_coin_balances);
Prover 使用 SMT 求解器数学证明这些不变量适用于所有可能的执行路径。
对于 L1 架构师来说,语言选择定义了网络的风险概况:
在十亿美元漏洞的时代,Move 的资源导向范式代表了自智能合约发明以来区块链安全领域最重要的架构进步。
为什么 Move 被认为比 Solidity 更安全?
Move 对资源使用“线性逻辑”,这意味着资产不能被意外复制或丢弃。这消除了“浮动 token”或“双重支付”等在 Solidity 账本式模型中可能出现的所有类型的错误,从而减少了对人工安全检查的依赖。
Rust 的内存安全能防止智能合约被黑客攻击吗?
不能。Rust 的内存安全防止系统级崩溃(如缓冲区溢出),但它不防止逻辑错误。开发者仍然必须手动验证账户所有权和签名。许多 Solana 攻击源于“签名者检查缺失”,这是 Rust 编译器无法捕获的逻辑缺陷。
什么是重入?为什么它在 2026 年仍然存在?
重入发生在恶意合约在状态更新完成之前回调到调用合约时。尽管这是一个已知问题已有十年之久,但它仍然存在,因为 Solidity 默认为“检查-影响-交互”的手动模式。Move 通过禁用动态调度或在执行期间锁定资源,在架构层面防止了这种情况。
如果我使用形式化验证,Solidity 审计仍然有必要吗?
是的。形式化验证证明代码符合规范,但它不能证明规范本身在经济上是合理的。仍然需要进行审计以弥合“逻辑与意图”之间的差距。
Move 代码审计成本与 Solidity 相比如何?
由于需要专业的技能,Move(和 Rust)审计通常比 Solidity 审计费用更高。然而,Move 中更严格的编译器检查可以减少花在“低级”错误上的时间。请参阅我们 2026 年的审计定价指南以获取确切的基准。
我可以轻松地将我的 Solidity dApp 移植到 Aptos/Sui 吗?
直接移植很困难,因为范式不同(以合约为中心与以资源为中心)。通常最好重写逻辑以利用 Move 的原生安全特性,而不是试图将 Solidity 模式强加给 Move,这可能导致效率低下和安全性较差的代码。
无论你是基于 EVM、Solana 还是 Move 进行构建,安全性都是你的 TVL 的基础。在 Zealynx,我们专注于跨链安全审查,从 Solidity 中的 gas 优化 到 Move 中的资源分析。
- 原文链接: zealynx.io/blogs/move-vs...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!