[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-10-gestion-stack-huff-dup-swap":3},{"article":4,"author":55},{"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":16,"meta_description":17,"focus_keyword":18,"og_image":19,"canonical_url":19,"robots_meta":20,"created_at":15,"updated_at":15,"tags":21,"category_name":35,"related_articles":36},"d8000000-0000-0000-0000-000000000110","a0000000-0000-0000-0000-000000000082","Deep EVM #10: Gestión del Stack en Huff — takes(), returns() y el Arte del dup\u002Fswap","deep-evm-10-gestion-stack-huff-dup-swap","Domina la disciplina del stack en Huff: anotaciones takes\u002Freturns, patrones dup\u002Fswap, técnicas de rotación del stack y herramientas de visualización para depurar contratos complejos.","## La disciplina del stack\n\nEn Huff, no hay variables — todo vive en el stack. Cada macro declara su contrato de stack con `takes(N) returns(M)`: consume N elementos y produce M. Esta anotación no es ejecutada por la EVM — es documentación que el compilador Huff verifica estáticamente.\n\nEl stack de la EVM tiene 1024 posiciones, pero solo las 16 superiores son accesibles vía DUP y SWAP. Esto significa que la planificación del layout del stack es una habilidad crítica.\n\n## Patrones fundamentales de dup\u002Fswap\n\n### DUP: copiar un elemento del stack\n```huff\n\u002F\u002F DUP1: duplicar el tope\n\u002F\u002F Stack: [a] -> [a, a]\n\n\u002F\u002F DUP2: copiar el segundo elemento\n\u002F\u002F Stack: [a, b] -> [b, a, b]\n\n\u002F\u002F DUP3: copiar el tercero\n\u002F\u002F Stack: [a, b, c] -> [c, a, b, c]\n```\n\nRegla: DUPn copia el elemento en posición n (contando desde 1 en el tope) y lo empuja al tope.\n\n### SWAP: intercambiar elementos\n```huff\n\u002F\u002F SWAP1: intercambiar los dos superiores\n\u002F\u002F Stack: [a, b] -> [b, a]\n\n\u002F\u002F SWAP2: intercambiar tope con el tercero\n\u002F\u002F Stack: [a, b, c] -> [c, b, a]\n```\n\n## Rotación del stack\n\nUno de los patrones más comunes es la rotación — reorganizar elementos sin perder ninguno:\n\n```huff\n\u002F\u002F Rotar 3 elementos: [a, b, c] -> [c, a, b]\n#define macro ROT3() = takes(3) returns(3) {\n    swap2   \u002F\u002F [c, b, a]\n    swap1   \u002F\u002F [c, a, b]\n}\n\n\u002F\u002F Rotar inverso: [a, b, c] -> [b, c, a]\n#define macro RROT3() = takes(3) returns(3) {\n    swap1   \u002F\u002F [b, a, c]\n    swap2   \u002F\u002F [b, c, a]\n}\n```\n\n## Ejemplo práctico: implementación de transferencia\n\nVeamos cómo gestionar el stack para una función transfer ERC-20:\n\n```huff\n#define macro TRANSFER() = takes(0) returns(0) {\n    \u002F\u002F Leer parámetros del calldata\n    0x04 calldataload       \u002F\u002F [to]\n    0x24 calldataload       \u002F\u002F [amount, to]\n    \n    \u002F\u002F Verificar amount > 0\n    dup1 iszero             \u002F\u002F [amount==0, amount, to]\n    err jumpi               \u002F\u002F [amount, to]\n    \n    \u002F\u002F Leer balance del sender\n    caller                  \u002F\u002F [sender, amount, to]\n    dup1                    \u002F\u002F [sender, sender, amount, to]\n    BALANCE_SLOT()          \u002F\u002F [slot, sender, amount, to]\n    sload                   \u002F\u002F [senderBal, sender, amount, to]\n    \n    \u002F\u002F Verificar balance suficiente\n    dup1                    \u002F\u002F [senderBal, senderBal, sender, amount, to]\n    dup4                    \u002F\u002F [amount, senderBal, senderBal, sender, amount, to]\n    gt                      \u002F\u002F [amount>bal, senderBal, sender, amount, to]\n    err jumpi               \u002F\u002F [senderBal, sender, amount, to]\n    \n    \u002F\u002F Restar del sender\n    dup3                    \u002F\u002F [amount, senderBal, sender, amount, to]\n    swap1 sub               \u002F\u002F [newSenderBal, sender, amount, to]\n    dup2                    \u002F\u002F [sender, newSenderBal, sender, amount, to]\n    BALANCE_SLOT()          \u002F\u002F [slot, newSenderBal, sender, amount, to]\n    sstore                  \u002F\u002F [sender, amount, to]\n    \n    \u002F\u002F Sumar al receptor\n    swap2                   \u002F\u002F [to, amount, sender]\n    dup1                    \u002F\u002F [to, to, amount, sender]\n    BALANCE_SLOT()          \u002F\u002F [slot, to, amount, sender]\n    dup1 sload              \u002F\u002F [toBal, slot, to, amount, sender]\n    dup4 add                \u002F\u002F [newToBal, slot, to, amount, sender]\n    swap1 sstore            \u002F\u002F [to, amount, sender]\n    \n    \u002F\u002F Emitir evento Transfer\n    swap1                   \u002F\u002F [amount, to, sender]\n    0x00 mstore             \u002F\u002F [to, sender]\n    swap1                   \u002F\u002F [sender, to]\n    [TRANSFER_SIG]          \u002F\u002F [sig, sender, to]\n    0x20 0x00               \u002F\u002F [0, 32, sig, sender, to]\n    log3                    \u002F\u002F []\n    \n    \u002F\u002F Retornar true\n    0x01 0x00 mstore\n    0x20 0x00 return\n    \n    err:\n    0x00 0x00 revert\n}\n```\n\n## Herramientas de visualización\n\nDebug del stack en Huff requiere herramientas:\n\n1. **Comentarios de stack** — Documenta el estado del stack después de cada opcode con `\u002F\u002F [elem1, elem2, ...]`\n2. **Foundry traces** — `forge test -vvvv` muestra trazas de opcodes con el stack\n3. **evm.codes playground** — Visualizador interactivo del stack paso a paso\n4. **huffc --print-stack** — Algunas versiones del compilador pueden analizar el flujo del stack\n\n## Patrones anti-stack-overflow\n\nCon funciones complejas, el stack puede crecer peligrosamente:\n\n```huff\n\u002F\u002F Patrón: almacenar temporalmente en memoria\n#define macro COMPLEX_CALC() = takes(5) returns(1) {\n    \u002F\u002F Demasiados valores en el stack? Almacena en memoria\n    0x00 mstore     \u002F\u002F Guardar primer valor en mem[0x00]\n    0x20 mstore     \u002F\u002F Guardar segundo en mem[0x20]\n    \u002F\u002F ... calcular con los 3 restantes ...\n    0x00 mload      \u002F\u002F Recuperar cuando sea necesario\n}\n```\n\nCada MSTORE cuesta 3 gas + posible expansión de memoria. Pero si la alternativa es DUP16+ (que no existe), no hay otra opción.\n\n## Errores comunes\n\n1. **Stack underflow** — Intentar POP de un stack vacío causa revert\n2. **Stack imbalance** — Una macro que deja elementos extra causa bugs en el caller\n3. **Olvidar POP** — Valores huérfanos en el stack acumulan basura\n4. **DUP\u002FSWAP incorrecto** — El off-by-one más costoso: DUP2 vs DUP3 puede significar leer el valor equivocado\n\n## Conclusión\n\nLa gestión del stack es el 80% del trabajo en Huff. Cada macro debe tener un contrato de stack claro, comentarios de estado en cada opcode, y pruebas exhaustivas. Dominar dup\u002Fswap\u002Frot es la diferencia entre un contrato Huff funcional y uno con bugs sutiles e impredecibles.","\u003Ch2 id=\"la-disciplina-del-stack\">La disciplina del stack\u003C\u002Fh2>\n\u003Cp>En Huff, no hay variables — todo vive en el stack. Cada macro declara su contrato de stack con \u003Ccode>takes(N) returns(M)\u003C\u002Fcode>: consume N elementos y produce M. Esta anotación no es ejecutada por la EVM — es documentación que el compilador Huff verifica estáticamente.\u003C\u002Fp>\n\u003Cp>El stack de la EVM tiene 1024 posiciones, pero solo las 16 superiores son accesibles vía DUP y SWAP. Esto significa que la planificación del layout del stack es una habilidad crítica.\u003C\u002Fp>\n\u003Ch2 id=\"patrones-fundamentales-de-dup-swap\">Patrones fundamentales de dup\u002Fswap\u003C\u002Fh2>\n\u003Ch3>DUP: copiar un elemento del stack\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F DUP1: duplicar el tope\n\u002F\u002F Stack: [a] -&gt; [a, a]\n\n\u002F\u002F DUP2: copiar el segundo elemento\n\u002F\u002F Stack: [a, b] -&gt; [b, a, b]\n\n\u002F\u002F DUP3: copiar el tercero\n\u002F\u002F Stack: [a, b, c] -&gt; [c, a, b, c]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Regla: DUPn copia el elemento en posición n (contando desde 1 en el tope) y lo empuja al tope.\u003C\u002Fp>\n\u003Ch3>SWAP: intercambiar elementos\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F SWAP1: intercambiar los dos superiores\n\u002F\u002F Stack: [a, b] -&gt; [b, a]\n\n\u002F\u002F SWAP2: intercambiar tope con el tercero\n\u002F\u002F Stack: [a, b, c] -&gt; [c, b, a]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"rotaci-n-del-stack\">Rotación del stack\u003C\u002Fh2>\n\u003Cp>Uno de los patrones más comunes es la rotación — reorganizar elementos sin perder ninguno:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Rotar 3 elementos: [a, b, c] -&gt; [c, a, b]\n#define macro ROT3() = takes(3) returns(3) {\n    swap2   \u002F\u002F [c, b, a]\n    swap1   \u002F\u002F [c, a, b]\n}\n\n\u002F\u002F Rotar inverso: [a, b, c] -&gt; [b, c, a]\n#define macro RROT3() = takes(3) returns(3) {\n    swap1   \u002F\u002F [b, a, c]\n    swap2   \u002F\u002F [b, c, a]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"ejemplo-pr-ctico-implementaci-n-de-transferencia\">Ejemplo práctico: implementación de transferencia\u003C\u002Fh2>\n\u003Cp>Veamos cómo gestionar el stack para una función transfer ERC-20:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro TRANSFER() = takes(0) returns(0) {\n    \u002F\u002F Leer parámetros del calldata\n    0x04 calldataload       \u002F\u002F [to]\n    0x24 calldataload       \u002F\u002F [amount, to]\n    \n    \u002F\u002F Verificar amount &gt; 0\n    dup1 iszero             \u002F\u002F [amount==0, amount, to]\n    err jumpi               \u002F\u002F [amount, to]\n    \n    \u002F\u002F Leer balance del sender\n    caller                  \u002F\u002F [sender, amount, to]\n    dup1                    \u002F\u002F [sender, sender, amount, to]\n    BALANCE_SLOT()          \u002F\u002F [slot, sender, amount, to]\n    sload                   \u002F\u002F [senderBal, sender, amount, to]\n    \n    \u002F\u002F Verificar balance suficiente\n    dup1                    \u002F\u002F [senderBal, senderBal, sender, amount, to]\n    dup4                    \u002F\u002F [amount, senderBal, senderBal, sender, amount, to]\n    gt                      \u002F\u002F [amount&gt;bal, senderBal, sender, amount, to]\n    err jumpi               \u002F\u002F [senderBal, sender, amount, to]\n    \n    \u002F\u002F Restar del sender\n    dup3                    \u002F\u002F [amount, senderBal, sender, amount, to]\n    swap1 sub               \u002F\u002F [newSenderBal, sender, amount, to]\n    dup2                    \u002F\u002F [sender, newSenderBal, sender, amount, to]\n    BALANCE_SLOT()          \u002F\u002F [slot, newSenderBal, sender, amount, to]\n    sstore                  \u002F\u002F [sender, amount, to]\n    \n    \u002F\u002F Sumar al receptor\n    swap2                   \u002F\u002F [to, amount, sender]\n    dup1                    \u002F\u002F [to, to, amount, sender]\n    BALANCE_SLOT()          \u002F\u002F [slot, to, amount, sender]\n    dup1 sload              \u002F\u002F [toBal, slot, to, amount, sender]\n    dup4 add                \u002F\u002F [newToBal, slot, to, amount, sender]\n    swap1 sstore            \u002F\u002F [to, amount, sender]\n    \n    \u002F\u002F Emitir evento Transfer\n    swap1                   \u002F\u002F [amount, to, sender]\n    0x00 mstore             \u002F\u002F [to, sender]\n    swap1                   \u002F\u002F [sender, to]\n    [TRANSFER_SIG]          \u002F\u002F [sig, sender, to]\n    0x20 0x00               \u002F\u002F [0, 32, sig, sender, to]\n    log3                    \u002F\u002F []\n    \n    \u002F\u002F Retornar true\n    0x01 0x00 mstore\n    0x20 0x00 return\n    \n    err:\n    0x00 0x00 revert\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"herramientas-de-visualizaci-n\">Herramientas de visualización\u003C\u002Fh2>\n\u003Cp>Debug del stack en Huff requiere herramientas:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Comentarios de stack\u003C\u002Fstrong> — Documenta el estado del stack después de cada opcode con \u003Ccode>\u002F\u002F [elem1, elem2, ...]\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Foundry traces\u003C\u002Fstrong> — \u003Ccode>forge test -vvvv\u003C\u002Fcode> muestra trazas de opcodes con el stack\u003C\u002Fli>\n\u003Cli>\u003Cstrong>evm.codes playground\u003C\u002Fstrong> — Visualizador interactivo del stack paso a paso\u003C\u002Fli>\n\u003Cli>\u003Cstrong>huffc –print-stack\u003C\u002Fstrong> — Algunas versiones del compilador pueden analizar el flujo del stack\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"patrones-anti-stack-overflow\">Patrones anti-stack-overflow\u003C\u002Fh2>\n\u003Cp>Con funciones complejas, el stack puede crecer peligrosamente:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Patrón: almacenar temporalmente en memoria\n#define macro COMPLEX_CALC() = takes(5) returns(1) {\n    \u002F\u002F Demasiados valores en el stack? Almacena en memoria\n    0x00 mstore     \u002F\u002F Guardar primer valor en mem[0x00]\n    0x20 mstore     \u002F\u002F Guardar segundo en mem[0x20]\n    \u002F\u002F ... calcular con los 3 restantes ...\n    0x00 mload      \u002F\u002F Recuperar cuando sea necesario\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Cada MSTORE cuesta 3 gas + posible expansión de memoria. Pero si la alternativa es DUP16+ (que no existe), no hay otra opción.\u003C\u002Fp>\n\u003Ch2 id=\"errores-comunes\">Errores comunes\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\u003Cstrong>Stack underflow\u003C\u002Fstrong> — Intentar POP de un stack vacío causa revert\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Stack imbalance\u003C\u002Fstrong> — Una macro que deja elementos extra causa bugs en el caller\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Olvidar POP\u003C\u002Fstrong> — Valores huérfanos en el stack acumulan basura\u003C\u002Fli>\n\u003Cli>\u003Cstrong>DUP\u002FSWAP incorrecto\u003C\u002Fstrong> — El off-by-one más costoso: DUP2 vs DUP3 puede significar leer el valor equivocado\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"conclusi-n\">Conclusión\u003C\u002Fh2>\n\u003Cp>La gestión del stack es el 80% del trabajo en Huff. Cada macro debe tener un contrato de stack claro, comentarios de estado en cada opcode, y pruebas exhaustivas. Dominar dup\u002Fswap\u002Frot es la diferencia entre un contrato Huff funcional y uno con bugs sutiles e impredecibles.\u003C\u002Fp>\n","es","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:31.368510Z","Deep EVM #10: Gestión del Stack en Huff — dup, swap y Disciplina del Stack","Domina la gestión del stack en Huff: anotaciones takes\u002Freturns, patrones dup\u002Fswap, rotación y herramientas de depuración para contratos EVM.","huff gestión stack evm",null,"index, follow",[22,27,31],{"id":23,"name":24,"slug":25,"created_at":26},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":28,"name":29,"slug":30,"created_at":26},"c0000000-0000-0000-0000-000000000020","Gas Optimization","gas-optimization",{"id":32,"name":33,"slug":34,"created_at":26},"c0000000-0000-0000-0000-000000000017","Huff","huff","Blockchain",[37,43,49],{"id":38,"title":39,"slug":40,"excerpt":41,"locale":12,"category_name":35,"published_at":42},"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":44,"title":45,"slug":46,"excerpt":47,"locale":12,"category_name":35,"published_at":48},"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":50,"title":51,"slug":52,"excerpt":53,"locale":12,"category_name":35,"published_at":54},"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":56,"slug":57,"bio":58,"photo_url":19,"linkedin":19,"role":59,"created_at":60,"updated_at":60},"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"]