SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
18.11.2024

Lição: 062: Funções Delegatecall e Call em Solidity

Em Solidity, as funções call e delegatecall são funções de baixo nível que permitem a interatividade entre contratos. Compreender a diferença entre essas duas funções é crucial para gerenciar o estado, custos de gás e segurança nos contratos inteligentes. Esta aula explorará essas funções com exemplos práticos para ilustrar seus casos de uso.

1. Introdução à Call

A função call permite que você chame uma função de outro contrato enquanto transfere o controle e o contexto para esse contrato. Ao usar call, o contrato alvo pode modificar seu estado e transferir Ether conforme necessário.

Exemplo de Call

Aqui está um exemplo simples demonstrando como a call funciona:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Receptor {
    uint256 public valor;

    function definirValor(uint256 _valor) public {
        valor = _valor;
    }
}

contract Chamador {
    function chamarDefinirValor(address enderecoReceptor, uint256 _valor) public {
        (bool sucesso, ) = enderecoReceptor.call(
            abi.encodeWithSignature("definirValor(uint256)", _valor)
        );
        require(sucesso, "Chamada falhou");
    }
}

Neste exemplo:

  • O contrato Receptor tem uma função definirValor.
  • O contrato Chamador utiliza call para invocar definirValor no contrato Receptor, passando um novo valor.

Nota Importante:

Usar call pode ser arriscado, pois permite flexibilidade na função chamada. Se o contrato Receptor mudar sua implementação, isso pode levar a comportamentos inesperados em Chamador.

2. Introdução ao Delegatecall

A função delegatecall é semelhante ao call, mas mantém o contexto do contrato chamador. Isso significa que o armazenamento, remetente e saldo permanecem inalterados. É utilizada principalmente em contratos proxy.

Exemplo de Delegatecall

Aqui está um exemplo mostrando como delegatecall funciona:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Logica {
    uint256 public valor;

    function definirValor(uint256 _valor) public {
        valor = _valor;
    }
}

contract Proxy {
    address public enderecoLogica;

    constructor(address _enderecoLogica) {
        enderecoLogica = _enderecoLogica;
    }

    function chamarDefinirValor(uint256 _valor) public {
        (bool sucesso, ) = enderecoLogica.delegatecall(
            abi.encodeWithSignature("definirValor(uint256)", _valor)
        );
        require(sucesso, "Delegatecall falhou");
    }
}

Neste exemplo:

  • O contrato Logica tem uma função definirValor que modifica a variável de estado valor.
  • O contrato Proxy mantém o endereço do contrato Logica e usa delegatecall para invocar definirValor sem transferir o controle.

Características Principais do Delegatecall:

  1. A variável de estado valor no contrato Logica é armazenada no armazenamento do contrato Proxy.
  2. Como utiliza o armazenamento do contrato chamador, o delegatecall é útil para contratos atualizáveis.

3. Diferenças entre Call e Delegatecall

Aqui está uma rápida comparação entre os dois:

Característica Call Delegatecall
Contexto Muda para o contexto do contrato chamado Mantém o contexto do contrato chamador
Alterações de Estado Muda o estado do contrato chamado Muda o estado do contrato chamador
Caso de Uso Chamadas a funções em contratos externos Implementação de padrões proxy

4. Considerações de Segurança

Tanto o call quanto o delegatecall têm potenciais implicações de segurança. Aqui estão algumas dicas para mitigar riscos:

  • Use Declarações require: Sempre verifique o valor de retorno de call e delegatecall para determinar se a chamada foi bem-sucedida.
  • Evite Contratos Não Confiáveis: Tenha cautela ao chamar contratos externos, especialmente aqueles cujo comportamento não é conhecido.
  • Limite o Acesso: Implemente controle de acesso para restringir quem pode invocar os métodos do contrato que usam essas funções de baixo nível.

Conclusão

Compreender call e delegatecall é essencial para o desenvolvimento efetivo de contratos inteligentes em Solidity. Ambos servem a propósitos únicos e devem ser usados com cautela. Em resumo, esta aula abordou as diferenças entre essas duas funções de baixo nível, fornecendo exemplos e enfatizando considerações de segurança.

Ao utilizar essas funções corretamente, você pode escrever contratos robustos e flexíveis, incluindo padrões proxy atualizáveis adequados para futuras iterações de suas aplicações.

Video

Did you like this article? Rate it from 1 to 5:

Thank you for voting!