Falha na Inicialização (Failure to Initialize)

Ocorre quando um contrato não é corretamente inicializado antes de seu uso, deixando variáveis críticas, como o endereço do proprietário ou configurações essenciais, em estados padrão. Isso pode permitir que qualquer usuário assuma o controle do contrato ou que ele funcione de maneira inesperada.

Exemplo:

Imagine um contrato inteligente que deveria ser inicializado com o endereço do proprietário (owner), que possui privilégios especiais como pausar ou destruir o contrato. Se o contrato não tiver um construtor que defina esse proprietário, ou se for implantado via proxy sem uma função de inicialização adequada, a variável owner pode permanecer no valor padrão — como o endereço 0x0 ou outro endereço padrão.

contract VulnerableContract {
    address public owner;

    function initialize(address _owner) external {
        owner = _owner;
    }

    function pauseContract() external {
        require(msg.sender == owner, "Not the contract owner");
        // Lógica para pausar el contrato
    }
}

Neste exemplo, se a função initialize não for chamada após o contrato ser implantado, a variável owner permanecerá não definida, permitindo que qualquer usuário potencialmente chame initialize e se defina como proprietário, assumindo o controle do contrato.

Mitigação:

  1. Uso de um construtor: Caso o contrato não utilize o padrão proxy e seja implantado diretamente, é altamente recomendável usar um construtor para inicializar variáveis críticas como owner. O construtor garante que essas variáveis sejam definidas no momento da implantação e não possam ser modificadas posteriormente.

    contract SecureContract {
        address public owner;
    
        constructor(address _owner) {
            owner = _owner;
        }
    
        function pauseContract() external {
            require(msg.sender == owner, "Not the contract owner");
            // Lógica para pausar el contrato
        }
    }
  2. Inicialização em proxies: Quando se utiliza o padrão proxy para implantar contratos (uma prática comum para facilitar atualizações), é fundamental incluir uma função de inicialização que garanta que o contrato só possa ser inicializado uma única vez. Essa função deve ser protegida para que possa ser chamada apenas uma vez e não possa ser reutilizada por um atacante.

    contract SecureContract {
        address public owner;
        bool private initialized;
    
        function initialize(address _owner) external {
            require(!initialized, "Already initialized");
            owner = _owner;
            initialized = true;
        }
    
        function pauseContract() external {
            require(msg.sender == owner, "Not the contract owner");
            // Lógica para pausar el contrato
        }
    }
  3. Proteção contra a re-inicialização: Além de garantir que a função de inicialização só possa ser executada uma única vez, é possível implementar um modificador que verifique se o contrato já foi inicializado antes de permitir a execução de funções críticas.

    modifier onlyInitialized() {
        require(initialized, "Contract not initialized");
        _;
    }
    
    function pauseContract() external onlyInitialized {
        require(msg.sender == owner, "Not the contract owner");
        // Lógica para pausar el contrato
    }

Last updated

Was this helpful?