Saltar al contenido
0%

EVM vs SVM: guía para desarrolladores

Uttam Singh

Escrito por Uttam Singh

Publicado el 25 de septiembre de 202611 min de lectura

EVM vs SVM: guía para desarrolladores

Toda blockchain funciona sobre una máquina virtual, el motor que ejecuta los programas y aplica sus cambios de estado. El motor de Ethereum es la EVM (Ethereum Virtual Machine), que también impulsa la mayoría de sus Layer 2. El de Solana es la SVM (Solana Virtual Machine), diseñada para ejecutar transacciones en paralelo. La diferencia arquitectónica central es que la EVM almacena juntos el código y el estado de un contrato, mientras que la SVM los mantiene en cuentas separadas. Esa diferencia determina cómo los programas almacenan datos, cómo se ejecutan las transacciones y cómo responden las fees a la congestión.

Esta guía compara ambas en modelos de cuentas, ejecución, fees, diseño de programas y herramientas, con ejemplos de código breves, y cierra con un marco para decidir dónde construir o hacia dónde portar. Si prefieres video, nuestra guía de SVM vs EVM para desarrolladores cubre la misma comparación.

¿Qué son la EVM y la SVM?

La EVM es una máquina virtual basada en stack que procesa las transacciones una por una y actualiza un único árbol de estado compartido. Su principal ventaja es la compatibilidad. El mismo contrato de Solidity se despliega sin cambios en Ethereum, en sus Layer 2 (Arbitrum, Base, Optimism, Unichain, World Chain, Ink) y en chains EVM independientes (BNB Chain, Avalanche, Polygon, Monad, Berachain), y las herramientas asociadas funcionan en cualquier lugar donde funcione el bytecode. Si la EVM es nueva para ti, nuestra guía sobre la Ethereum Virtual Machine cubre los fundamentos.

La SVM se diseñó en torno a la ejecución paralela. Los programas se compilan a bytecode sBPF, un formato basado en registros derivado de eBPF (el mismo diseño de bytecode que usa el kernel de Linux), y cada transacción declara de antemano qué cuentas leerá y escribirá. Esta declaración permite que Sealevel, el runtime paralelo de Solana, ejecute simultáneamente transacciones sin conflictos entre núcleos de CPU. Nuestra guía sobre la Solana Virtual Machine cubre el pipeline de ejecución en profundidad.

La siguiente tabla resume las diferencias principales.

Dimensión
EVM
SVM

Modelo de cuentas

Código y almacenamiento agrupados en cuentas de contrato

Todo es una cuenta; los programas no tienen estado

Ejecución

Secuencial dentro de un bloque

Paralela entre transacciones sin conflictos

Máquina virtual

Basada en stack, palabras de 256 bits

Basada en registros, derivada de eBPF

Mercado de fees

Una base fee global más propinas

Base fee por firma más priority fees acotadas a las cuentas con contención

Lenguaje principal

Solidity

Rust con Anchor

Tokens

Un contrato por token

Token Program compartido, una cuenta mint por token

Actualizaciones

Inmutable por defecto, proxies para actualizar

Actualizable por defecto, revocar la autoridad lo congela

¿En qué se diferencian los modelos de cuentas?

Ethereum tiene dos tipos de cuentas: cuentas de propiedad externa, controladas por claves privadas, y cuentas de contrato, controladas por código. Una cuenta de contrato guarda su propio almacenamiento, un key-value store de slots de 32 bytes, junto con su bytecode. Cuando llamas a balanceOf en un token ERC-20, el contrato lee tu balance desde un mapping en su propio almacenamiento. El código y el estado comparten una dirección y no se pueden separar.

Solana usa un modelo de cuentas único para todo. Cada porción de estado en Solana es una cuenta con la misma estructura: un balance en lamports (la unidad más pequeña de Solana, como wei), un campo de datos, un owner y un flag executable. Un programa es una cuenta cuyos datos son bytecode sBPF y cuyo flag executable tiene el valor true. El estado que administra un programa vive en cuentas de datos separadas. El runtime aplica el ownership directamente, ya que solo el programa que es owner de una cuenta puede modificar sus datos, lo que elimina gran parte de la lógica de control de acceso que un contrato de Solidity implementa por sí mismo. Nuestra guía de cuentas de datos vs. cuentas de programa en Solana cubre esta separación en detalle.

