Saltar al contenido

Máquina virtual de Ethereum (EVM)

Guía sensible al fork sobre transacciones EVM, llamadas, bytecode, pila, memoria, storage, gas, REVERT, DELEGATECALL, precompilados, recibos y conciliación del estado.

Actualizado

Solo con fines educativos; no constituye asesoramiento de inversión. Invertir puede ocasionar pérdidas.

Respuesta directa

La EVM es la máquina de transición de estado de la capa de ejecución que interpreta bytecode según las reglas de un fork concreto. Con el mismo estado previo válido, transacción o mensaje, entorno de bloque y especificación, los clientes conformes deben calcular el mismo estado posterior o fallo. La EVM no ordena transacciones, aporta finalidad ni iguala la seguridad de todas las cadenas compatibles.

Una transacción firmada externamente es un objeto de nivel superior. La actividad entre contratos son llamadas y marcos anidados, no transacciones independientes. Cada marco tiene código, contador, pila de 256 bits, memoria, calldata, returndata, gas y contexto; el storage persistente pertenece a una cuenta y el transitorio dura una transacción.

Cómo funciona

  1. Fijar cadena y chainId, red, bloque y hash, estado canónico o finalizado, fork, cliente, revisión, estado previo, tipo, bytes firmados, hash y recibo.
  2. Decodificar la envoltura y separar validez previa de ejecución. Verificar firma, remitente, nonce, destino o creación, value, calldata, límite de gas, comisiones, access list y campos específicos. Un rechazo previo no es una transacción incluida que hizo revert.
  3. Construir mensaje y árbol de llamadas. Registrar CALL, STATICCALL, DELEGATECALL, creación y precompilados; caller, dirección de contexto y código, msg.sender, msg.value, value, datos, gas y resultado. “Transacción interna” es una vista de trace.
  4. Trazar contador, pila, memoria, datos, logs, storage persistente y transitorio. CALL usa contexto del callee; DELEGATECALL ejecuta código ajeno en el contexto del caller conservando sender y value; STATICCALL prohíbe modificar estado.
  5. Aplicar gas del fork: intrínseco, opcodes, memoria, accesos cold/warm, llamadas, stipends, precompilados y refunds. Calcular la comisión por separado del value. Una estimación no es garantía.
  6. Resolver resultados por ámbito. RETURN confirma si confirman los ancestros. REVERT revierte el marco y descendientes, devuelve datos y puede conservar gas; un halt excepcional difiere. El padre puede capturar el fallo, por lo que status superior puede ser 1. Un fallo incluido consume nonce y gas.
  7. Conciliar status, gas, logs, dirección creada y retorno con balances, nonces, código, storage, tokens, traces y state root. Reejecutar si procede y auditar proxies, layouts, precompilados, compilador y forks aparte de la finalidad.

Ejemplos resueltos

  • Revert superior y comisión. Una transacción tipo 2 tiene límite 80,000, usa 52,000, base 20 gwei, prioridad máxima 3 gwei y máximo 40 gwei. El precio efectivo es min(40, 20 + 3) = 23 gwei; paga 52,000 * 23 gwei = 0.001196 ETH: se queman 52,000 * 20 gwei = 0.001040 ETH y la prioridad es 52,000 * 3 gwei = 0.000156 ETH. Los 28,000 gas no usados no se cobran. Si revierte, storage, value y logs retroceden, pero nonce y comisión permanecen.
  • Fallo hijo capturado. A empieza con A.x = 5. Llama a B; B escribe B.y = 9, emite un log y ejecuta REVERT. Escritura y log retroceden. A ve success = false, escribe A.x = 7 y termina. El status es 1, queda A.x = 7 y B conserva el valor anterior.
  • Contexto de DELEGATECALL. Un proxy tiene slot0 = 5 y la implementación slot0 = 99. El código suma 7. Mediante DELEGATECALL, el proxy pasa a slot0 = 12 y la implementación queda en slot0 = 99; se usa dirección y storage del proxy y se conservan sender y value.
  • SELFDESTRUCT según fork. Bajo EIP-6780, un contrato existente con 2 ETH ejecuta SELFDESTRUCT hacia B. B recibe 2 ETH y el saldo queda cero, pero cuenta, código y storage no se borran. El borrado solo subsiste si creación y autodestrucción ocurren en la misma transacción.

Riesgos

  • Reejecutar contra cadena, bloque, fork, cliente o estado incorrectos.
  • Tratar un estado no canónico o reorganizado como final.
  • Confundir rechazo previo y revert incluido.
  • Suponer que una simulación pendiente coincidirá con la inclusión.
  • Ignorar revert, halt excepcional u out-of-gas superior.
  • Omitir un fallo hijo capturado.
  • Leer mal contexto, código, caller, sender o value.
  • Corromper un proxy por layout incompatible en DELEGATECALL.
  • Permitir reentrancy o transferencias externas inseguras.
  • Confiar en returndata, flags o errores no validados.
  • Tratar logs o traces como estado final.
  • Calcular mal accesos, memoria o gas reenviado.
  • Aplicar mal refunds, límites, stipends o regla 63/64.
  • Usar precompilado, entrada, coste o fork incorrectos.
  • Confundir storage, memoria y almacenamiento transitorio.
  • Esperar modificaciones dentro de STATICCALL.
  • Aplicar supuestos antiguos de borrado de SELFDESTRUCT.
  • Omitir cambios de implementación, admin o compilador.
  • Ejecutar reglas de cliente divergentes o desactualizadas.
  • Inferir seguridad de consenso, bridge, token o gobierno por compatibilidad EVM.

Errores comunes

  • El código fuente Solidity se ejecuta directamente onchain.
  • Una transacción incluida que revierte no cuesta nada ni cambia el nonce.
  • Status 1 prueba que todas las llamadas internas salieron bien.
  • Un evento o trace es el estado autoritativo.
  • Compatibilidad EVM garantiza opcodes, gas, precompilados, consenso y seguridad idénticos.

Temas relacionados

Fuentes

Navegación

Buscar en la wiki...