Como funcionam as chamadas de contrato em Yul?
Escrito por Mark Jonathas
Yul é uma linguagem de programação intermediária que pode ser usada para escrever uma forma de linguagem assembly dentro de smart contracts. Agora que você entende a sintaxe, o storage e como a memória funciona em Yul, é hora de chamar contratos!
Como funcionam as chamadas de contrato em yul?
Na seção final desta série veremos como funcionam as chamadas de contrato em Yul. Antes de mergulharmos em alguns exemplos, precisamos aprender mais algumas Operações Yul primeiro. Vamos dar uma olhada.
Certo, agora vamos olhar para alguns novos contratos para esses exemplos. Primeiro, vamos ver o contrato que iremos chamar.
Este contrato tem duas variáveis de storage var1 e var2, armazenadas nos storage slots 1 e 2 respectivamente.
A função a() exige que o usuário envie pelo menos 1 ether ao contrato, caso contrário ela reverte.
Em seguida, a função a() atualiza var1 e var2 e as retorna.
A função b() simplesmente lê var1 e var2 e as retorna.
Antes de passarmos ao nosso contrato que chama o contrato CallMe, precisamos de um momento para entender os function selectors.
Vamos olhar para o seguinte calldata de uma transação 0x773d45e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002.
Os primeiros 4 bytes do calldata são o que chamamos de function selector (0x773d45e0). É assim que a EVM sabe qual função você quer chamar. Derivamos o function selector obtendo os primeiros 4 bytes do hash de uma string da assinatura da função.
Então a assinatura da função a() seria a(uint256,uint256).
Calculando o hash dessa string obtemos: 0x773d45e097aa76a22159880d254a5f1db8365bc2d0f0987a82bda7dfd3b9c8aa.
Olhando para os primeiros 4 bytes, vemos que é igual a 0x773d45e0.
Note a ausência de espaços na assinatura. Isso é importante porque adicionar espaços resultaria em um hash completamente diferente. Você não precisa se preocupar em obter os selectors para nossos exemplos de código, eu os fornecerei.
Vamos começar olhando para o storage layout.
Note como var1 & var2 têm o mesmo layout do contrato CallMe. Você deve se lembrar de eu ter dito que o layout precisa ser o mesmo do nosso outro contrato para que delegatecall() funcione corretamente.
Atendemos a essas necessidades e conseguimos ter outras variáveis (selectorA & selectorB) desde que nossas novas variáveis sejam adicionadas ao final. Isso evita colisões de storage.
Agora estamos prontos para fazer nossa primeira chamada de contrato.
Como usar staticcall() em yul
Vamos começar com algo simples, staticcall(). Aqui está nossa função:
Aqui está o que está acontecendo:
- Recuperar o function selector de b() do storage carregando o slot 2 (ambos os selectors estão empacotados em um único slot)
- Deslocar à direita 4 bytes (32 bits) para isolar selectorB
- Armazenar o function selector no scratch space da memória
- Fazer nossa static call
- Passar gas() (você também pode especificar a quantidade de gas)
- Passar o parâmetro _callMe como endereço do contrato
- Verificar se a chamada de função foi bem-sucedida, caso contrário retornamos sem dados.
- Retornar nossos dados da memória e ver os valores 1 e 2
Observação: 0x1c e 0x20 indicam que queremos passar os últimos 4 bytes do que armazenamos no scratch space. Os dois últimos parâmetros de staticcall() especificam que queremos armazenar o return data nas posições de memória 0x80 - 0xc0.
Como usar call() em yul
A seguir vamos olhar para call(). Vamos chamar a função a() de CallMe. Lembre-se de enviar pelo menos 1 ether ao contrato! Vou passar 3 e 4 como _var1 & _var2 neste exemplo.
Aqui está o código:
Ok, então de forma semelhante ao nosso último exemplo, precisamos carregar o slot2. Desta vez, no entanto, vamos mascarar selectorB para isolar selectorA.
Agora vamos armazenar o selector em 0x80.
Como precisamos de parâmetros do calldata, vamos usar calldatacopy(). Estamos dizendo a calldatacopy() para:
- armazenar nosso calldata na posição de memória 0xa0
- pular os primeiros 36 bytes
- armazenar o tamanho do calldata menos 36 bytes
Observação: os primeiros 4 bytes que pulamos são o function selector de callA() e os próximos 32 bytes são o endereço de callMe.
Agora estamos prontos para fazer nossa chamada de contrato!
Assim como da última vez, passamos gas() e _callMe. No entanto, desta vez passamos nosso calldata a partir de 0x9c (últimos 4 bytes da série de memória 0x80) - 0xe0, e armazenamos nossos dados na posição de memória 0x100 - 0x120.
Novamente, verificamos se a chamada foi bem-sucedida e retornamos nossa saída. Se verificarmos o contrato CallMe, veremos que os valores foram atualizados com sucesso para 3 e 4.
Para maior clareza sobre o que está acontecendo, aqui está o layout de memória logo antes de retornarmos:
Como usar delegate call em yul
Em nossa última seção, veremos delegatecall(). O código será quase idêntico ao de call(), com apenas uma mudança.
A única mudança que fizemos foi trocar call() por delegatecall() e remover callvalue().
Não precisamos de um callvalue(), porque delegate call executa o código de CallMe dentro de seu próprio estado. Portanto, o statement require() em a() está verificando se ether foi enviado ao nosso contrato Caller. Se verificarmos var1 e var2 em CallMe, não veremos mudanças. No entanto, var1 e var2 no nosso contrato Caller foram atualizadas com sucesso.
Isso encerra nossa seção sobre chamadas de contrato! A seguir, aprenda como Memory, Storage e Smart Contract Calls funcionam em Yul.
Visões gerais relacionadas
Solidity3 de dezembro de 2025
As 6 melhores IDEs de Solidity para desenvolvedores (2026)
Conheça as melhores IDEs para desenvolvimento em Solidity.
Solidity19 de novembro de 2025
Otimização de gas em Solidity: 12 técnicas para deixar seus smart contracts mais baratos e eficientes
Quer escrever código melhor e reduzir suas taxas de gas?
Solidity13 de novembro de 2025
12 boas práticas de segurança para smart contracts em Solidity
Proteja seus smart contracts com essas dicas e ferramentas de segurança de especialistas.

Construa magia blockchain
A Alchemy combina os produtos e ferramentas de desenvolvimento Web3 mais poderosos com recursos, comunidade e suporte lendário.