---
title: "EVM vs SVM：開發者指南"
description: "為開發者比較 EVM 與 SVM，涵蓋帳戶模型、平行執行、費用、program 設計與遷移，並附上程式碼範例。"
---

# EVM vs SVM：開發者指南

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

每條區塊鏈都運行在一個虛擬機之上，也就是負責執行鏈上程式並套用其狀態變化的引擎。Ethereum 的引擎是 EVM（Ethereum Virtual Machine），它同時也驅動了 Ethereum 大多數的 Layer 2。Solana 的引擎是 SVM（Solana Virtual Machine），其設計目的是平行執行交易。兩者在架構上的核心差異在於：EVM 將合約的程式碼與狀態儲存在一起，而 SVM 則將兩者存放在不同的帳戶中。這項差異決定了鏈上程式如何儲存資料、交易如何執行，以及費用如何因應網路壅塞。

本指南從帳戶模型、執行方式、費用、program 設計與工具等面向比較兩者，附上簡短的程式碼範例，最後提供一套決策框架，協助你決定要在哪裡建構或移植應用。如果你偏好影片，我們的 [SVM vs 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 Virtual Machine 說明文章](https://www.alchemy.com/overviews/what-is-the-ethereum-virtual-machine-evm) 介紹了基礎知識。

SVM 是圍繞平行執行來設計的。Program 會編譯成 [sBPF 位元碼](https://solana.com/docs/core/programs)，這是一種衍生自 eBPF（Linux kernel 所使用的同一種位元碼設計）的暫存器式格式，而且每筆交易都會預先宣告它將讀取與寫入哪些帳戶。這項宣告讓 Sealevel，也就是 [Solana 的平行執行環境](https://solana.com/docs/references/terminology)，能在多個 CPU 核心上同時執行彼此不衝突的交易。我們的 [Solana Virtual Machine 說明文章](https://www.alchemy.com/overviews/what-is-the-solana-virtual-machine) 深入介紹了其執行 pipeline。

下表整理了主要差異。

<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>一切皆是帳戶；program 是無狀態的</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/)：由私鑰控制的外部擁有帳戶（externally-owned account），以及由程式碼控制的合約帳戶。合約帳戶除了保存位元碼，也持有自己的儲存空間，也就是一個由 32 位元組槽位組成的鍵值儲存區。當你對某個 ERC-20 代幣呼叫 `balanceOf` 時，合約會從自身儲存空間中的一個 mapping 讀取你的餘額。程式碼與狀態共用同一個位址，無法分開。

Solana 對所有東西都使用[單一帳戶模型](https://www.alchemy.com/overviews/solana-account-model)。[Solana 上的每一份狀態都是一個帳戶](https://solana.com/docs/core/accounts)，且結構相同：以 lamports（Solana 的最小單位，類似 wei）計價的餘額、一個資料欄位、一個 owner，以及一個 executable 旗標。Program 是一種資料內容為 sBPF 位元碼、且 executable 旗標設為 true 的帳戶。Program 所管理的狀態則存放在獨立的資料帳戶中。執行環境會直接強制執行 ownership，因為只有擁有某個帳戶的 program 才能修改其資料，這省去了 Solidity 合約必須自行實作的大量存取控制邏輯。我們的 [Solana 資料帳戶 vs. program 帳戶指南](https://www.alchemy.com/overviews/solana-data-vs-program-accounts) 詳細說明了這種區分。

對 EVM 開發者來說，Program derived address（PDA）通常是最陌生的概念。Solidity 合約會把每位使用者的資料存放在 mapping 中，而 Solana program 則是根據 [program ID 與一組 seed](https://solana.com/docs/core/pda)（通常是使用者的公鑰）為每位使用者衍生出專屬的帳戶位址。這種衍生是確定性的，產生的位址落在 Ed25519 曲線之外，因此不存在對應的私鑰。只有該 program 能代表這個位址簽署。實務上，Solidity mapping 中的每一筆項目，在 Solana 上都會成為獨立的帳戶。

兩種模型對儲存空間的計價方式也不同。在 Ethereum 上，你只在寫入時以 gas 支付一次儲存費用。在 Solana 上，每個帳戶都必須持有一筆[與其大小成正比的可退還押金](https://solana.com/docs/core/accounts)，稱為[免租（rent exemption）](https://www.alchemy.com/overviews/how-to-calculate-rent-for-solana-programs)。帳戶關閉時會退還這筆押金，讓開發者有直接的誘因清除不再使用的狀態。

## SVM 上的平行執行如何運作？

EVM 會循序執行區塊中的交易。一筆交易可以讀寫任何儲存槽，而這些存取在交易實際執行前無從得知，因此 EVM 無法安全地同時執行兩筆交易。

Solana 消除了這種不確定性，要求每筆交易在執行前列出它將讀取與寫入的每個帳戶。排程器會[平行執行只讀取共享帳戶的交易，並將寫入同一帳戶的交易序列化](https://docs.anza.xyz/validator/runtime)。寫入鎖一次只允許一個執行緒持有。需要同一個鎖的交易會排入佇列並依序處理，不會因為衝突而失敗。

這個模型會影響 program 設計。許多使用者會同時更新的狀態，應該分散到多個帳戶中，這正是 SPL 代幣（Solana 的代幣標準）的結構方式。兩筆發生在無關錢包之間的 USDC 轉帳會寫入四個不同的代幣帳戶，因此可以同時執行。在 Ethereum 上，同樣的兩筆轉帳都會更新同一份 ERC-20 合約的儲存空間，只能一筆接著一筆執行。

平行執行也正在進入 EVM 生態系統。[Monad](https://docs.monad.xyz/introduction/why-monad) 運行一條具備完整位元碼相容性的平行執行 EVM L1，而 MegaETH 則以 Ethereum L2 的形式採用類似技術。這些鏈在執行期偵測衝突，而不是要求交易宣告其帳戶，因此在提升吞吐量的同時保留了 EVM 相容性。

## 兩者的費用有何不同？

Ethereum 使用單一的全域費用市場。每筆交易都支付相同的[基本費用（base fee）](https://ethereum.org/en/developers/docs/gas/)，由協定在每個區塊調整並銷毀，另外可再選擇支付優先小費給驗證者。一筆標準的 ETH 轉帳花費 21,000 gas，區塊的目標為 3,000 萬 gas，[gas limit 為 6,000 萬](https://ethereum.org/en/developers/docs/blocks/)。由於基本費用適用於整條鏈，單一應用的需求會影響所有人。熱門的 NFT 鑄造或空投領取會推高所有使用者的基本費用，包括無關應用的使用者。

Solana 採用不同的費用結構。每筆交易都要支付[每個簽章 5,000 lamports 的基本費用](https://solana.com/docs/core/fees)，其中一半銷毀，一半支付給驗證者。運算以 compute unit（CU）計量，每個 instruction 的預設 budget 為 200,000 CU，每筆交易的上限為 140 萬 CU。交易也可以附加優先費（prioritization fee），以每 compute unit 多少 micro-lamports 計價，藉此比其他交易更早被排程。

關鍵差異在於費用競爭的範圍。由於每筆交易都會指明它要寫入的帳戶，優先費的競爭會集中在爭用相同帳戶的交易之間。生態系統將這種行為稱為局部費用市場（local fee markets）。[`getRecentPrioritizationFees`](https://solana.com/docs/rpc/http/getrecentprioritizationfees) 這個 RPC 方法反映了這種設計：它會依交易將鎖定的可寫入帳戶來篩選費用樣本。在熱門的鑄造活動期間，寫入該鑄造相關帳戶的交易費用會上升，而無關的交易則大致不受影響。

這會影響容量規劃。在 Ethereum 上，無關應用的活動可能推高你的交易成本，而應用設計無法避免這一點。在 Solana 上，費用壓力主要來自你自身帳戶上的爭用，因此將頻繁寫入的狀態分散到更多帳戶，就能降低費用壓力。

## Program 設計有哪些改變？

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;
    }
}`}
/>

以 [Anchor](https://www.alchemy.com/overviews/solana-anchor)（一個廣泛使用的 Solana program 框架）撰寫的等效 Solana program，本身不儲存任何狀態。計數值存放在一個獨立的帳戶中，每次呼叫時都會明確傳入：

<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 instruction，用來建立計數器帳戶並存入所需資金。Anchor 會在處理函式執行前，依據 `Increment` 結構驗證每個帳戶，確認帳戶具有預期的型別與 owner。不過，這項檢查並不會限制誰可以呼叫該 instruction。依目前的寫法，任何人都能呼叫 `increment`，因此實際的 program 需要加上 signer 要求或衍生位址限制，以控制誰可以更新計數器。

預設的升級行為正好相反。以升級權限（upgrade authority）部署的 Solana program [原生即可升級](https://solana.com/docs/core/programs)，撤銷該權限則會使 program 變成不可變。因此 Solana program 不需要代理合約，也省去了 EVM 審計經常關注的一整類程式碼。

代幣也遵循相同的模式。每個 ERC-20 代幣都是實作標準介面的[獨立合約](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)，因此支援多種代幣的應用必須依賴許多各自獨立的程式碼庫。在 Solana 上，代幣是透過[共用的 Token Program](https://solana.com/docs/tokens) 發行，而 Token-2022 則提供擴充版本，支援轉帳手續費等選用功能。每種代幣都是一個記錄供給量與小數位數的 mint 帳戶，每位持有者的餘額則儲存在代幣帳戶中。整合這些 program 的應用，不需要為個別代幣撰寫程式碼，就能支援任何 SPL 代幣。

事件處理是 EVM 具有明顯優勢的領域。EVM 合約會發出帶索引的事件，`eth_getLogs` 與索引器可以原生使用這些事件。Solana [沒有原生的事件系統](https://www.anchor-lang.com/docs/features/events)。Program 會寫入日誌訊息，而 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` 變成 signer 帳戶。** Solana 上的授權來自交易中被標記為 signer、並由你的 program 檢查的帳戶；當 program 本身持有權限時，則來自[由 program 代為簽署的 PDA](https://solana.com/docs/core/cpi)。
- **Mapping 變成 PDA。** Solidity mapping 中的每個 key 都會變成一個衍生帳戶，必須在首次使用前建立並存入 rent 所需的資金。讀取資料的方式也會改變，因為用戶端是取得帳戶，而不是查詢合約儲存空間。
- **合約儲存空間變成有固定大小、需存入 rent 資金的帳戶。** 狀態必須以已知大小預先配置，帳戶關閉時則會退還押金。
- **不再需要代理升級模式。** Program 的升級權限取代了代理設定，撤銷該權限則會使 program 變成不可變。
- **事件變成日誌與串流。** 任何使用 `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 倍的 archive 呼叫與 99.99% 的正常運作時間，而 [gRPC 串流](https://www.alchemy.com/solana-grpc) 則提供 Solana 索引所仰賴的即時資料饋送。如果你正在評估 Solana 基礎設施，我們的 [Solana RPC 指南](https://www.alchemy.com/overviews/solana-rpc) 說明了挑選供應商時應注意的事項。

一組免費的 API 金鑰，就能讓你從同一個儀表板取得 EVM 鏈與 Solana 的端點，無需簽約，也沒有最低用量承諾，更不必為每個生態系統分別整合不同的供應商。
