---
title: "EVM 与 SVM：开发者指南"
description: "面向开发者的 EVM 与 SVM 对比，涵盖账户模型、并行执行、费用、程序设计和迁移，并附代码示例。"
---

# EVM 与 SVM：开发者指南

<ImageBlock
  src="https://media.alchemy.com/overviews/evm-vs-svm-hero-20260924.png"
  alt="EVM 与 SVM：开发者指南"
  width={1920}
  height={900}
  priority
/>

每条区块链都运行在一个虚拟机上，虚拟机是执行程序并应用其状态变更的引擎。Ethereum 的引擎是 EVM（Ethereum 虚拟机），它同时也支撑着 Ethereum 的大多数 Layer 2。Solana 的引擎是 SVM（Solana 虚拟机），其设计目标是并行运行交易。两者在架构上的核心差异在于：EVM 将合约的代码和状态存储在一起，而 SVM 将它们保存在不同的账户中。这一差异决定了程序如何存储数据、交易如何执行，以及费用如何随拥堵而变化。

本指南从账户模型、执行、费用、程序设计和工具链几个方面对两者进行对比，附有简短的代码示例，最后给出一个决定在哪里构建或迁移的决策框架。如果你更喜欢视频，我们的 [SVM 与 EVM 构建者指南](https://www.youtube.com/watch?v=OsposMFk9Ro)涵盖了相同的对比内容。

## EVM 和 SVM 是什么？

EVM 是一个基于栈的虚拟机，它[逐笔处理交易](https://ethereum.org/en/developers/docs/evm/)，并更新单一的共享状态树。它的主要优势是兼容性。同一份 Solidity 合约无需修改即可部署到 Ethereum、其 Layer 2（Arbitrum、Base、Optimism、Unichain、World Chain、Ink）以及独立的 EVM 链（BNB Chain、Avalanche、Polygon、Monad、Berachain）上，字节码能运行的地方，周边工具也都能使用。如果你刚接触 EVM，我们的 [Ethereum 虚拟机详解](https://www.alchemy.com/overviews/what-is-the-ethereum-virtual-machine-evm)介绍了相关基础知识。

SVM 是围绕并行执行设计的。程序被编译为 [sBPF 字节码](https://solana.com/docs/core/programs)，这是一种派生自 eBPF（Linux 内核使用的同一种字节码设计）的基于寄存器的格式，并且每笔交易都会预先声明它将读取和写入哪些账户。这种声明使 Sealevel，即 [Solana 的并行运行时](https://solana.com/docs/references/terminology)，能够跨 CPU 核心同时运行互不冲突的交易。我们的 [Solana 虚拟机详解](https://www.alchemy.com/overviews/what-is-the-solana-virtual-machine)深入介绍了其执行管线。

下表总结了两者的主要差异。

<EmbeddedTable
  table={{
    columns: [
      { key: "1", width: 240, title: "维度", dataType: "object" },
      { key: "2", width: 240, title: "EVM", dataType: "object" },
      { key: "3", width: 240, title: "SVM", dataType: "object" },
    ],
    data: [
      {
        "1": {
          title: "<p>账户模型</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>代码和存储捆绑在合约账户中</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title: "<p>一切皆为账户；程序是无状态的</p>",
          tooltip: "",
          icon: "",
        },
        id: 0,
      },
      {
        "1": {
          title: "<p>执行</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>区块内顺序执行</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title: "<p>互不冲突的交易并行执行</p>",
          tooltip: "",
          icon: "",
        },
        id: 1,
      },
      {
        "1": {
          title: "<p>虚拟机</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>基于栈，256 位字长</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title: "<p>基于寄存器，派生自 eBPF</p>",
          tooltip: "",
          icon: "",
        },
        id: 2,
      },
      {
        "1": {
          title: "<p>费用市场</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>单一的全局基础费用加小费</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title: "<p>按签名收取的基础费用，加上仅作用于争用账户的优先费</p>",
          tooltip: "",
          icon: "",
        },
        id: 3,
      },
      {
        "1": {
          title: "<p>主要语言</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>Solidity</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title: "<p>Rust 搭配 Anchor</p>",
          tooltip: "",
          icon: "",
        },
        id: 4,
      },
      {
        "1": {
          title: "<p>代币</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>每个代币一个合约</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title: "<p>共享的 Token Program，每个代币一个 mint 账户</p>",
          tooltip: "",
          icon: "",
        },
        id: 5,
      },
      {
        "1": {
          title: "<p>升级</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>默认不可变，通过代理升级</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title: "<p>默认可升级，撤销升级权限即可冻结</p>",
          tooltip: "",
          icon: "",
        },
        id: 6,
      },
    ],
  }}
/>

## 账户模型有何不同？

Ethereum 有[两种账户类型](https://ethereum.org/en/developers/docs/accounts/)：由私钥控制的外部拥有账户，以及由代码控制的合约账户。合约账户除了字节码之外，还持有自己的存储，即一个由 32 字节槽位组成的键值存储。当你在 ERC-20 代币上调用 `balanceOf` 时，合约会从其自身存储中的一个映射里读取你的余额。代码和状态共用同一个地址，无法分离。

Solana 对一切都使用[单一的账户模型](https://www.alchemy.com/overviews/solana-account-model)。[Solana 上的每一份状态都是一个账户](https://solana.com/docs/core/accounts)，且结构相同：以 lamports 计的余额（Solana 的最小单位，类似于 wei）、一个数据字段、一个所有者，以及一个可执行标志。程序是一个数据为 sBPF 字节码、可执行标志设为 true 的账户。程序所管理的状态存放在独立的数据账户中。运行时直接强制执行所有权，只有拥有某个账户的程序才能修改其数据，这省去了 Solidity 合约需要自行实现的大部分访问控制逻辑。我们的 [Solana 数据账户与程序账户指南](https://www.alchemy.com/overviews/solana-data-vs-program-accounts)详细介绍了这种拆分。

对 EVM 开发者来说，程序衍生地址（PDA）通常是最陌生的概念。Solidity 合约将每个用户的数据存储在映射中，而 Solana 程序则根据[程序 ID 和一组种子](https://solana.com/docs/core/pda)（通常是用户的公钥）为每个用户衍生出一个专用的账户地址。这种衍生是确定性的，生成的地址位于 Ed25519 曲线之外，因此不存在对应的私钥。只有程序能代表该地址签名。实际上，Solidity 映射中的每个条目在 Solana 上都会成为一个独立的账户。

两种模型对存储的定价方式也不同。在 Ethereum 上，你在写入存储时以 gas 一次性支付费用。在 Solana 上，每个账户都必须持有一笔[与其大小成正比的可退还押金](https://solana.com/docs/core/accounts)，称为[租金豁免](https://www.alchemy.com/overviews/how-to-calculate-rent-for-solana-programs)。账户关闭时押金会退还，这让开发者有直接的动力去清除不再使用的状态。

## SVM 上的并行执行是如何工作的？

EVM 按顺序执行区块中的交易。一笔交易可以读写任何存储槽，而这些访问在交易运行之前是未知的，因此 EVM 无法安全地同时执行两笔交易。

Solana 要求每笔交易在执行前列出它将读取和写入的所有账户，从而消除了这种不确定性。调度器[并行运行只读取共享账户的交易，并将写入同一账户的交易串行化](https://docs.anza.xyz/validator/runtime)。写锁一次只允许一个线程持有。需要同一把锁的交易会排队并按顺序处理，它们不会因为冲突而失败。

这一模型会影响程序设计。许多用户同时更新的状态应当拆分到多个账户中，SPL 代币（Solana 的代币标准）正是这样组织的。两笔在无关钱包之间进行的 USDC 转账会写入四个不同的代币账户，因此可以同时执行。在 Ethereum 上，同样的两笔转账都会更新同一个 ERC-20 合约的存储，只能先后执行。

并行执行也正在进入 EVM 生态系统。[Monad](https://docs.monad.xyz/introduction/why-monad) 运行一条具备完整字节码兼容性的并行执行 EVM L1，MegaETH 则作为 Ethereum L2 应用了类似的技术。这些链在运行时检测冲突，而不是要求交易声明其账户，从而在提高吞吐量的同时保留了 EVM 兼容性。

## 两者的费用有何不同？

Ethereum 使用单一的全局费用市场。每笔交易都支付相同的[基础费用](https://ethereum.org/en/developers/docs/gas/)，该费用由协议在每个区块进行调整并销毁，外加一笔支付给验证者的可选优先小费。一笔标准的 ETH 转账消耗 21,000 gas，区块的目标为 3000 万 gas，[gas 上限为 6000 万](https://ethereum.org/en/developers/docs/blocks/)。由于基础费用作用于整条链，一个应用的需求会影响所有人。一次热门的 NFT 铸造或空投领取会抬高所有用户的基础费用，包括那些无关应用的用户。

Solana 采用不同的费用结构。每笔交易都支付[每个签名 5,000 lamports 的基础费用](https://solana.com/docs/core/fees)，其中一半被销毁，一半支付给验证者。计算量以计算单元（CU）计量，每条指令的默认预算为 200,000 CU，每笔交易最多 140 万 CU。交易还可以附带优先费（以每计算单元的 micro-lamports 计价），以便先于其他交易被调度。

关键区别在于费用竞争的范围。由于每笔交易都会指明它写入的账户，优先费竞争集中在争用相同账户的交易之间。生态系统将这种行为称为局部费用市场。[`getRecentPrioritizationFees`](https://solana.com/docs/rpc/http/getrecentprioritizationfees) RPC 方法体现了这一设计：它按交易将要锁定的可写账户来筛选费用样本。在一次热门铸造期间，写入该铸造相关账户的交易费用会上涨，而无关的交易基本不受影响。

这会影响容量规划。在 Ethereum 上，无关应用的活动可能会推高你的交易成本，而应用设计无法阻止这一点。在 Solana 上，费用压力主要来自对你自己账户的争用，因此将频繁写入的状态分散到更多账户中可以降低这种压力。

## 程序设计有哪些变化？

Solidity 合约是代码与存储合一的单一单元，并且[在设计上是不可变的](https://ethereum.org/en/developers/docs/smart-contracts/upgrading/)。部署后要更改其逻辑，需要使用基于 `delegatecall` 构建的代理模式，将调用路由到一个可替换的实现合约。一个最简的 Solidity 计数器如下：

<CodeSnippet
  language="solidity"
  code={`// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Counter {
    uint64 public count; // state lives inside the contract itself
    function increment() external {
        count += 1;
    }
}`}
/>

等效的 Solana 程序使用 [Anchor](https://www.alchemy.com/overviews/solana-anchor)（一个广泛使用的 Solana 程序框架）编写，本身不存储任何状态。计数器的值存放在一个独立的账户中，每次调用时都需显式传入：

<CodeSnippet
  language="rust"
  code={`use anchor_lang::prelude::*;
// Run anchor keys sync to set your program ID here and in Anchor.toml.
declare_id!("REPLACE_WITH_YOUR_PROGRAM_ID");
#[program]
mod counter {
    use super::*;
    pub fn increment(ctx: Context<Increment>) -> Result<()> {
        ctx.accounts.counter.count += 1;
        Ok(())
    }
}
#[derive(Accounts)]
pub struct Increment<'info> {
    #[account(mut)]
    pub counter: Account<'info, Counter>, // state account passed in explicitly
}
#[account]
pub struct Counter {
    pub count: u64,
}`}
/>

完整版本还应包含一条 initialize 指令，用于创建计数器账户并为其注资。Anchor 会在处理函数运行之前，根据 `Increment` 结构体验证每个账户，确认账户具有预期的类型和所有者。但这项检查并不限制谁可以调用该指令。按目前的写法，任何人都可以调用 `increment`，因此实际的程序需要添加签名者要求或派生地址约束，以控制谁可以更新计数器。

默认的升级行为正好相反。设置了升级权限的 Solana 程序[原生支持升级](https://solana.com/docs/core/programs)，撤销该权限即可使程序不可变。因此 Solana 程序不需要代理合约，这消除了 EVM 审计经常关注的一类代码。

代币也遵循同样的模式。每个 ERC-20 代币都是[独立的合约](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)，实现一套标准接口，因此支持众多代币的应用要依赖众多相互独立的代码库。在 Solana 上，代币通过[共享的 Token Program](https://solana.com/docs/tokens) 发行，Token-2022 则提供了一个扩展版本，支持转账手续费等可选功能。每个代币是一个记录供应量和小数位数的 mint 账户，每个持有者的余额存储在一个代币账户中。集成这些程序的应用无需针对每个代币编写代码，即可支持任何 SPL 代币。

事件处理是 EVM 具有明显优势的领域。EVM 合约会发出带索引的事件，`eth_getLogs` 和索引器可以原生地消费这些事件。Solana [没有原生的事件系统](https://www.anchor-lang.com/docs/features/events)。程序写入日志消息，Anchor 的事件宏将结构化数据编码到这些日志中，而日志可能被截断。因此，Solana 上的生产级索引通常依赖流式基础设施，例如 [Webhook](https://www.alchemy.com/webhooks) 和 [Solana gRPC 流](https://www.alchemy.com/solana-grpc)。

## 客户端技术栈是什么样的？

VM 的选择也决定了语言和工具。EVM 开发使用 Solidity 和成熟的工具链（Foundry、Hardhat），对测试、模糊测试和部署有广泛支持。Solana 开发使用 Rust 和 Anchor，学习曲线更陡，审计人员群体也更小，尽管这一群体正在壮大。我们的 [Web3 编程语言概览](https://www.alchemy.com/overviews/web3-programming-languages)更详细地介绍了各种语言选项。

数据模型的差异在客户端代码中同样可见。在 EVM 上，读取状态意味着调用合约上的某个函数，由它从自身存储中返回数据。以下示例使用 viem：

<CodeSnippet
  language="typescript"
  code={`import { createPublicClient, http, parseAbi, formatUnits } from "viem";
import { mainnet } from "viem/chains";
const client = createPublicClient({
  chain: mainnet,
  transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"),
});
const balance = await client.readContract({
  address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC contract
  abi: parseAbi(["function balanceOf(address) view returns (uint256)"]),
  functionName: "balanceOf",
  args: ["0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503"],
});
console.log(formatUnits(balance, 6));`}
/>

在 Solana 上，读取状态意味着获取持有该数据的账户。代币余额存储在代币账户中，而不是 Token Program 中，因此客户端直接读取该账户。以下示例使用 `@solana/kit`：

<CodeSnippet
  language="typescript"
  code={`import { createSolanaRpc, address } from "@solana/kit";
const rpc = createSolanaRpc("https://solana-mainnet.g.alchemy.com/v2/YOUR_API_KEY");
// SOL balance: fetch the account's lamports by its address
const { value: lamports } = await rpc
  .getBalance(address("83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri"))
  .send();
// SPL balance: read the token account directly
const { value: tokenBalance } = await rpc
  .getTokenAccountBalance(address("2ocS3orPq3jyszjsJ4NozKWyhdotr3csDjAizmkj65aH"))
  .send();
console.log(lamports, tokenBalance.uiAmountString);`}
/>

这种模式贯穿整个客户端层。EVM 客户端查询合约，而 Solana 客户端需要知道每份数据由哪个账户持有，这使得账户布局成为应用设计的一部分。

## 将 EVM 应用移植到 Solana 时，哪些部分会失效？

将应用从 EVM 迁移到 Solana 需要重写链上代码，因为两者的账户模型和执行模型不同。主要变化包括：

- **`msg.sender` 变为签名者账户。** Solana 上的授权来自交易中被标记为签名者、并由你的程序检查的账户，以及在程序自身持有权限时[由程序代为签名的 PDA](https://solana.com/docs/core/cpi)。
- **映射变为 PDA。** Solidity 映射中的每个键都会成为一个衍生账户，必须在首次使用前创建并预存租金。读取数据的方式也随之改变，因为客户端获取的是账户，而不是查询合约存储。
- **合约存储变为有固定大小、预存租金的账户。** 状态必须按已知大小预先分配，账户关闭时押金会退还。
- **不再需要代理升级模式。** 程序的升级权限取代了代理设置，撤销该权限即可使程序不可变。
- **事件变为日志和流式传输。** 任何消费 `eth_getLogs` 的系统都必须围绕日志解析、Webhook 或 gRPC 流重新构建。
- **客户端和测试技术栈发生变化。** 客户端代码从 viem 迁移到 `@solana/kit`，测试从 Foundry 迁移到 Anchor 的测试框架，CI 需要一个本地验证者。

反方向迁移（从 SVM 到 EVM）的团队，通常会获得更成熟的工具链、原生事件索引和更大的审计市场，同时放弃并行执行、亚秒级确认和按账户隔离的费用。

无论哪个方向，团队的学习曲线通常都是最大的成本。对于转向 Solana 的 EVM 工程师，我们的 [Solana 开发路线图](https://www.alchemy.com/overviews/learn-solana-development)是一个不错的起点。

## 如何在 EVM 和 SVM 之间做出选择？

<EmbeddedTable
  table={{
    columns: [
      { key: "1", width: 240, title: "你要构建的是", dataType: "object" },
      {
        key: "2",
        width: 240,
        title: "建议的起点",
        dataType: "object",
      },
      { key: "3", width: 240, title: "原因", dataType: "object" },
    ],
    data: [
      {
        "1": {
          title: "<p>高吞吐量的消费级应用（支付、交易、铸造）</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>SVM</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title:
            "<p>并行执行和按账户隔离的费用，使成本在你自身的负载下保持稳定</p>",
          tooltip: "",
          icon: "",
        },
        id: 0,
      },
      {
        "1": {
          title: "<p>与现有流动性组合的 DeFi 协议</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>EVM</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title: "<p>成熟的 DeFi 协议、集成和审计方集中在 EVM 生态系统中</p>",
          tooltip: "",
          icon: "",
        },
        id: 1,
      },
      {
        "1": {
          title: "<p>熟悉 Solidity、产品对延迟不敏感的团队</p>",
          tooltip: "",
          icon: "",
        },
        "2": {
          title: "<p>EVM，或并行 EVM 链</p>",
          tooltip: "",
          icon: "",
        },
        "3": {
          title:
            "<p>当工作负载不需要 SVM 的吞吐量时，留在现有技术栈上可以避免重写</p>",
          tooltip: "",
          icon: "",
        },
        id: 2,
      },
    ],
  }}
/>

<ExternalVideo
  url="https://www.youtube.com/watch?v=OsposMFk9Ro"
  provider="youtube"
  providerUid="OsposMFk9Ro"
/>

## Alchemy 如何支持 EVM 和 SVM 开发？

我们在单一平台上同时支持这两个生态系统。我们的 [RPC 端点](https://www.alchemy.com/rpc-api)覆盖 Ethereum、主要 L2 以及更广泛的 EVM 生态系统。我们的 [Solana 基础设施](https://www.alchemy.com/blog/solana-infrastructure)提供最高快 20 倍的归档调用和 99.99% 的正常运行时间，[gRPC 流](https://www.alchemy.com/solana-grpc)则提供 Solana 索引所依赖的实时数据流。如果你正在评估 Solana 基础设施，我们的 [Solana RPC 指南](https://www.alchemy.com/overviews/solana-rpc)介绍了选择服务商时需要关注的要点。

一个免费的 API 密钥即可让你在同一个控制台中获得 EVM 链和 Solana 的端点，无需签订合同或承诺最低用量，也无需为每个生态系统分别集成不同的服务商。
