- Home
- /
- Blog
- /
- OpenZeppelin
OpenZeppelin: Manejo De Usuarios#
Una necesidad muy frecuente en un contrato inteligente es poder controlar usuarios. El acceso al contrato y restringir el mismo al due帽o del contrato.
Propiedad de un contrato#
Por lo general, la direcci贸n que despliega el contrato se convierte en el owner del mismo. Puedes obtener la direcci贸n de qui茅n realice el despliegue con msg.sender
, asign谩rselo a una variable y, con la misma, hacer la validaci贸n del due帽o del contrato.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract MiContrato {
address private owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Debes ser el owner del contrato para continuar");
_;
}
function functionParaElOwner() public onlyOwner {}
}
Propiedad del contrato con OpenZeppelin#
Al tratarse de un caso de uso muy trivial e importante, puedes utilizar una librer铆a de OpenZeppelin para solucionarlo en menos l铆neas de c贸digo.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "@openzeppelin/contracts/access/Ownable.sol";
contract MiContrato is Ownable {
function functionParaElOwner() public onlyOwner {}
}
Tu contrato hereda de Ownable para disponer del modificador onlyOwner
. De esta forma, aseguras tu contrato a no cometer ning煤n error con respecto a la manipulaci贸n de su due帽o.
Cambiar el due帽o de un contrato#
El contrato Ownable de OpenZeppelin trae consigo dos caracter铆sticas m谩s que pueden serte de utilidad en la l贸gica que tengas que desarrollar en tu propio contrato.
La primera es la posibilidad de cambiar el due帽o del contrato. La funci贸n transferOwnership(address)
recibe por par谩metro una direcci贸n y asignar谩 la misma como nuevo owner del contrato.
Cabe destacar que solo el actual due帽o del contrato puede llamar a esta funci贸n y ceder la propiedad del contrato.
La segunda caracter铆stica es la posibilidad de que el due帽o actual del contrato renuncie a este. La funci贸n renounceOwnership()
le asignar谩 un 0 a la variable que guarda la direcci贸n del due帽o del contrato, haciendo imposible su recuperaci贸n.
隆Ten cuidado! Es importante tener cuidado con esta funci贸n, ya que el contrato podr铆a quedar inutilizable si nadie es el owner del mismo.
Contratos con m煤ltiples roles#
En determinados contratos, a veces no es suficiente disponer solo de un owner del mismo. Podemos necesitar tener dos, tres o N cantidad de roles diferentes. Cada uno con sus respectivas responsabilidades.
Podemos definir la cantidad de roles que vamos a necesitar en nuestro contrato. Sin embargo, a煤n requerimos que exista un 煤nico due帽o que asigne posteriormente los roles a otras cuentas.
Importa y hereda AccessControl desde OpenZeppelin para comenzar a definir tus propios roles.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract ContratoConRoles is AccessControl {
bytes32 public constant ROL_ADMIN = keccak256("ROL_ADMIN");
bytes32 public constant ROL_USUARIO = keccak256("ROL_USUARIO");
constructor() {
_grantRole(ROL_ADMIN, msg.sender);
}
function soloAdmin() public {
require(hasRole(ROL_ADMIN, msg.sender), "Esta funcion solo puede ser utilizada por el ADMIN");
}
function soloUsuario() public {
require(hasRole(ROL_USUARIO, msg.sender), "Esta funcion solo puede ser utilizada por un USUARIO");
}
function agregarRol(bytes32 role, address account) public {
require(hasRole(ROL_ADMIN, msg.sender), "Esta funcion solo puede ser utilizada por el ADMIN");
_grantRole(role, account);
}
}
La cuenta que despliega el contrato, ser谩 la due帽a del mismo por defecto, asignando este en el constructor del contrato. Luego de esto, puede utilizar la funci贸n agregarRol()
para asignar roles a otras cuentas.
La creaci贸n de roles se realiza de la forma:
bytes32 public constant ROL_ADMIN = keccak256("ROL_ADMIN");
La funci贸n keccak256()
encripta y convierte en bytes32
el nombre del rol para poder asignarlo a las cuentas posteriormente de forma segura.
La misma crea una funci贸n p煤blica para que puedas obtener el hash del rol y poder utilizarlo.
ROL_ADMIN = 0x7e5b835f8ef15bb117d49cb6d0658113bc08d41d8a6edf12d3d1feb5c5875330
ROL_USUARIO = 0x575582185c1302752a00c2a38ce472577737eb5e4ab29b34daf1ccaa4c9fe08a
La asignaci贸n de los roles debe hacerse en bytes32 y no con el String con el que fue definido:
Manipulaci贸n de roles#
Es importante destacar que, as铆 como el owner del contrato puede asignar roles, tambi茅n puede quitar roles con la funci贸n revokeRole(address)
.
Las propias cuentas pueden renunciar a un rol si consideran que ya no lo necesita o no lo quieren con la funci贸n renounceRole(bytes32,address)
.
Puede no ser necesario crear un ROL_ADMIN
, ya que el contrato AccessControl
ya dispone de este rol por defecto.
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
A partir de todas estas caracter铆sticas que necesitas para el manejo de roles, puedes desarrollar tus contratos de la forma m谩s conveniente.
Conclusi贸n#
Tener la posibilidad de que una sola cuenta ejecute determinadas acciones en un contrato puede llevar a centralizar el mismo. Implem茅ntalo en casos de uso donde verdaderamente una sola persona deba poder gestionarlo y tener un buen motivo para que as铆 sea.
Sin embargo, administrar correctamente el owner de un contrato es crucial para evitar robos de fondos o identidades en un proyecto y utilizar contratos ya probados y auditados como lo es Ownable de OpenZeppelin es m谩s que aconsejable hacerlo.
Sabemos que la principal filosof铆a de Blockchain es la descentralizaci贸n, pero en determinados casos de uso se puede requerir tareas centralizadas en pocos usuarios.
No necesariamente un contrato va a manipular grandes fondos de dinero, y si es el caso, pueden existir razonables motivos para utilizar roles y privilegios para administrar estos. Lo importante es que los usuarios del contrato sepan que esto es as铆 y est茅n de acuerdo.
Por ejemplo, un contrato que guarda informaci贸n de estudiantes y sus notas. Los propios estudiantes no deben ser capaz de modificar sus datos, solo un profesor debe poder hacerlo.
Implementa la administraci贸n de roles de forma inteligente para crear tus contratos y que cada tipo de cuenta tenga sus responsabilidades. El caso de uso que tengas que resolver determinar谩 c贸mo debes desarrollar tu contrato.
Post creado en colaboraci贸n con el Curso de OpenZeppelin de Platzi.