Las program derived addresses (PDAs) suelen ser el concepto menos familiar para los desarrolladores de EVM. Donde un contrato de Solidity almacena datos por usuario en un mapping, un programa de Solana deriva una dirección de cuenta dedicada para cada usuario a partir del ID del programa y un conjunto de seeds, normalmente la clave pública del usuario. La derivación es determinista y produce una dirección fuera de la curva Ed25519, así que no existe una clave privada para ella. Solo el programa puede firmar en su nombre. En la práctica, cada entrada de un mapping de Solidity se convierte en su propia cuenta en Solana.

Los dos modelos también cobran el almacenamiento de forma distinta. En Ethereum, pagas el almacenamiento una sola vez, en gas, cuando lo escribes. En Solana, cada cuenta debe mantener un depósito reembolsable proporcional a su tamaño, conocido como exención de rent. El depósito se devuelve cuando se cierra la cuenta, lo que da a los desarrolladores un incentivo directo para eliminar el estado que no usan.

¿Cómo funciona la ejecución paralela en la SVM?

La EVM ejecuta las transacciones de un bloque de forma secuencial. Una transacción puede leer o escribir cualquier slot de almacenamiento, y esos accesos no se conocen hasta que se ejecuta, así que la EVM no puede ejecutar de forma segura dos transacciones al mismo tiempo.

Solana elimina esa incertidumbre al exigir que cada transacción liste todas las cuentas que leerá y escribirá antes de la ejecución. El scheduler ejecuta en paralelo las transacciones que solo leen cuentas compartidas y serializa las transacciones que escriben en la misma cuenta. Un lock de escritura permite un solo thread a la vez. Las transacciones que necesitan el mismo lock se encolan y se procesan en orden, y no fallan por el conflicto.

Este modelo afecta el diseño de programas. El estado que muchos usuarios actualizan al mismo tiempo debe dividirse entre varias cuentas, que es como se estructuran los tokens SPL (el estándar de tokens de Solana). Dos transferencias de USDC entre wallets no relacionadas escriben en cuatro cuentas de token distintas, así que pueden ejecutarse al mismo tiempo. En Ethereum, esas mismas dos transferencias actualizan el almacenamiento de un único contrato ERC-20 y se ejecutan una después de la otra.

La ejecución paralela también está llegando al ecosistema EVM. Monad opera una L1 EVM con ejecución paralela y compatibilidad total de bytecode, y MegaETH aplica técnicas similares como L2 de Ethereum. Estas chains detectan los conflictos en tiempo de ejecución en lugar de exigir que las transacciones declaren sus cuentas, lo que preserva la compatibilidad con la EVM y a la vez aumenta el throughput.

¿Cómo se comparan las fees?

Ethereum usa un único mercado de fees global. Cada transacción paga la misma base fee, que el protocolo ajusta en cada bloque y quema, más una propina de prioridad opcional para el validador. Una transferencia estándar de ETH cuesta 21,000 de gas, y los bloques tienen un objetivo de 30 millones de gas con un límite de 60 millones de gas. Como la base fee aplica a toda la chain, la demanda de una aplicación afecta a todos. Un mint popular de NFT o el claim de un airdrop sube la base fee para todos los usuarios, incluidos los de aplicaciones no relacionadas.

Solana usa una estructura de fees distinta. Cada transacción paga una base fee de 5,000 lamports por firma, de la cual la mitad se quema y la otra mitad se paga al validador. El compute se mide en compute units (CU), con un presupuesto por defecto de 200,000 CU por instrucción y un máximo de 1.4 millones de CU por transacción. Las transacciones también pueden incluir una priority fee, con precio en micro-lamports por compute unit, para que se programen antes que otras.

