Recentemente, tenho reaprendido a solidez, consolidado os detalhes e escrito uma “Cartilha Minimalista de Solidez” para iniciantes usarem (os caras da programação podem encontrar outro tutorial), atualizada 1-3 vezes por semana.
Todos os códigos e tutoriais são de código aberto no GitHub: github.com/AmazingAng/WTFSolidity
Na Palestra 17: Enviando ETH, falamos sobre o uso de call para enviar ETH, e nesta palestra vamos mostrar como usá-lo para chamar contratos.
Chamada
Call é uma função de membro de baixo nível do tipo de endereço, que é usada para interagir com outros contratos. Ele retorna (bool, data), que corresponde ao sucesso da chamada e ao valor de retorno da função objetiva, respectivamente.
call é o método oficialmente recomendado de enviar ETH acionando o fallback ou receber funções por solidez. Não é recomendável chamar outro contrato com uma chamada, porque quando você chama a função de um contrato inseguro, você lhe dá a iniciativa. O método recomendado ainda é chamar a função depois de declarar a variável de contrato, veja Aula 19: Chamando outros contratos. Se não soubermos o código-fonte ou ABI do contrato da outra parte, não podemos gerar variáveis contratuais, mas ainda podemos chamar as funções contratuais da outra parte por chamada.
Regras para o uso da chamada
As regras para usar a chamada são as seguintes:
A codificação binária usa a função de codificação estruturada abi.encodeWithSignature para obter:
A assinatura da função é “Nome da função (tipo de parâmetro separado por vírgula)”. Por exemplo, abi.encodeWithSignature(“f(uint256,address)”, _x, _addr).
Além disso, ao ligar para o contrato, você pode especificar a quantidade de ETH e gás a ser enviada pela transação:
Parece um pouco complicado, então vamos dar um exemplo de um aplicativo de chamada.
Contrato-alvo
Vamos começar escrevendo um contrato de destino simples, OtherContract, e implantando-o, o código é basicamente o mesmo que na Aula 19, exceto com a adição de uma função de fallback.
Este contrato contém uma variável de estado x, um log de eventos que é acionado quando o ETH é recebido e três funções:
getBalance(): Devolve o saldo ETH do contrato. setX(): função externa a pagar, que pode definir o valor de x e enviar ETH para o contrato. getX(): Lê o valor de x.
Use call para chamar o contrato de destino
1. Evento de resposta
Vamos escrever um contrato Call para chamar a função de contrato de destino. Em primeiro lugar, escreva uma definição de um evento de resposta e produza o sucesso e os dados retornados pela chamada, para que possamos observar o valor de retorno.
2. Chamar a função setX
Definimos a função callSetX para chamar setX() do contrato de destino, transferimos a quantidade de ETH para msg.value e liberamos o evento Response para o sucesso e os dados de saída:
Em seguida, chamamos callSetX para alterar a variável de estado _x para 5, e os parâmetros são o endereço OtherContract e 5, porque a função objetiva setX() não retorna um valor, portanto, a saída de dados do evento Response é 0x, que está vazia.
3. Chamar a função getX
Vamos chamar a função getX(), que retornará o valor do contrato de destino _x, do tipo uint256. Podemos usar abi.decode para decodificar o valor de retorno da chamada, dados e ler o valor.
A partir da saída do evento Response, podemos ver que os dados são 0x0000000000000000000000000000000000000000000000000000000000000005. Após abi.decode, o valor de retorno final é 5.
4. Chamar uma função que não existe
Se a função que inserimos na chamada não existir no contrato de destino, a função de fallback do contrato de destino será acionada.
No exemplo acima, chamamos de função foo inexistente. A chamada ainda pode ser executada com êxito e retornar com êxito, mas na verdade é a função de fallback do contrato de destino chamado.
Resumo
Nesta palestra, mostramos como usar a chamada de função de baixo nível para chamar outros contratos. Call não é o método recomendado para chamar um contrato porque não é seguro. Mas é útil nos deixar chamar o contrato de destino sem saber o código-fonte e a ABI.
Ver original
Esta página pode conter conteúdos de terceiros, que são fornecidos apenas para fins informativos (sem representações/garantias) e não devem ser considerados como uma aprovação dos seus pontos de vista pela Gate, nem como aconselhamento financeiro ou profissional. Consulte a Declaração de exoneração de responsabilidade para obter mais informações.
Introdução à Solidez|Palestra 22: Chamada
Recentemente, tenho reaprendido a solidez, consolidado os detalhes e escrito uma “Cartilha Minimalista de Solidez” para iniciantes usarem (os caras da programação podem encontrar outro tutorial), atualizada 1-3 vezes por semana.
Todos os códigos e tutoriais são de código aberto no GitHub: github.com/AmazingAng/WTFSolidity
Na Palestra 17: Enviando ETH, falamos sobre o uso de call para enviar ETH, e nesta palestra vamos mostrar como usá-lo para chamar contratos.
Chamada
Call é uma função de membro de baixo nível do tipo de endereço, que é usada para interagir com outros contratos. Ele retorna (bool, data), que corresponde ao sucesso da chamada e ao valor de retorno da função objetiva, respectivamente.
call é o método oficialmente recomendado de enviar ETH acionando o fallback ou receber funções por solidez. Não é recomendável chamar outro contrato com uma chamada, porque quando você chama a função de um contrato inseguro, você lhe dá a iniciativa. O método recomendado ainda é chamar a função depois de declarar a variável de contrato, veja Aula 19: Chamando outros contratos. Se não soubermos o código-fonte ou ABI do contrato da outra parte, não podemos gerar variáveis contratuais, mas ainda podemos chamar as funções contratuais da outra parte por chamada.
Regras para o uso da chamada
As regras para usar a chamada são as seguintes:
A codificação binária usa a função de codificação estruturada abi.encodeWithSignature para obter:
A assinatura da função é “Nome da função (tipo de parâmetro separado por vírgula)”. Por exemplo, abi.encodeWithSignature(“f(uint256,address)”, _x, _addr).
Além disso, ao ligar para o contrato, você pode especificar a quantidade de ETH e gás a ser enviada pela transação:
Parece um pouco complicado, então vamos dar um exemplo de um aplicativo de chamada.
Contrato-alvo
Vamos começar escrevendo um contrato de destino simples, OtherContract, e implantando-o, o código é basicamente o mesmo que na Aula 19, exceto com a adição de uma função de fallback.
Este contrato contém uma variável de estado x, um log de eventos que é acionado quando o ETH é recebido e três funções:
getBalance(): Devolve o saldo ETH do contrato. setX(): função externa a pagar, que pode definir o valor de x e enviar ETH para o contrato. getX(): Lê o valor de x.
Use call para chamar o contrato de destino
1. Evento de resposta
Vamos escrever um contrato Call para chamar a função de contrato de destino. Em primeiro lugar, escreva uma definição de um evento de resposta e produza o sucesso e os dados retornados pela chamada, para que possamos observar o valor de retorno.
2. Chamar a função setX
Definimos a função callSetX para chamar setX() do contrato de destino, transferimos a quantidade de ETH para msg.value e liberamos o evento Response para o sucesso e os dados de saída:
Em seguida, chamamos callSetX para alterar a variável de estado _x para 5, e os parâmetros são o endereço OtherContract e 5, porque a função objetiva setX() não retorna um valor, portanto, a saída de dados do evento Response é 0x, que está vazia.
3. Chamar a função getX
Vamos chamar a função getX(), que retornará o valor do contrato de destino _x, do tipo uint256. Podemos usar abi.decode para decodificar o valor de retorno da chamada, dados e ler o valor.
A partir da saída do evento Response, podemos ver que os dados são 0x0000000000000000000000000000000000000000000000000000000000000005. Após abi.decode, o valor de retorno final é 5.
4. Chamar uma função que não existe
Se a função que inserimos na chamada não existir no contrato de destino, a função de fallback do contrato de destino será acionada.
No exemplo acima, chamamos de função foo inexistente. A chamada ainda pode ser executada com êxito e retornar com êxito, mas na verdade é a função de fallback do contrato de destino chamado.
Resumo
Nesta palestra, mostramos como usar a chamada de função de baixo nível para chamar outros contratos. Call não é o método recomendado para chamar um contrato porque não é seguro. Mas é útil nos deixar chamar o contrato de destino sem saber o código-fonte e a ABI.