SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
18.11.2024

Lição 065: Padrões de Controle de Acesso

No mundo dos contratos inteligentes, garantir que apenas usuários autorizados possam realizar ações específicas é fundamental. Padrões de controle de acesso são essenciais para estabelecer permissões e restringir o acesso a funções sensíveis. Esta lição explorará vários padrões comuns de controle de acesso em Solidity.

1. Controle de Acesso Básico com onlyOwner

Uma das formas mais simples de controle de acesso é restringir o acesso a determinadas funções ao proprietário do contrato. Isso pode ser realizado utilizando o padrão Ownable.

Exemplo:

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

import "@openzeppelin/contracts/access/Ownable.sol";

contract ControleAcessoBasico is Ownable {
    string public mensagemSecreta;

    function definirMensagemSecreta(string memory _mensagem) public onlyOwner {
        mensagemSecreta = _mensagem;
    }

    function visualizarMensagemSecreta() public view returns (string memory) {
        return mensagemSecreta;
    }
}

Neste exemplo:

  • O contrato ControleAcessoBasico herda do contrato Ownable da biblioteca OpenZeppelin.
  • A função definirMensagemSecreta só pode ser chamada pelo proprietário do contrato, enquanto qualquer pessoa pode chamar visualizarMensagemSecreta.

2. Múltiplos Proprietários com o Padrão Multisig

Utilizar múltiplos proprietários pode aumentar a segurança e a descentralização. O padrão de assinatura múltipla (multisig) permite que um grupo de contas controle um único contrato.

Exemplo:

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

contract MultiAssinatura {
    address[] public proprietarios;
    mapping(address => bool) public ehProprietario;
    uint8 public necessários;

    constructor(address[] memory _proprietarios, uint8 _necessários) {
        require(_proprietarios.length > 0, "Deve ter proprietários");
        require(_necessários > 0 && _necessários <= _proprietarios.length, "Número de proprietários necessários inválido");

        for (uint8 i = 0; i < _proprietarios.length; i++) {
            require(!ehProprietario[_proprietarios[i]], "Proprietário duplicado");
            ehProprietario[_proprietarios[i]] = true;
        }

        proprietarios = _proprietarios;
        necessários = _necessários;
    }

    modifier apenasProprietarios() {
        require(ehProprietario[msg.sender], "Não é um proprietário");
        _;
    }
}

Neste exemplo, o contrato MultiAssinatura permite que vários proprietários sejam designados. Funções podem ser adicionadas que requerem um determinado número de proprietários para aprovar ações.

3. Controle de Acesso Baseado em Funções

Para aplicações mais complexas, um padrão de controle de acesso baseado em funções (RBAC) pode ser usado. Isso permite permissões diferentes para diferentes funções.

Exemplo:

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

import "@openzeppelin/contracts/access/AccessControl.sol";

contract ControleAcessoPorFuncoes is AccessControl {
    bytes32 public constant ROLE_ADMIN = keccak256("ROLE_ADMIN");
    bytes32 public constant ROLE_MINTER = keccak256("ROLE_MINTER");

    constructor() {
        _setupRole(ROLE_ADMIN, msg.sender);
        _setupRole(ROLE_MINTER, msg.sender);
    }

    function mint(address to) public onlyRole(ROLE_MINTER) {
        // Lógica de mintagem
    }

    function concederRoleMinter(address conta) public onlyRole(ROLE_ADMIN) {
        grantRole(ROLE_MINTER, conta);
    }

    function revogarRoleMinter(address conta) public onlyRole(ROLE_ADMIN) {
        revokeRole(ROLE_MINTER, conta);
    }
}

No contrato ControleAcessoPorFuncoes:

  • Funções são definidas utilizando constantes bytes32.
  • O ROLE_ADMIN pode conceder ou revogar funções, enquanto o ROLE_MINTER pode criar novos tokens.
  • Este padrão é muito flexível e permite futuras melhorias nas funções.

4. Controle de Acesso Pausável

Em certas situações, pode ser necessário pausar a funcionalidade do contrato em emergências. O padrão Pausable pode facilitar isso.

Exemplo:

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

import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract ControleAcessoPausavel is Pausable, Ownable {
    function realizarAcao() public whenNotPaused {
        // Lógica da ação que pode ser pausada
    }

    function pausar() public onlyOwner {
        _pause();
    }

    function despausar() public onlyOwner {
        _unpause();
    }
}

No contrato ControleAcessoPausavel:

  • O contrato pode ser pausado ou despausado pelo proprietário.
  • A função realizarAcao só pode ser executada quando o contrato não está pausado.

Conclusão

O controle de acesso é um aspecto fundamental da segurança em contratos inteligentes. Esta lição apresentou padrões essenciais de controle de acesso, incluindo propriedade básica, multisig, controle baseado em funções e contratos pausáveis. Ao implementar cuidadosamente esses padrões, os desenvolvedores podem melhorar significativamente a segurança e a funcionalidade de seus contratos inteligentes. Explore esses padrões e aplique-os judiciosamente para proteger seus projetos no espaço descentralizado.

Video

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

Thank you for voting!