La diferencia clave es el alcance de la competencia por fees. Como cada transacción nombra las cuentas en las que escribe, la competencia por priority fees se concentra entre las transacciones que se disputan las mismas cuentas. El ecosistema llama a este comportamiento mercados de fees locales (local fee markets). El método RPC getRecentPrioritizationFees refleja este diseño al filtrar las muestras de fees según las cuentas escribibles que bloqueará una transacción. Durante un mint popular, las fees suben para las transacciones que escriben en las cuentas del mint, mientras que las transacciones no relacionadas casi no se ven afectadas.

Esto afecta la planificación de capacidad. En Ethereum, la actividad de aplicaciones no relacionadas puede subir los costos de tus transacciones, y el diseño de la aplicación no puede evitarlo. En Solana, la presión sobre las fees proviene principalmente de la contención en tus propias cuentas, así que distribuir el estado que se escribe con frecuencia entre más cuentas la reduce.

¿Qué cambia en el diseño de programas?

Un contrato de Solidity es una unidad única de código y almacenamiento, y es inmutable por diseño. Cambiar su lógica después del despliegue requiere un patrón proxy basado en delegatecall, que enruta las llamadas a un contrato de implementación reemplazable. Un contador mínimo en Solidity se ve así:

solidity
Copied
// 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; } }

El programa equivalente en Solana, escrito con Anchor (un framework de programas de Solana ampliamente usado), no almacena estado por sí mismo. El valor del contador vive en una cuenta separada que cada llamada pasa de forma explícita:

rust
Copied
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, }

Una versión completa también incluiría una instrucción de inicialización para crear y fondear la cuenta del contador. Antes de que se ejecute el handler, Anchor valida cada cuenta contra el struct Increment, lo que confirma que la cuenta tiene el tipo y el owner esperados. Esa validación no restringe quién puede llamar a la instrucción. Tal como está escrito, cualquiera puede llamar a increment, así que un programa real agregaría un requisito de firmante o una restricción de dirección derivada para controlar quién puede actualizar el contador.

El comportamiento de actualización por defecto es el inverso. Los programas de Solana desplegados con una upgrade authority son actualizables de forma nativa, y revocar esa autoridad hace que el programa sea inmutable. Por eso, los programas de Solana no necesitan contratos proxy, lo que elimina una categoría de código en la que suelen enfocarse las auditorías de EVM.

Los tokens siguen el mismo patrón. Cada token ERC-20 es su propio contrato que implementa una interfaz estándar, así que una aplicación que admite muchos tokens depende de muchos codebases independientes. En Solana, los tokens se emiten mediante un Token Program compartido, y Token-2022 ofrece una versión extendida que admite funcionalidades opcionales como las fees de transferencia. Cada token es una cuenta mint que registra el supply y los decimales, y el balance de cada titular se almacena en una cuenta de token. Una aplicación que integra estos programas puede admitir cualquier token SPL sin código específico por token.

El manejo de eventos es un área donde la EVM tiene una clara ventaja. Los contratos EVM emiten eventos indexados que eth_getLogs y los indexadores consumen de forma nativa. Solana no tiene un sistema de eventos nativo. Los programas escriben mensajes de log, y las macros de eventos de Anchor codifican datos estructurados en esos logs, que pueden truncarse. Por eso, la indexación en producción en Solana suele depender de infraestructura de streaming como webhooks y streaming gRPC de Solana.

¿Cómo es el stack de cliente?

La elección de la VM también determina el lenguaje y las herramientas. El desarrollo en EVM usa Solidity y un toolchain maduro (Foundry, Hardhat) con amplio soporte para testing, fuzzing y despliegue. El desarrollo en Solana usa Rust y Anchor, con una curva de aprendizaje más pronunciada y un grupo de auditores más pequeño, aunque en crecimiento. Nuestra guía de lenguajes de programación web3 cubre las opciones de lenguaje con más detalle.

La diferencia en los modelos de datos también se nota en el código de cliente. En la EVM, leer el estado significa llamar a una función del contrato, que devuelve datos de su propio almacenamiento. Este ejemplo usa viem:

typescript
Copied
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));

