Lição: 185: Padrões de Projeto: Restrição de Acesso
No desenvolvimento de contratos inteligentes utilizando Solidity, a restrição de acesso é um padrão de design significativo que ajuda a garantir que apenas usuários ou contratos autorizados possam realizar ações específicas. Este padrão é essencial para manter a integridade e a segurança da funcionalidade do contrato.
Nesta aula, exploraremos vários métodos comuns de implementar restrições de acesso em contratos inteligentes Solidity, incluindo acesso apenas para o proprietário
, listas brancas e controle de acesso baseado em funções.
1. Controle de Acesso Apenas para o Proprietário
A forma mais simples e comum de restrição de acesso é permitir que apenas o proprietário do contrato execute certas ações. Para implementar isso, podemos usar o contrato Ownable
fornecido pelo OpenZeppelin, uma biblioteca que simplifica o desenvolvimento de contratos inteligentes.
Exemplo: Contrato Ownable
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
contract AcessoRestrito is Ownable {
uint256 public valor;
// Função para definir um novo valor, apenas chamável pelo proprietário
function definirValor(uint256 _valor) external onlyOwner {
valor = _valor;
}
}
Neste contrato, a função definirValor
só pode ser chamada pelo proprietário do contrato, que é definido no momento da implantação.
2. Listagem Branca
A listagem branca é outro padrão de restrição de acesso que permite que apenas endereços específicos executem determinadas funções. Essa abordagem pode ser útil para contratos que exigem um controle mais refinado sobre quem pode realizar ações.
Exemplo: Endereços da Lista Branca
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ListaBranca {
mapping(address => bool) public enderecosAutorizados;
// Evento a ser emitido quando um endereço for adicionado à lista branca
event EnderecoAdicionado(address indexed _endereco);
event EnderecoRemovido(address indexed _endereco);
// Apenas o proprietário do contrato pode adicionar à lista branca
modifier somenteAutorizado() {
require(enderecosAutorizados[msg.sender], "Não está na lista branca");
_;
}
function adicionarEndereco(address _endereco) external {
enderecosAutorizados[_endereco] = true;
emit EnderecoAdicionado(_endereco);
}
function removerEndereco(address _endereco) external {
enderecosAutorizados[_endereco] = false;
emit EnderecoRemovido(_endereco);
}
// Usuários autorizados podem chamar esta função
function realizarAcaoRestrita() external somenteAutorizado {
// Realizar ação restrita
}
}
Neste exemplo, as funções adicionarEndereco
e removerEndereco
não são restritas, permitindo que qualquer um modifique a lista. No entanto, apenas os endereços marcados como autorizados podem chamar a função realizarAcaoRestrita
.
3. Controle de Acesso Baseado em Funções
O controle de acesso baseado em funções (RBAC) permite que múltiplas funções sejam definidas em um contrato, e cada função pode ter diferentes permissões. Essa flexibilidade pode ser benéfica em sistemas mais complexos onde diferentes usuários precisam de diferentes níveis de acesso.
Exemplo: Controle de Acesso Baseado em Funções com OpenZeppelin
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract AcessoBaseadoEmFuncoes is AccessControl {
bytes32 public constant FUNCAO_ADMIN = keccak256("FUNCAO_ADMIN");
bytes32 public constant FUNCAO_USUARIO = keccak256("FUNCAO_USUARIO");
constructor() {
_setupRole(FUNCAO_ADMIN, msg.sender); // Concede ao implantador do contrato a função de admin
}
modifier apenasAdmin() {
require(hasRole(FUNCAO_ADMIN, msg.sender), "Chamador não é um admin");
_;
}
function concederFuncaoUsuario(address _usuario) external apenasAdmin {
grantRole(FUNCAO_USUARIO, _usuario);
}
function revogarFuncaoUsuario(address _usuario) external apenasAdmin {
revokeRole(FUNCAO_USUARIO, _usuario);
}
// Usuários podem chamar esta função se tiverem a FUNCAO_USUARIO
function realizarAcaoUsuario() external onlyRole(FUNCAO_USUARIO) {
// Realizar ação específica do usuário
}
}
Neste contrato, definimos duas funções: FUNCAO_ADMIN
e FUNCAO_USUARIO
. O implantador do contrato recebe a FUNCAO_ADMIN
, o que lhes permite conceder ou revogar FUNCAO_USUARIO
para outros endereços. A função realizarAcaoUsuario
pode ser chamada por qualquer usuário com a FUNCAO_USUARIO
.
Conclusão
A restrição de acesso é um padrão de design crucial nos contratos inteligentes em Solidity, garantindo que apenas usuários autorizados possam realizar ações específicas. Seja utilizando acesso apenas para o proprietário, listas brancas ou controle de acesso baseado em funções, esses padrões podem ajudá-lo a proteger a funcionalidade do seu contrato.
Ao implementar corretamente essas estratégias de restrição de acesso, você pode aumentar a segurança e manter a integridade dos seus contratos inteligentes. Sempre lembre-se de considerar cuidadosamente os direitos de acesso ao projetar seus contratos inteligentes, pois um acesso inadequado pode levar a vulnerabilidades significativas.