OpenZeppelin: Bloqueo De Tiempo

Al darle la responsabilidad de ejecutar ciertas tareas en un contrato inteligente a un reducido grupo de usuarios, podemos caer en problemas de centralización del mismo. Una buena práctica para remediar esto, es colocando un retraso en la ejecución de la acción.

Demoras en la ejecución de una tarea

OpenZeppelin implementa un contrato inteligente llamado TimelockController que permite establecer una demora antes de la ejecución de una tarea.

Supongamos que en un contrato inteligente que emite tokens, sus administradores deciden aumentar la emisión de los mismos. Esto podría llevar a que el precio de los tokens baje considerablemente. Sería oportuno darles 48 o 72 horas a sus usuarios para que decidan retirar sus fondos o continuar participando del proyecto.

Implementación de TimelockController

TimelockController, a su vez, hereda del contrato AccessControl para que el mismo sea administrado por diferentes roles de usuarios.

bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE");
bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");

Es contrato tiene roles variados, desde sus administradores, los usuarios que proponen los cambios, los que ejecutan las tareas y los que cancelan las mismas. Pudiendo ser, una misma cuenta, responsable de todas las operaciones.

Por otro lado, para el despliegue de este contrato se requiere definir tanto el tiempo de espera como los responsables de proponer y ejecutar las tareas.

constructor(
  uint256 minDelay,
  address[] memory proposers,
  address[] memory executors
) {
Además de disponer de una serie de eventos para notificar a los usuarios de una nueva propuesta o de la pronta ejecución de una tarea que puede provocar cambios en el contrato.

event CallScheduled(
  bytes32 indexed id,
  uint256 indexed index,
  address target,
  uint256 value,
  bytes data,
  bytes32 predecessor,
  uint256 delay
);
event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);
event Cancelled(bytes32 indexed id);
event MinDelayChange(uint256 oldDuration, uint256 newDuration);

Consejo Es importante que los usuarios del contrato sepan de cuánto tiempo disponen para tomar una decisión. Tal vez no sea aconsejable otorgar escasos minutos. La comunicación con los mismos enviando notificaciones o en redes sociales es de vital importancia para mantener su confianza.

Es un contrato que puede causar problemas o malos entendidos con la comunidad que participa del proyecto, es crucial la notificación a los usuarios de cualquier cambio trascendental en el contrato.

Conclusión

Este tipo de contratos pueden caer fácilmente en problemas de centralización. Su utilización está limitada a casos de uso con buenos motivos para ser implementada una funcionalidad como tal.

Es importante conocer conceptualmente todo lo que pude desarrollarse en un contrato inteligente para proponerlo y/o implementarlo llegada la necesidad en un proyecto.


Post creado en colaboración con el Curso de OpenZeppelin de Platzi.