En Solana, leer el estado significa obtener la cuenta que contiene los datos. Un balance de tokens se almacena en una cuenta de token y no en el Token Program, así que el cliente lee esa cuenta directamente. Este ejemplo usa @solana/kit:

typescript
Copied
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);

Este patrón aplica en toda la capa de cliente. Un cliente EVM consulta un contrato, mientras que un cliente de Solana necesita saber qué cuenta contiene cada dato, lo que hace que el layout de cuentas sea parte del diseño de la aplicación.

¿Qué se rompe al portar una app EVM a Solana?

Llevar una aplicación de la EVM a Solana requiere reescribir el código onchain, porque los modelos de cuentas y de ejecución son distintos. Los cambios principales son:

  • msg.sender se convierte en cuentas firmantes. La autorización en Solana proviene de las cuentas marcadas como firmantes en la transacción y verificadas por tu programa, además de los PDAs por los que firma el programa cuando el propio programa tiene la autoridad.
  • Los mappings se convierten en PDAs. Cada clave de un mapping de Solidity se convierte en una cuenta derivada que debe crearse y fondearse con rent antes de su primer uso. La lectura de los datos también cambia, ya que los clientes obtienen cuentas en lugar de consultar el almacenamiento del contrato.
  • El almacenamiento del contrato se convierte en cuentas con tamaño definido y fondeadas con rent. El estado debe asignarse de antemano con un tamaño conocido, y el depósito se devuelve cuando se cierra la cuenta.
  • Los patrones de actualización mediante proxy ya no son necesarios. La upgrade authority del programa reemplaza la configuración de proxy, y revocar esa autoridad hace que el programa sea inmutable.
  • Los eventos se convierten en logs y streaming. Cualquier sistema que consumía eth_getLogs debe reconstruirse en torno al parseo de logs, webhooks o streams de gRPC.
  • Cambian el stack de cliente y el de testing. El código de cliente pasa de viem a @solana/kit, los tests pasan de Foundry al framework de testing de Anchor, y el CI necesita un validador local.

Los equipos que se mueven en la dirección opuesta, de la SVM a la EVM, suelen ganar profundidad de herramientas, indexación nativa de eventos y un mercado de auditores más grande, y renuncian a la ejecución paralela, la confirmación en menos de un segundo y el aislamiento de fees por cuenta.

En ambas direcciones, la curva de aprendizaje del equipo suele ser el mayor costo. Para ingenieros de EVM que pasan a Solana, nuestra hoja de ruta de desarrollo en Solana es un buen punto de partida.

¿Cómo elegir entre la EVM y la SVM?

Lo que estás construyendo
Punto de partida sugerido
Por qué

Una app de consumo de alto throughput (pagos, trading, mints)

SVM

La ejecución paralela y el aislamiento de fees por cuenta mantienen los costos estables bajo tu propia carga

Un protocolo DeFi que se compone con la liquidez existente

EVM

Los protocolos DeFi establecidos, las integraciones y los auditores se concentran en el ecosistema EVM

Un equipo con experiencia en Solidity y productos tolerantes a la latencia

EVM, o una chain EVM paralela

Mantenerse en el stack actual evita una reescritura cuando la carga de trabajo no requiere el throughput de la SVM

¿Cómo apoya Alchemy el desarrollo en EVM y SVM?

Damos soporte a ambos ecosistemas desde una sola plataforma. Nuestros endpoints RPC cubren Ethereum, las principales L2 y el ecosistema EVM en general. Nuestra infraestructura de Solana ofrece llamadas de archivo hasta 20x más rápidas con 99.99% de disponibilidad, y el streaming gRPC proporciona los feeds de datos en tiempo real de los que depende la indexación en Solana. Si estás evaluando infraestructura de Solana, nuestra guía de RPC de Solana cubre qué buscar en un proveedor.

Una API key gratuita te da endpoints para chains EVM y Solana desde un solo dashboard, sin contrato ni compromiso mínimo, y sin necesidad de integrar un proveedor distinto para cada ecosistema.

Background gradient

Construye magia blockchain

Alchemy combina los productos y herramientas de desarrollo Web3 más potentes con recursos, comunidad y un soporte legendario.