Lição 182: Padrões de Design: Registro
No mundo do desenvolvimento de contratos inteligentes, os padrões de design desempenham um papel crucial na estruturação do código, garantindo sua manutenabilidade, reutilização e clareza. Um desses padrões é o padrão de design Registro. Este padrão é particularmente útil para gerenciar registros de entidades, endereços ou configurações em uma aplicação descentralizada (dApp).
O que é o Padrão de Registro?
O padrão de design Registro permite que você mantenha o controle de itens (como contratos, ativos ou usuários) de uma maneira centralizada. Ele atua como uma única fonte de verdade para os endereços desses itens, o que pode ser útil para sistemas descentralizados onde múltiplos contratos interagem entre si.
Os principais benefícios de usar o padrão de Registro incluem:
- Gestão centralizada de contratos e seus endereços.
- Atualizações e modificações mais fáceis nos endereços sem a necessidade de alterar o código de outros contratos.
- Maior modularidade e flexibilidade.
Estrutura Básica de um Registro
Em uma implementação típica, um contrato de Registro pode permitir que você registre, desregistre e recupere endereços de entidades registradas. Abaixo está um exemplo simples de um contrato que implementa o padrão de Registro.
Exemplo: Contrato de Registro Simples
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract RegistroSimples {
// Mapeamento para armazenar endereços registrados
mapping(bytes32 => address) private registro;
// Evento para registrar a inscrição
event Registrado(bytes32 indexed nome, address indexed entidade);
// Evento para registrar a desinscrição
event Desregistrado(bytes32 indexed nome);
// Função para registrar um endereço com um nome
function registrar(bytes32 nome, address entidade) external {
require(entidade != address(0), "Endereço inválido");
require(registro[nome] == address(0), "Já registrado");
registro[nome] = entidade;
emit Registrado(nome, entidade);
}
// Função para desregistrar um endereço pelo nome
function desregistrar(bytes32 nome) external {
require(registro[nome] != address(0), "Não registrado");
delete registro[nome];
emit Desregistrado(nome);
}
// Função para recuperar uma entidade pelo nome
function obterEntidade(bytes32 nome) external view returns (address) {
return registro[nome];
}
}
Explicação
-
Mapeamento: O mapeamento
registro
permite associar um identificador únicobytes32
(nome) a um endereço do Ethereum. -
Função Registrar: Esta função verifica se o endereço é válido e ainda não está registrado. Se ambas as condições forem atendidas, registra a entidade e emite um evento
Registrado
. -
Função Desregistrar: Esta função remove uma entidade do registro, emitindo um evento
Desregistrado
. -
Função Obter Entidade: Esta função permite que qualquer um consulte o registro para obter o endereço registrado para um determinado nome.
Caso de Uso: Registro de Tokens
Vamos expandir nosso registro simples criando um registro de tokens que permite aos usuários registrar diferentes contratos de tokens.
Exemplo: Contrato de Registro de Tokens
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Interface do Token
interface IToken {
function nome() external view returns (string memory);
function simbolo() external view returns (string memory);
}
contract RegistroDeTokens {
mapping(bytes32 => address) private tokens;
event TokenRegistrado(bytes32 indexed nome, address indexed token);
event TokenDesregistrado(bytes32 indexed nome);
function registrarToken(bytes32 nome, address token) external {
require(token != address(0), "Endereço de token inválido");
require(tokens[nome] == address(0), "Token já registrado");
tokens[nome] = token;
emit TokenRegistrado(nome, token);
}
function desregistrarToken(bytes32 nome) external {
require(tokens[nome] != address(0), "Token não registrado");
delete tokens[nome];
emit TokenDesregistrado(nome);
}
function obterToken(bytes32 nome) external view returns (address) {
return tokens[nome];
}
function obterDetalhesToken(bytes32 nome) external view returns (string memory, string memory) {
address enderecoToken = tokens[nome];
require(enderecoToken != address(0), "Token não registrado");
IToken token = IToken(enderecoToken);
return (token.nome(), token.simbolo());
}
}
Explicação
-
Interface do Token: Definimos uma interface
IToken
para interagir com contratos de tokens, permitindo a recuperação de seus nomes e símbolos. -
Função Registrar Token: Isso permite que os usuários registrem um contrato de token fornecendo seu nome e endereço.
-
Função Obter Detalhes do Token: Esta função recupera o nome e o símbolo do token registrado consultando o contrato correspondente.
Conclusão
O padrão de design Registro é uma maneira eficaz de gerenciar os relacionamentos entre vários componentes em uma aplicação descentralizada. Ele centraliza a gestão de endereços, facilitando a atualização de contratos e configurações sem grandes mudanças em todo o sistema.
Ao utilizar os exemplos fornecidos, você pode aproveitar o poder do padrão de Registro em seus próprios projetos de contratos inteligentes, melhorando a estrutura e a manutenabilidade do seu código.