¿Cómo funcionan las llamadas a contratos en Yul?
Escrito por Mark Jonathas
Yul es un lenguaje de programación intermedio que se puede usar para escribir una forma de lenguaje ensamblador dentro de smart contracts. Ahora que entiendes la sintaxis, el storage y cómo funciona la memoria en Yul, es momento de llamar contratos.
¿Cómo funcionan las llamadas a contratos en yul?
En la sección final de esta serie veremos cómo funcionan las llamadas a contratos en Yul. Antes de ver algunos ejemplos, necesitamos aprender algunas operaciones más de Yul. Veamos.
Bien, ahora veamos algunos contratos nuevos para estos ejemplos. Primero, veamos el contrato que vamos a llamar.
Este contrato tiene dos variables de storage, var1 y var2, que se almacenan en los storage slots 1 y 2 respectivamente.
La función a() requiere que el usuario envíe al menos 1 ether al contrato, de lo contrario revierte.
Luego, la función a() actualiza var1 y var2 y las retorna.
La función b() simplemente lee var1 y var2 y las retorna.
Antes de pasar a nuestro contrato que llama al contrato CallMe, necesitamos tomarnos un momento para entender los function selectors.
Veamos el siguiente calldata para una transacción 0x773d45e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002.
Los primeros 4 bytes del calldata son lo que se conoce como el function selector (0x773d45e0). Así es como el EVM sabe qué función quieres llamar. El function selector se obtiene tomando los primeros 4 bytes del hash de un string con la firma de la función.
Entonces, la firma de la función a() sería a(uint256,uint256).
Tomando el hash de este string obtenemos: 0x773d45e097aa76a22159880d254a5f1db8365bc2d0f0987a82bda7dfd3b9c8aa.
Al ver los primeros 4 bytes, vemos que es igual a 0x773d45e0.
Nota la ausencia de espacios en la firma. Esto es importante porque agregar espacios nos daría un hash completamente distinto. No tienes que preocuparte por obtener los selectors para nuestros ejemplos de código, yo los proporcionaré.
Empecemos viendo el storage layout.
Nota cómo var1 y var2 tienen el mismo layout que el contrato CallMe. Recordarás que mencioné que el layout debe ser el mismo que el de nuestro otro contrato para que delegatecall() funcione correctamente.
Cumplimos con esos requisitos y podemos tener otras variables (selectorA y selectorB) siempre que nuestras nuevas variables se agreguen al final. Esto evita colisiones de storage.
Ahora estamos listos para hacer nuestra primera llamada a un contrato.
Cómo usar staticcall() en yul
Empecemos con algo simple, staticcall(). Aquí está nuestra función:
Esto es lo que está pasando:
- Obtenemos el function selector de b() desde storage cargando el slot 2 (ambos selectors están empaquetados en un mismo slot)
- Hacemos un shift a la derecha de 4 bytes (32 bits) para aislar selectorB
- Almacenamos el function selector en el scratch space de la memoria
- Hacemos nuestra static call
- Pasamos gas() (también puedes especificar la cantidad de gas)
- Pasamos el parámetro _callMe como la dirección del contrato
- Verificamos si la llamada a la función fue exitosa; de lo contrario, retornamos sin datos.
- Retornamos nuestros datos desde memoria y vemos los valores 1 y 2
Nota: 0x1c y 0x20 indican que queremos pasar los últimos 4 bytes de lo que almacenamos en el scratch space. Los últimos dos parámetros de staticcall() especifican que queremos almacenar el return data en las ubicaciones de memoria 0x80 - 0xc0.
Cómo usar call() en yul
Ahora veamos call(). Vamos a llamar a la función a() de CallMe. ¡Recuerda enviar al menos 1 ether al contrato! Voy a pasar 3 y 4 como _var1 y _var2 para este ejemplo.
Aquí está el código:
Bien, similar a nuestro ejemplo anterior, tenemos que cargar el slot2. Esta vez, sin embargo, vamos a hacer un mask de selectorB para aislar selectorA.
Ahora almacenaremos el selector en 0x80.
Como necesitamos parámetros del calldata, vamos a usar calldatacopy(). Le estamos indicando a calldatacopy() que:
- almacene nuestro calldata en la ubicación de memoria 0xa0
- se salte los primeros 36 bytes
- almacene el tamaño del calldata menos 36 bytes
Nota: los primeros 4 bytes que saltamos son el function selector de callA() y los siguientes 32 bytes son la dirección de callMe.
Ahora estamos listos para hacer nuestra llamada al contrato.
Como la última vez, pasamos gas() y _callMe. Sin embargo, esta vez pasamos nuestro calldata desde 0x9c (los últimos 4 bytes de la serie de memoria en 0x80) hasta 0xe0, y almacenamos nuestros datos en la ubicación de memoria 0x100 - 0x120.
De nuevo, verificamos si la llamada fue exitosa y retornamos nuestro output. Si revisamos el contrato CallMe, vemos que los valores se actualizaron correctamente a 3 y 4.
Para aclarar aún más lo que está pasando, aquí está el layout de memoria justo antes de retornar:
Cómo usar delegate call en yul
En nuestra última sección veremos delegatecall(). El código se verá casi idéntico a call(), con un solo cambio.
El único cambio que hicimos fue cambiar call() por delegatecall() y eliminar callvalue().
No necesitamos un callvalue(), porque delegatecall ejecuta el código de CallMe dentro de su propio estado. Por lo tanto, el statement require() en a() está verificando si se envió ether a nuestro contrato Caller. Si revisamos var1 y var2 en CallMe, vemos que no hubo cambios. Sin embargo, var1 y var2 en nuestro contrato Caller se actualizaron correctamente.
¡Esto concluye nuestra sección sobre llamadas a contratos! A continuación, aprende cómo funcionan Memory, Storage y Smart Contract Calls en Yul.
Resúmenes relacionados
Solidity3 de diciembre de 2025
Los 6 mejores IDEs de Solidity para desarrolladores (2026)
Explora los mejores IDEs para el desarrollo en Solidity.
Solidity19 de noviembre de 2025
Optimización de gas en Solidity: 12 técnicas para hacer tus smart contracts más económicos y eficientes
¿Quieres escribir mejor código y reducir tus fees de gas?
Solidity13 de noviembre de 2025
12 mejores prácticas de seguridad para smart contracts en Solidity
Protege tus smart contracts con estos consejos y herramientas de seguridad de expertos.

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