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.
Contratos con múltiples roles
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.
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
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.
Contribución creada por: Kevin Fiorentino (Platzi contributor).
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?