[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-1-como-evm-ejecuta-codigo-opcodes-stack-gas":3},{"article":4,"author":54},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":7,"meta_description":16,"focus_keyword":17,"og_image":18,"canonical_url":18,"robots_meta":19,"created_at":15,"updated_at":15,"tags":20,"category_name":34,"related_articles":35},"d8000000-0000-0000-0000-000000000101","a0000000-0000-0000-0000-000000000082","Deep EVM #1: Cómo la EVM Ejecuta Tu Código — Opcodes, Stack y Gas","deep-evm-1-como-evm-ejecuta-codigo-opcodes-stack-gas","Un recorrido de bajo nivel por la Máquina Virtual de Ethereum: cómo los opcodes manipulan el stack, cómo funciona la medición de gas y qué sucede realmente cuando tu transacción se ejecuta.","## La EVM es una máquina de pila\n\nLa Máquina Virtual de Ethereum no es como el procesador x86 de tu portátil. No tiene registros. En cambio, es una **máquina de pila (stack machine)** — cada cálculo empuja hacia o extrae de una pila de 1024 elementos donde cada elemento es una palabra de 256 bits (32 bytes).\n\nCuando llamas a un contrato inteligente, la EVM recibe el bytecode del contrato — una secuencia plana de opcodes de un solo byte — y comienza a ejecutar desde el byte 0. No hay tabla de funciones, ni encabezado ELF, ni paso de enlace. El bytecode es el programa.\n\n```\n\u002F\u002F Solidity:\n\u002F\u002F uint256 result = 2 + 3;\n\n\u002F\u002F Compila a bytecode:\n\u002F\u002F PUSH1 0x02  PUSH1 0x03  ADD\n\n\u002F\u002F Traza del stack:\n\u002F\u002F []           -> PUSH1 0x02 -> [2]\n\u002F\u002F [2]          -> PUSH1 0x03 -> [2, 3]\n\u002F\u002F [2, 3]       -> ADD        -> [5]\n```\n\nCada opcode consume sus operandos desde la parte superior del stack y empuja su resultado de vuelta. El opcode ADD extrae dos valores, los suma y empuja la suma. Esto es fundamentalmente diferente de las arquitecturas basadas en registros donde se especifican registros de origen y destino.\n\n## Categorías de opcodes\n\nLa EVM define aproximadamente 140 opcodes, agrupados en categorías funcionales:\n\n### Aritmética y comparación\n- **ADD, SUB, MUL, DIV, MOD** — Aritmética básica de enteros de 256 bits. Todos cuestan 3 gas (el nivel G_verylow).\n- **SDIV, SMOD** — División y módulo con signo usando complemento a dos.\n- **ADDMOD, MULMOD** — Aritmética modular: `(a + b) % N` y `(a * b) % N` en un solo opcode. Son críticos para operaciones de curvas elípticas y cuestan 8 gas.\n- **EXP** — Exponenciación. Cuesta 10 gas + 50 por byte en el exponente, siendo uno de los opcodes aritméticos más caros.\n- **LT, GT, SLT, SGT, EQ, ISZERO** — Opcodes de comparación que empujan 1 (verdadero) o 0 (falso).\n\n### Operaciones a nivel de bits\n- **AND, OR, XOR, NOT** — Lógica a nivel de bits, 3 gas cada uno.\n- **SHL, SHR, SAR** — Desplazamiento a la izquierda, desplazamiento lógico a la derecha, desplazamiento aritmético a la derecha (añadidos en Constantinople, EIP-145).\n- **BYTE** — Extrae un solo byte de una palabra de 32 bytes.\n\n### Manipulación del stack\n- **POP** — Descarta el elemento superior.\n- **PUSH1 a PUSH32** — Empuja de 1 a 32 bytes de datos inmediatos al stack.\n- **DUP1 a DUP16** — Duplica el enésimo elemento del stack al tope.\n- **SWAP1 a SWAP16** — Intercambia el elemento superior con el enésimo elemento inferior.\n\n### Información del entorno y del bloque\n- **CALLER** (msg.sender), **CALLVALUE** (msg.value), **CALLDATALOAD**, **CALLDATASIZE**, **CALLDATACOPY** — Acceso al contexto de la transacción.\n- **NUMBER**, **TIMESTAMP**, **BASEFEE**, **CHAINID** — Información a nivel de bloque.\n- **BALANCE**, **EXTCODESIZE**, **EXTCODECOPY** — Consultar otras cuentas.\n\n## El calendario de gas\n\nCada opcode tiene un coste de gas. El gas cumple dos propósitos: previene bucles infinitos (el problema de la detención) y establece precios justos para los recursos computacionales.\n\nLos costes de gas se dividen en niveles:\n\n| Nivel | Gas | Ejemplos |\n|-------|-----|----------|\n| Cero | 0 | STOP, RETURN, REVERT |\n| Base | 2 | ADDRESS, ORIGIN, CALLER |\n| Muy bajo | 3 | ADD, SUB, LT, GT, AND, OR, POP |\n| Bajo | 5 | MUL, DIV, MOD |\n| Medio | 8 | ADDMOD, MULMOD, JUMP |\n| Alto | 10 | JUMPI |\n| Especial | variable | SLOAD, SSTORE, CALL, CREATE |\n\nLos opcodes caros son los que tocan el estado:\n\n```\n\u002F\u002F Costes de gas para acceso al estado (post EIP-2929):\n\u002F\u002F SLOAD (frío):   2100 gas\n\u002F\u002F SLOAD (caliente):  100 gas\n\u002F\u002F SSTORE (frío, 0->no-cero): 22100 gas\n\u002F\u002F SSTORE (caliente):  100 gas (+ 20000 si 0->no-cero)\n\u002F\u002F CALL (frío):    2600 gas\n\u002F\u002F CALL (caliente):   100 gas\n```\n\n## Acceso frío vs caliente (EIP-2929)\n\nEIP-2929 (actualización Berlin, abril 2021) introdujo el concepto de una **lista de acceso** — un conjunto por transacción de direcciones y slots de almacenamiento que han sido accedidos.\n\nLa primera vez que accedes a un slot de almacenamiento o dirección externa dentro de una transacción, está \"frío\" y cuesta gas extra. Los accesos posteriores están \"calientes\" y son baratos. Por eso el orden en que lees los slots de almacenamiento importa para la optimización de gas.\n\n```solidity\n\u002F\u002F En Solidity, este patrón es caro:\nfunction mal() external view returns (uint256) {\n    uint256 a = myStorage; \u002F\u002F Primera lectura: 2100 gas (frío)\n    \u002F\u002F ... alguna lógica ...\n    uint256 b = myStorage; \u002F\u002F Segunda lectura: 100 gas (caliente)\n    return a + b;\n}\n\n\u002F\u002F Cachear en memoria:\nfunction bien() external view returns (uint256) {\n    uint256 cached = myStorage; \u002F\u002F 2100 gas (frío), solo una vez\n    return cached + cached;     \u002F\u002F 6 gas (ADD + DUP)\n}\n```\n\n## Flujo de ejecución: Qué sucede en una transacción\n\nCuando envías una transacción que llama a un contrato, esta es la secuencia completa:\n\n1. **Validación de la transacción** — Verificación de nonce, balance >= value + gas * gasPrice, verificación de firma.\n2. **Deducción de gas intrínseco** — 21000 gas por la transacción en sí, más 16 gas por byte de calldata no cero y 4 por byte cero.\n3. **Configuración del contexto** — La EVM crea un contexto de ejecución: código, calldata, caller, value, gas restante.\n4. **El contador de programa comienza en 0** — La EVM lee el opcode en la posición 0 y lo ejecuta.\n5. **Ejecución secuencial** — Cada opcode se ejecuta, el gas se deduce. JUMP y JUMPI permiten flujo de control no lineal, pero solo a posiciones marcadas con JUMPDEST.\n6. **Terminación** — La ejecución termina con STOP (éxito, sin datos de retorno), RETURN (éxito, con datos), REVERT (fallo, estado revertido) o quedándose sin gas.\n7. **Commit o rollback del estado** — En caso de éxito, todos los cambios de estado se confirman. En caso de revert, todos los cambios se revierten.\n\n## El contador de programa y JUMP\n\nEl contador de programa (PC) es un registro implícito que rastrea la posición actual en el bytecode. La mayoría de los opcodes avanzan el PC en 1 (o en 1 + N para opcodes PUSH). Dos opcodes modifican el PC directamente:\n\n- **JUMP** — Extrae un destino del stack, establece el PC a ese valor. El destino debe contener un opcode JUMPDEST o la transacción se revierte.\n- **JUMPI** — Salto condicional. Extrae destino y condición. Si la condición es distinta de cero, salta; de lo contrario continúa secuencialmente.\n\nAsí es como la EVM implementa if\u002Felse, bucles y despacho de funciones.\n\n## Sub-llamadas: CALL, STATICCALL, DELEGATECALL\n\nLos contratos pueden invocar otros contratos usando tres opcodes de llamada:\n\n- **CALL** — Llamada estándar. Crea un nuevo contexto de ejecución con su propio stack y memoria.\n- **STATICCALL** — Llamada de solo lectura (EIP-214). Cualquier opcode que modifique el estado dentro del callee causa un revert inmediato.\n- **DELEGATECALL** — Ejecuta el código del callee pero en el contexto de almacenamiento del caller. msg.sender y msg.value se preservan. Así funcionan los patrones de proxy y las bibliotecas.\n\n## Implicaciones prácticas para MEV\n\nSi estás construyendo bots de MEV, entender la EVM a nivel de opcode no es opcional — es un requisito competitivo. Cada unidad de gas ahorrada en la ejecución de tu bot es margen de beneficio.\n\n- **Simula antes de enviar** — Usa `eth_call` o una EVM local (revm, EVMONE) para trazar la ejecución.\n- **Minimiza accesos fríos** — Pre-calienta slots de almacenamiento vía listas de acceso (EIP-2930).\n- **Usa STATICCALL para lecturas** — Ligeramente más barato y garantiza que no muta estado.\n- **Conoce tus costes de opcodes** — Un solo SLOAD mal ubicado puede costar 2100 gas.\n\n## Conclusión\n\nLa EVM es elegante en su simplicidad: una máquina de pila con palabras de 256 bits, un formato de bytecode plano y un sistema de medición de gas que pone precio a cada operación. Entender esta base — opcodes, el stack y el gas — es el prerrequisito para todo lo que sigue en esta serie: layout de memoria, optimización de almacenamiento, primitivas de seguridad, y finalmente escribir Yul y Huff crudos.","\u003Ch2 id=\"la-evm-es-una-m-quina-de-pila\">La EVM es una máquina de pila\u003C\u002Fh2>\n\u003Cp>La Máquina Virtual de Ethereum no es como el procesador x86 de tu portátil. No tiene registros. En cambio, es una \u003Cstrong>máquina de pila (stack machine)\u003C\u002Fstrong> — cada cálculo empuja hacia o extrae de una pila de 1024 elementos donde cada elemento es una palabra de 256 bits (32 bytes).\u003C\u002Fp>\n\u003Cp>Cuando llamas a un contrato inteligente, la EVM recibe el bytecode del contrato — una secuencia plana de opcodes de un solo byte — y comienza a ejecutar desde el byte 0. No hay tabla de funciones, ni encabezado ELF, ni paso de enlace. El bytecode es el programa.\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002F\u002F Solidity:\n\u002F\u002F uint256 result = 2 + 3;\n\n\u002F\u002F Compila a bytecode:\n\u002F\u002F PUSH1 0x02  PUSH1 0x03  ADD\n\n\u002F\u002F Traza del stack:\n\u002F\u002F []           -&gt; PUSH1 0x02 -&gt; [2]\n\u002F\u002F [2]          -&gt; PUSH1 0x03 -&gt; [2, 3]\n\u002F\u002F [2, 3]       -&gt; ADD        -&gt; [5]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Cada opcode consume sus operandos desde la parte superior del stack y empuja su resultado de vuelta. El opcode ADD extrae dos valores, los suma y empuja la suma. Esto es fundamentalmente diferente de las arquitecturas basadas en registros donde se especifican registros de origen y destino.\u003C\u002Fp>\n\u003Ch2 id=\"categor-as-de-opcodes\">Categorías de opcodes\u003C\u002Fh2>\n\u003Cp>La EVM define aproximadamente 140 opcodes, agrupados en categorías funcionales:\u003C\u002Fp>\n\u003Ch3>Aritmética y comparación\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>\u003Cstrong>ADD, SUB, MUL, DIV, MOD\u003C\u002Fstrong> — Aritmética básica de enteros de 256 bits. Todos cuestan 3 gas (el nivel G_verylow).\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SDIV, SMOD\u003C\u002Fstrong> — División y módulo con signo usando complemento a dos.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>ADDMOD, MULMOD\u003C\u002Fstrong> — Aritmética modular: \u003Ccode>(a + b) % N\u003C\u002Fcode> y \u003Ccode>(a * b) % N\u003C\u002Fcode> en un solo opcode. Son críticos para operaciones de curvas elípticas y cuestan 8 gas.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>EXP\u003C\u002Fstrong> — Exponenciación. Cuesta 10 gas + 50 por byte en el exponente, siendo uno de los opcodes aritméticos más caros.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>LT, GT, SLT, SGT, EQ, ISZERO\u003C\u002Fstrong> — Opcodes de comparación que empujan 1 (verdadero) o 0 (falso).\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Operaciones a nivel de bits\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>\u003Cstrong>AND, OR, XOR, NOT\u003C\u002Fstrong> — Lógica a nivel de bits, 3 gas cada uno.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SHL, SHR, SAR\u003C\u002Fstrong> — Desplazamiento a la izquierda, desplazamiento lógico a la derecha, desplazamiento aritmético a la derecha (añadidos en Constantinople, EIP-145).\u003C\u002Fli>\n\u003Cli>\u003Cstrong>BYTE\u003C\u002Fstrong> — Extrae un solo byte de una palabra de 32 bytes.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Manipulación del stack\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>\u003Cstrong>POP\u003C\u002Fstrong> — Descarta el elemento superior.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>PUSH1 a PUSH32\u003C\u002Fstrong> — Empuja de 1 a 32 bytes de datos inmediatos al stack.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>DUP1 a DUP16\u003C\u002Fstrong> — Duplica el enésimo elemento del stack al tope.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SWAP1 a SWAP16\u003C\u002Fstrong> — Intercambia el elemento superior con el enésimo elemento inferior.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Información del entorno y del bloque\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>\u003Cstrong>CALLER\u003C\u002Fstrong> (msg.sender), \u003Cstrong>CALLVALUE\u003C\u002Fstrong> (msg.value), \u003Cstrong>CALLDATALOAD\u003C\u002Fstrong>, \u003Cstrong>CALLDATASIZE\u003C\u002Fstrong>, \u003Cstrong>CALLDATACOPY\u003C\u002Fstrong> — Acceso al contexto de la transacción.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>NUMBER\u003C\u002Fstrong>, \u003Cstrong>TIMESTAMP\u003C\u002Fstrong>, \u003Cstrong>BASEFEE\u003C\u002Fstrong>, \u003Cstrong>CHAINID\u003C\u002Fstrong> — Información a nivel de bloque.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>BALANCE\u003C\u002Fstrong>, \u003Cstrong>EXTCODESIZE\u003C\u002Fstrong>, \u003Cstrong>EXTCODECOPY\u003C\u002Fstrong> — Consultar otras cuentas.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"el-calendario-de-gas\">El calendario de gas\u003C\u002Fh2>\n\u003Cp>Cada opcode tiene un coste de gas. El gas cumple dos propósitos: previene bucles infinitos (el problema de la detención) y establece precios justos para los recursos computacionales.\u003C\u002Fp>\n\u003Cp>Los costes de gas se dividen en niveles:\u003C\u002Fp>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Nivel\u003C\u002Fth>\u003Cth>Gas\u003C\u002Fth>\u003Cth>Ejemplos\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>Cero\u003C\u002Ftd>\u003Ctd>0\u003C\u002Ftd>\u003Ctd>STOP, RETURN, REVERT\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Base\u003C\u002Ftd>\u003Ctd>2\u003C\u002Ftd>\u003Ctd>ADDRESS, ORIGIN, CALLER\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Muy bajo\u003C\u002Ftd>\u003Ctd>3\u003C\u002Ftd>\u003Ctd>ADD, SUB, LT, GT, AND, OR, POP\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Bajo\u003C\u002Ftd>\u003Ctd>5\u003C\u002Ftd>\u003Ctd>MUL, DIV, MOD\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Medio\u003C\u002Ftd>\u003Ctd>8\u003C\u002Ftd>\u003Ctd>ADDMOD, MULMOD, JUMP\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Alto\u003C\u002Ftd>\u003Ctd>10\u003C\u002Ftd>\u003Ctd>JUMPI\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Especial\u003C\u002Ftd>\u003Ctd>variable\u003C\u002Ftd>\u003Ctd>SLOAD, SSTORE, CALL, CREATE\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Los opcodes caros son los que tocan el estado:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002F\u002F Costes de gas para acceso al estado (post EIP-2929):\n\u002F\u002F SLOAD (frío):   2100 gas\n\u002F\u002F SLOAD (caliente):  100 gas\n\u002F\u002F SSTORE (frío, 0-&gt;no-cero): 22100 gas\n\u002F\u002F SSTORE (caliente):  100 gas (+ 20000 si 0-&gt;no-cero)\n\u002F\u002F CALL (frío):    2600 gas\n\u002F\u002F CALL (caliente):   100 gas\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"acceso-fr-o-vs-caliente-eip-2929\">Acceso frío vs caliente (EIP-2929)\u003C\u002Fh2>\n\u003Cp>EIP-2929 (actualización Berlin, abril 2021) introdujo el concepto de una \u003Cstrong>lista de acceso\u003C\u002Fstrong> — un conjunto por transacción de direcciones y slots de almacenamiento que han sido accedidos.\u003C\u002Fp>\n\u003Cp>La primera vez que accedes a un slot de almacenamiento o dirección externa dentro de una transacción, está “frío” y cuesta gas extra. Los accesos posteriores están “calientes” y son baratos. Por eso el orden en que lees los slots de almacenamiento importa para la optimización de gas.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F En Solidity, este patrón es caro:\nfunction mal() external view returns (uint256) {\n    uint256 a = myStorage; \u002F\u002F Primera lectura: 2100 gas (frío)\n    \u002F\u002F ... alguna lógica ...\n    uint256 b = myStorage; \u002F\u002F Segunda lectura: 100 gas (caliente)\n    return a + b;\n}\n\n\u002F\u002F Cachear en memoria:\nfunction bien() external view returns (uint256) {\n    uint256 cached = myStorage; \u002F\u002F 2100 gas (frío), solo una vez\n    return cached + cached;     \u002F\u002F 6 gas (ADD + DUP)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"flujo-de-ejecuci-n-qu-sucede-en-una-transacci-n\">Flujo de ejecución: Qué sucede en una transacción\u003C\u002Fh2>\n\u003Cp>Cuando envías una transacción que llama a un contrato, esta es la secuencia completa:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Validación de la transacción\u003C\u002Fstrong> — Verificación de nonce, balance &gt;= value + gas * gasPrice, verificación de firma.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Deducción de gas intrínseco\u003C\u002Fstrong> — 21000 gas por la transacción en sí, más 16 gas por byte de calldata no cero y 4 por byte cero.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Configuración del contexto\u003C\u002Fstrong> — La EVM crea un contexto de ejecución: código, calldata, caller, value, gas restante.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>El contador de programa comienza en 0\u003C\u002Fstrong> — La EVM lee el opcode en la posición 0 y lo ejecuta.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Ejecución secuencial\u003C\u002Fstrong> — Cada opcode se ejecuta, el gas se deduce. JUMP y JUMPI permiten flujo de control no lineal, pero solo a posiciones marcadas con JUMPDEST.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Terminación\u003C\u002Fstrong> — La ejecución termina con STOP (éxito, sin datos de retorno), RETURN (éxito, con datos), REVERT (fallo, estado revertido) o quedándose sin gas.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Commit o rollback del estado\u003C\u002Fstrong> — En caso de éxito, todos los cambios de estado se confirman. En caso de revert, todos los cambios se revierten.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"el-contador-de-programa-y-jump\">El contador de programa y JUMP\u003C\u002Fh2>\n\u003Cp>El contador de programa (PC) es un registro implícito que rastrea la posición actual en el bytecode. La mayoría de los opcodes avanzan el PC en 1 (o en 1 + N para opcodes PUSH). Dos opcodes modifican el PC directamente:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>JUMP\u003C\u002Fstrong> — Extrae un destino del stack, establece el PC a ese valor. El destino debe contener un opcode JUMPDEST o la transacción se revierte.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>JUMPI\u003C\u002Fstrong> — Salto condicional. Extrae destino y condición. Si la condición es distinta de cero, salta; de lo contrario continúa secuencialmente.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Así es como la EVM implementa if\u002Felse, bucles y despacho de funciones.\u003C\u002Fp>\n\u003Ch2 id=\"sub-llamadas-call-staticcall-delegatecall\">Sub-llamadas: CALL, STATICCALL, DELEGATECALL\u003C\u002Fh2>\n\u003Cp>Los contratos pueden invocar otros contratos usando tres opcodes de llamada:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>CALL\u003C\u002Fstrong> — Llamada estándar. Crea un nuevo contexto de ejecución con su propio stack y memoria.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>STATICCALL\u003C\u002Fstrong> — Llamada de solo lectura (EIP-214). Cualquier opcode que modifique el estado dentro del callee causa un revert inmediato.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>DELEGATECALL\u003C\u002Fstrong> — Ejecuta el código del callee pero en el contexto de almacenamiento del caller. msg.sender y msg.value se preservan. Así funcionan los patrones de proxy y las bibliotecas.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"implicaciones-pr-cticas-para-mev\">Implicaciones prácticas para MEV\u003C\u002Fh2>\n\u003Cp>Si estás construyendo bots de MEV, entender la EVM a nivel de opcode no es opcional — es un requisito competitivo. Cada unidad de gas ahorrada en la ejecución de tu bot es margen de beneficio.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Simula antes de enviar\u003C\u002Fstrong> — Usa \u003Ccode>eth_call\u003C\u002Fcode> o una EVM local (revm, EVMONE) para trazar la ejecución.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Minimiza accesos fríos\u003C\u002Fstrong> — Pre-calienta slots de almacenamiento vía listas de acceso (EIP-2930).\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Usa STATICCALL para lecturas\u003C\u002Fstrong> — Ligeramente más barato y garantiza que no muta estado.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Conoce tus costes de opcodes\u003C\u002Fstrong> — Un solo SLOAD mal ubicado puede costar 2100 gas.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"conclusi-n\">Conclusión\u003C\u002Fh2>\n\u003Cp>La EVM es elegante en su simplicidad: una máquina de pila con palabras de 256 bits, un formato de bytecode plano y un sistema de medición de gas que pone precio a cada operación. Entender esta base — opcodes, el stack y el gas — es el prerrequisito para todo lo que sigue en esta serie: layout de memoria, optimización de almacenamiento, primitivas de seguridad, y finalmente escribir Yul y Huff crudos.\u003C\u002Fp>\n","es","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:31.063801Z","Un recorrido de bajo nivel por la Máquina Virtual de Ethereum: opcodes, operaciones de stack, medición de gas y acceso frío vs caliente.","EVM opcodes",null,"index, follow",[21,26,30],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000020","Gas Optimization","gas-optimization",{"id":31,"name":32,"slug":33,"created_at":25},"c0000000-0000-0000-0000-000000000014","Solidity","solidity","Blockchain",[36,42,48],{"id":37,"title":38,"slug":39,"excerpt":40,"locale":12,"category_name":34,"published_at":41},"d0000000-0000-0000-0000-000000000614","La capa de interoperabilidad de Ethereum: Como 55+ L2s se convierten en una sola cadena","capa-interoperabilidad-ethereum-55-l2s-una-sola-cadena","Ethereum tiene 55+ rollups Layer 2, fragmentando la liquidez y la experiencia del usuario. La capa de interoperabilidad de Ethereum — combinando mensajeria cross-rollup, secuenciadores compartidos y based rollups — busca unificarlos en una red componible unica.","2026-03-28T10:44:45.451917Z",{"id":43,"title":44,"slug":45,"excerpt":46,"locale":12,"category_name":34,"published_at":47},"d0000000-0000-0000-0000-000000000613","Pruebas ZK mas alla de los rollups: Inferencia de IA verificable en Ethereum","pruebas-zk-mas-alla-rollups-inferencia-ia-verificable-ethereum","Las pruebas de conocimiento cero ya no son solo una herramienta de escalabilidad. En 2026, zkML permite la inferencia de IA verificable on-chain, los coprocesadores ZK mueven el calculo pesado off-chain con verificacion on-chain, y nuevos sistemas de prueba como SP1 y Jolt lo hacen practico.","2026-03-28T10:44:45.446211Z",{"id":49,"title":50,"slug":51,"excerpt":52,"locale":12,"category_name":34,"published_at":53},"d0000000-0000-0000-0000-000000000590","EIP-7702 en la practica: construir flujos de cuenta inteligente despues de Pectra","eip-7702-en-la-practica-construir-flujos-cuenta-inteligente-despues-pectra","EIP-7702 permite a cualquier EOA de Ethereum actuar temporalmente como contrato inteligente en una sola transaccion. Asi se implementan transacciones por lotes, patrocinio de gas y recuperacion social con la nueva primitiva de account abstraction.","2026-03-28T10:44:43.986612Z",{"id":13,"name":55,"slug":56,"bio":57,"photo_url":18,"linkedin":18,"role":58,"created_at":59,"updated_at":59},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]