Parceros
  • 馃懡Recursos
    • 馃捇Nodos validadores
      • Buenas pr谩cticas y seguridad de un validador
      • Montaje de nodo validador de Stargaze
      • Montaje de nodo validador de Tgrade
      • Montaje de nodo validador de Juno
      • Instalacion del Cosmovisor
      • Instalaci贸n de AutoCompound
      • Gu铆a de instalaci贸n Prometheus y Grafana para un Validador
    • 馃帗Desarrollo
      • Fundamentos en Gnu/Linux
      • Fundamentos en Blockchain
      • Billeteras
      • Introducci贸n a Cosmos Hub
      • Guia de Inicio en Rust
      • Clases de CosmWasm
        • Introducci贸n a CosmWasm
        • Puntos de entrada de un contrato vacio
        • Consultas - Query
      • Clases de Rust
        • Introducci贸n a Rust
        • Ciclos
        • Funciones
        • Manejo de la memoria
        • Tipos de datos avanzados
        • Macros
        • Manejo de paquetes
        • Manejo de errores
      • Guia Archway
        • Instalaci贸n de requisitos
        • Configuraci贸n del proyecto
        • Solicitud de tokens Testnet
        • Mi primera app
          • Configuracion
          • Produciendo ejecutables wasm
          • Despliegue e instanciaci贸n de contratos en la cadena
          • Interactuar con su contrato
          • Construir el frontend de la dApp
        • Proyecto NFT
          • Creando un proyecto NFT
          • Despliegue del contrato de tokens
          • Acu帽aci贸n y env铆o de tokens
          • Construye la Dapp NFT
        • Fee Grant
          • Comprendiendo los Fee grant
          • Grant asignaci贸n
          • Utilizando asignaciones grant
        • Multifirmas
          • Archway multi firma hub
          • Navegar por la interfaz multi firmas
      • Cosmwasm Documentacion
        • Introducci贸n
        • Primeros pasos
          • Introducci贸n
          • Configuraci贸n del entorno
          • Elaborar un contrato
          • Test Unitarios
          • Despliegue e interacci贸n
          • Integraci贸n con contratos inteligentes
          • Pr贸ximos pasos
        • Arquitectura
          • 驴Qu茅 son los contratos multicadena?
          • Modelo de actor para las convocatorias de contratos
          • Nombres y direcciones
          • Consulta del estado del contrato
          • Formatos de serializaci贸n
          • Composici贸n del contrato
          • Comparaci贸n con los contratos de solidity
        • Contratos inteligentes
          • Sem谩ntica contractual
          • Message
            • Messages
            • Submensajes
          • State
            • Simple state
            • Complex state y maps
          • Result y option
          • Entry points
          • Query
          • Events
          • Math
          • Verificaci贸n de contratos inteligentes
          • Migration
          • Migrar una dapp a una red diferente
          • Testing
          • Ejecuci贸n Sudo
          • CosmWasm y CIB
        • Tutoriales
          • Opcion simple
            • Testing
          • Storage
            • 驴C贸mo funciona el almacenamiento de valores clave?
            • 脥ndices
            • Modelizaci贸n avanzada de estados
          • Cosmwasm con ejemplos
            • Operaciones matem谩ticas de Cosmowasm
            • Crear una instancia de un contrato CosmWasm
            • Timelock
            • Contrato Crowdfunding
            • Respuestas y atributos en Cosmwasm
            • Lee y escribe
            • Env铆o de tokens
            • Token Vaults
            • Creador de mercado autom谩tico de productos constantes (AMM)
      • Guia Celestia
        • Descripcion general de celestia
          • Introduccion
          • Blockchains monol铆ticos vs modulares
          • Capa de disponibilidad de datos
            • La capa de disponibilidad de datos de Celestia
            • El ciclo de vida de una transacci贸n celestia-app
            • Recuperabilidad de datos y poda
            • Disponibilidad de datos FAQ
          • Recursos adicionales
            • Aprende modular
            • Glosario de Celestia
            • Especificaciones de aplicaci贸n de celestes
            • Documentaci贸n API de nodo celestial
        • Ejecutar un nodo
          • Descripci贸n general de los nodos en ejecuci贸n en Celestia
          • Gu铆a de inicio r谩pido
            • Decidir qu茅 nodo ejecutar
            • Entorno de desarrollo
            • Instalar celestia-node
            • Instalar celestia-app
            • 馃惓 Configuraci贸n de Docker
          • Redes
            • Resumen de redes
            • Mainnet Beta
            • Mocha testnet
            • Ar谩bica devnet
          • Tipos de nodos
            • Disponibilidad de datos
              • Nodo ligero
              • Nodo completo
              • Nodo puente
            • Consenso
            • Relay de IBC
              • Gu铆a de retransmisi贸n IBC
              • Relays de IBC
          • Recursos
            • nodo-celestia
              • Metricas
              • gu铆a config.toml
              • Redes y valores personalizados
              • Soluci贸n de problemas
            • celestia-app
              • Especificaciones
              • M茅tricas, visualizaci贸n y alertas
              • Mec谩nica de corte
              • Crear un testnet Celestia
              • Comandos CLI 煤tiles
              • Monitor de Actualizaci贸n
              • Carteras en celestia-app
              • Multisig
              • Crea una cuenta de adquisici贸n
            • SystemD
            • Proceso de hardfork
        • Desarrolladores
          • Construir modular
          • Env铆o de blobs de datos a Celestia
          • Directrices de reenv铆o de transacciones
          • API de nodo
            • Celestia-node RPC CLI tutorial
            • Documentaci贸n de la API RPC de Celestia-Node
            • R谩pido Scavenger
            • Page
          • Integrar con Blobstream
            • Descripci贸n general de Blobstream
            • Integrarse con contratos de Blobstream
            • Integrar con el cliente Blobstream
            • Consultando las pruebas de Blobstream
            • Operadores locales de Blobstream X
              • Solicitar rangos de compromiso de datos
              • Nuevas implementaciones de Blobstream X
          • Implementar un rollup
            • L2s Ethereum
              • Ethereum fallback
              • Arbitro
                • Introducci贸n a los rollups de Arbitrum con Celestia como DA
                • Implementar un arbitrum rollup devnet
                • Testnet de nitr贸geno
                • Implementar un contrato inteligente sobre la implementaci贸n de Arbitrum
                • Implemente un dapp en su devnet Arbitrum rollup
                • Optimismo
                  • Introducci贸n a la integraci贸n de OP Stack
                  • Bubs testnet
                  • Implemente un contrato inteligente en Bubs testnet
                  • Implemente un dapp en Bubs testnet
                  • Implemente un devnet OP Stack
                  • Implemente un devnet OP Stack en Celestia
                  • Auditor铆a
                  • Implemente un dapp con thirdweb
                  • Rollups-as-a-Servicio
                    • Caldera
            • Rollkit
            • Astria
              • Documentaci贸n
              • Implementar a Dusknet
            • SDK Soberano
            • Vistara
            • Dimensi贸n
          • Carteras
            • Crea una billetera con celestia-node
            • Integraciones de billeteras con Celestia
          • Integre Celestia para proveedores de servicios
      • Uni贸n
        • Arquitectura
          • CometBLS
          • Galois
          • Voyager
        • Conceptos
          • BLS Firmas
          • Clientes de Luz Condicional
          • Verificaci贸n de Consenso
          • Tecnolog铆a de validador distribuido
          • IBC
          • Sin permiso versus sin confianza
        • Infraestructura
          • Operador de nodo
            • Empezando
            • Docker Compose
            • Kubernetes
            • NixOS
            • Configuraci贸n del Nodo
        • Integracion
          • IBC Enabled Solidity
        • Demostrar
          • Dirigiendo el Union Devnet
          • PingPong
        • Unirse al testnet
          • Empezando
          • Ejecutar el binario cliente
          • Ejecuci贸n de Unionvisor
          • Obteniendo Tokens Testnet
          • Crear un Validador
          • Endpoints publicos
          • Sincronizaci贸n de estado
          • Liberar un validador
          • Preguntas frecuentes
          • Historial de actualizaciones
        • Guia de estilo
          • Lista de palabras
      • Avail
        • Introducci贸n a Avail
          • Aprovechar DA
          • Aprovechar Nexus
          • Aprovechar la fusi贸n
        • Informacion de red
        • M谩s informaci贸n sobre disponibilidad
          • El conseso
            • BABE
            • GRANDPA
            • NPoS
          • EIP-4844 y disponible
        • Guia de nuevo usuario
          • C贸mo crear y administrar una cuenta disponible
          • C贸mo utilizar el Explorador Goldberg Testnet
          • C贸mo utilizar el faucet Testnet
          • C贸mo establecer una identidad en cadena
          • C贸mo generar una identificaci贸n de aplicaci贸n disponible
          • C贸mo realizar transferencias de saldo disponibles
          • C贸mo crear grupos de nominaciones disponibles
        • Construir con disponibilidad
          • Cree un paquete acumulativo con Avail
          • Comience con Avail
          • Optimium
            • OP Stack
            • Aprovechando la pila OP con Avail
            • C贸mo utilizar la pila OP con Avail
            • Adaptador de pila OP 馃敆
          • Validium
            • Polygon zkEVM
              • Construyendo sobre Polygon zkEVM con Avail
              • C贸mo utilizar Polygon zkEVM con Avail
              • Nodo Validium 馃敆
              • Contratos de Validium 馃敆
              • Puente Validium 馃敆
            • Madara Starknet
              • Construyendo sobre Madara Stack con Avail
              • C贸mo utilizar Madara con Avail
              • Madara Starknet馃敆
            • Referencia
          • Sovereign Rollups
            • Sovereign SDK 馃敆
            • Rollkit 馃敆
            • OpEVM 馃敆
        • Glosario
        • Preguntas generales frecuentes
      • Dymension
        • Aprender
          • ELI5
          • RollApps
            • RollApps
            • Tokens
            • Gobernancia
            • Puente
            • En profundidad
              • Dymension RDK
                • Dymint
              • Gobernanza
                • Gobernador
                  • Descripci贸n general
                  • Crear gobernador
                  • Otros comandos
                • Votaci贸n
                  • Par谩metros ajustables
                  • Gasto comunitario
                  • Registro de tokens ERC-20
              • IBC Puente
                • Visi贸n general
                • Seguridad
                • Retransmisores
          • Dymension
            • Visi贸n general
            • DYM
              • Supply
              • Demanda
              • Crecimiento
              • Distribuci贸n
            • Seguridad
              • Est谩ndares
              • Actualizable
              • Disponibilidad de datos
              • Pruebas de fraude
              • Resistencia a la censura
              • Page 1
            • Puentes
              • IBC
              • eIBC
            • Liquidez
              • Descripci贸n general
              • Depositar tokens
              • Vinculaci贸n de tokens LP
              • Incentivos
              • Comisiones
            • Gobernanza
              • Descripci贸n general
              • Preparando una propuesta
              • Proponiendo a la dimocracia
        • Construir
          • Descripci贸n general
          • Testnet
            • EVM
              • Descripci贸n general
            • CosmWasm
              • Descripci贸n general
              • Informaci贸n
              • Ejemplo de cosmoWasm
          • Roller CLI
            • Descripci贸n general
            • Comenzar
              • Instalar
              • Inicializar RollApp
              • Registro
              • Correr
                • Simple
                • Avanzado
                  • Cliente ligero DA
                  • Secuenciador
                  • Retransmisor
            • Nodo en ejecuci贸n
              • Ejecutando en producci贸n
              • Supervisi贸n
              • Informaci贸n de RollApp
              • Exportar claves
              • Mejora
              • Editar la configuraci贸n de RollApp
              • Sincronizaci贸n de estado
            • Soluci贸n de problemas
              • Descripci贸n general
              • Saldos
              • Hardware
              • Rollapp de importaci贸n/exportaci贸n
              • Acceso externo
              • Estado
              • Archivos de registro
            • RollApp local
              • Ejecute la aplicaci贸n EVM RollApp
              • Ejecute la aplicaci贸n CosmWasm RollApp
        • Validar
          • Preguntas frecuentes sobre nodos
          • Construir dimensi贸n
          • Configuraci贸n de nodo
          • 脷nase a una red
          • Nodo de sincronizaci贸n
          • Validador
          • Actualizaciones
          • Soluci贸n de problemas
          • Programa de delegaci贸n
            • objetivos del programa
            • Par谩metros de evaluaci贸n
            • Solicitud
      • Movement
        • Desarrolladores
          • Inicio r谩pido
          • Configuraci贸n
            • Usando contenedores
            • Usando el instalador
          • Tutoriales
            • Desplegar
              • M贸dulo Aptos
              • M贸dulo Sui
              • Contratos EVM
                • Implementaci贸n de contratos de solidez en movimiento utilizando Foundry y Fractal
                • Implementaci贸n de contratos de solidez en M1 usando Hardhat y Fractal
                • Implementaci贸n de contratos inteligentes de Solidity en M1 utilizando el tiempo de ejecuci贸n Fractal
            • Ejecute MoveVM
              • Ejecutando M1 usted mismo
            • Construir dApp
              • Aptos Move dApp
              • Aplicaci贸n Sui Move
              • DApp de solidity
            • Interoperar
              • AptosVM<>MEVM
          • Herramientas de desarrollo
            • Movement CLI
              • Movement aptos
                • cuenta
                  • crear
                  • crear-cuenta-de-recursos
                    • derivar-direcci贸n-de-cuenta-de-recursos
                  • fondo-con-grifo
                  • lista
                  • direcci贸n de b煤squeda
                  • rotar llave
                  • transferir
                • configuraci贸n
                  • generar-compleciones-de-shell
                  • configurar-global-config
                  • show-global-config
                  • mostrar-perfiles
                • g茅nesis
                  • generar-admin-escritura-conjunto
                  • generar-g茅nesis
                  • obtener direcciones de grupo
                  • generar-claves
                  • generar-plantilla-de-dise帽o
                  • configuraci贸n-git
                  • configuraci贸n-del-validador-de-conjuntos
                • gobernancia
                  • proponer
                  • votar
                  • propuesta de show
                  • lista-propuestas
                  • verificar-propuesta
                  • ejecutar propuesta
                  • generar-propuesta-de-actualizaci贸n
                  • aprobar-ejecuci贸n-hash
                • informaci贸n
                • init
                • llave
                  • generar
                  • extraer-peer
                • mover
                  • construir-publicar-carga 煤til
                  • limpio
                  • compilar
                  • script de compilaci贸n
                  • cobertura
                    • resumen
                    • fuente
                    • c贸digo de bytes
                  • crear-cuenta-de-recursos-y-publicar-paquete
                  • desmontar
                  • documento
                  • descargar
                  • init
                  • list
                  • probar
                  • publicar
                  • correr
                  • ejecutar gui贸n
                  • prueba
                  • prueba transaccional
                  • verificar-paquete
                  • vista
                • multifirma
                  • aprobar
                  • crear
                  • crear-transacci贸n
                  • ejecutar
                  • ejecutar-rechazar
                  • ejecutar con carga 煤til
                  • rechazar
                  • verificar-propuesta
                • nodo
                  • analizar-validador-rendimiento
                  • arranque-db
                  • verificar-conectividad-de-red
                  • conseguir-participaci贸n-pool
                  • inicializar-validador
                  • conjunto de validadores de uni贸n
                  • conjunto de validadores de licencia
                  • mostrar-informaci贸n-de-茅poca
                  • mostrar-validador-config
                  • mostrar-conjunto-validador
                  • mostrar-validador-participaci贸n
                  • ejecutar-testnet-local
                  • actualizaci贸n-clave-de-consenso
                  • actualizar-validador-direcciones-de-red
                • apostar
                  • agregar apuesta
                  • crear-contrato-de-participaci贸n
                  • distribuir-monedas-adquiridas
                  • aumentar-bloqueo
                  • inicializar-propietario de la participaci贸n
                  • solicitud-comisi贸n
                  • establecer-votante-delegado
                  • operador de conjunto
                  • desbloquear-apuesta
                  • desbloquear-monedas-adquiridas
                  • retirar-apuesta
                • actualizar
              • movement sui
                • comenzar
                • g茅nesis
                • ceremonia-genesis
                  • init
                  • estado de validaci贸n
                  • agregar-validador
                  • validadores de lista
                  • punto de control de compilaci贸n sin firmar
                  • examinar-punto-de-control-g茅nesis
                  • verificar y firmar
                  • finalizar
                • herramienta clave
                  • convertir
                  • decodificar-tx-bytes
                  • decodificar-multi-sig
                  • generar
                  • importar
                  • lista
                  • par de claves de carga
                  • direcci贸n multifirma
                  • multi-sig-combinar-sig-parcial
                  • herencia-sig-parcial-combinada-multi-sig
                  • espect谩culo
                  • firmar
                  • se帽al-kms
                  • deshacer
                  • zk-login-firmar-y-ejecutar-tx
                  • zk-login-ingresar-token
                  • zk-login-sig-verificar
                  • zk-login-signo-inseguro-mensaje-personal
                • consola
                • cliente
                  • direcci贸n activa
                  • entorno-activo
                  • direcciones
                  • llamar
                  • identificador de cadena
                  • campo din谩mico
                  • env
                  • ejecutar-tx firmado
                  • gas
                  • fusionar moneda
                  • nueva direccion
                  • nuevo-ambiente
                  • objeto
                  • objetos
                  • pagar
                  • pago todo-sui
                  • pay-sui
                  • publicar
                  • moneda dividida
                  • cambiar
                  • bloque tx
                  • transferir
                  • transferencia-sui
                  • mejora
                  • verificar-bytecode-metro
                  • verificar-fuente
                  • transacci贸n-repetici贸n
                  • lote de repetici贸n
                  • punto de control de repetici贸n
                • validador
                  • hacer-informaci贸n-validador
                  • convertirse en candidato
                  • comit茅 conjunto
                  • comit茅 de licencia
                  • metadatos de visualizaci贸n
                  • actualizar-metadatos
                    • nombre
                    • descripci贸n
                    • URL de la imagen
                    • URL del proyecto
                    • direcci贸n de red
                    • direcci贸n primaria
                    • direcci贸n-trabajador
                    • direcci贸n-p2p
                    • clave-pub-de-red
                    • clave-pub-trabajador
                    • protocolo-pub-clave
                  • actualizar-precio-de-gas
                  • validador de informes
                  • serializar-carga 煤til-pop
                  • mostrar-actualizaci贸n-del-precio-del-gas-raw-txn
                • move
                  • construir
                  • cobertura
                    • resumen
                    • fuente
                    • c贸digo de bytes
                  • desmontar
                  • nuevo
                  • probar
                  • prueba
                • simulacro de incendio
                  • rotaci贸n de metadatos
              • movement ctl
              • movement manage
            • fractales
              • marco evm
          • Desarrolladores Aptos
            • Configurar la CLI de Aptos
            • Usando la CLI de Aptos
          • Desarrolladores Sui
            • Configurar Sui CLI
            • Usando Sui CLI
          • Preguntas m谩s frecuentes
        • Ecosistema
          • Wallets
          • Tokens
          • Faucet
          • Move idioma
            • M贸dulos y scripts
            • Tipos primitivos
              • Enteros
              • booleano
              • DIRECCI脫N
              • Vector
              • Firmante
              • Referencias
              • Tuplas y unidad
          • Recursos de aprendizaje
          • Techpedia
            • Paralelizaci贸n
            • Mover recursos
            • SDK de movement
      • Initia
        • ACERCA DE
          • Bienvenido a Inicia
          • Arquitectura Omnitia
            • Inicia (Capa 1)
            • Minitia (Capa 2)
          • Ciclo de vida de la transacci贸n
          • Liquidez y apuestas consagradas
            • IniciaDEX
          • Programa de intereses adquiridos
        • CONSTRUIR SOBRE LA INICIATIVA
          • iniciado
          • inicia.js
          • Creando cuenta
          • Tutoriales espec铆ficos de VM
            • MoverVM
              • Implementaci贸n de m贸dulos de movimiento
              • Creando moneda de movimiento
              • Env铆o de moneda de movimiento
              • Creando movimiento NFT
              • M贸dulos relacionados con el replanteo
              • Interactuar con Oracle en MoveVM
              • Mover ganchos IBC
            • WASMVM
              • Implementaci贸n del contrato CosmWasm
              • Interactuando con Oracle en WasmVM
              • Ganchos Wasm IBC
              • F谩brica de fichas
            • EVM
              • Implementaci贸n del contrato de solidez
              • Crear un token ERC-20 personalizado
              • Consultar estados del cosmos
              • Ejecutando mensajes de Cosmos
              • Conversi贸n de direcciones entre EVM y Cosmos
              • Conversi贸n entre direcciones Denom y ERC-20
              • Interactuar con Oracle en EVM
              • Ganchos EVM IBC
              • Ethereum JSON-RPC
          • Tutoriales generales
            • Or谩culo: Furtivo
            • Mensajes entre cadenas
            • Saltar API
            • Miniswap
              • Interactuando con Minitswap
            • Conversi贸n entre nombres de usuario y direcciones
            • Usando el Explorador local de Initia
            • Interactuando con InitiaDEX
            • Usando el widget de billetera Initia
        • IMPLEMENTAR MINITIA
          • Empezando
            • Implementaci贸n de su propia Minitia (Capa 2)
          • Configuraci贸n
          • Implementaci贸n de una Minitia independiente
          • Implementaci贸n completa de Minitia
            • Dirigiendo la Minitia
            • Pila de OPinit
              • M贸dulo OPinit: OPhost y OPchild
              • Configurar robots OPinit
                • Ejecutor del puente
                • Remitente de salida
                • Desafiador
                • Env铆o por lotes
                  • Env铆o de lotes a Inicia L1
                  • Env铆o de lotes a Celestia
            • Rel茅 Hermes (IBC)
            • Habilitando or谩culos
          • Retroceder
          • Agregar tokens a Initia Wallet
          • Personalizando Minitia
        • EJECUTAR EL NODO DE INICIO
          • Ejecutando el nodo de inicio
          • Arrancar un nodo de inicio
          • Con茅ctese a la red Inicial
          • Or谩culo
          • Automatizaci贸n de actualizaciones de software con Cosmovisor
          • Convertirse en un validador
        • RECURSOS
          • Registro de Iniciaci贸n
          • Informaci贸n de la cadena Testnet
          • Par谩metros de cadena
          • Documentaci贸n de la API
          • Documentos API (MiniMove)
          • Documentos API (MiniWasm)
          • Documentos API (MiniEVM)
      • Internet Computer
        • 隆Hola, mundo!
        • Descripci贸n general del ICP
Powered by GitBook
On this page
  • Explicaci贸n
  • Ejemplo
  1. Recursos
  2. Desarrollo
  3. Cosmwasm Documentacion
  4. Tutoriales
  5. Cosmwasm con ejemplos

Timelock

Explicaci贸n

Un contrato inteligente de bloqueo de tiempo introduce un mecanismo de retraso para ejecutar llamadas a funciones en otros contratos inteligentes. Establece un retraso de tiempo m铆nimo predefinido antes de que se pueda ejecutar una operaci贸n programada.

Si bien Timelock no es estrictamente un contrato MultiSig/Voting, se alinea estrechamente con los principios de los contratos que cumplen con las especificaciones CW3. En lugar de una ejecuci贸n inmediata, las direcciones solo pueden proponer o programar operaciones, que luego sufren un retraso antes de que se permita la ejecuci贸n final.

Creaci贸n de instancias

Al implementar el contrato Timelock, puede configurar: Plazo m铆nimo y direcciones para actuar como Administradores y Proponentes. Los proponentes s贸lo podr谩n programar operaciones si su tiempo de ejecuci贸n excede el retraso establecido.

Administradores:

Los administradores manejan la configuraci贸n inicial y garantizan la compatibilidad con posibles contratos de destino. De forma predeterminada, el iniciador del contrato se convierte en administrador si no se proporcionan otras direcciones. Despu茅s de la configuraci贸n, los administradores pueden congelar el Timelock, haci茅ndolo inmutable. Esta acci贸n es irrevocable y puede inutilizar el contrato.

Proponentes

Los proponentes programan operaciones que se ejecutar谩n despu茅s del retraso. Aseg煤rese de que el contrato Timelock tenga los permisos necesarios en los contratos de destino. Especifique las direcciones de los ejecutores responsables de la ejecuci贸n de la operaci贸n final en el contrato de destino. Si no se especifica ning煤n ejecutor, cualquier direcci贸n se puede ejecutar una vez que llegue el momento.

Info

La programaci贸n no garantiza la ejecuci贸n. Las operaciones programadas pueden ser canceladas por el proponente antes de su ejecuci贸n. Por tanto, elegir a los proponentes es crucial.

InstantiateMsg

pub struct InstantiateMsg {
  pub admins: Option<Vec<String>>,
  pub proposers: Vec<String>,
  pub min_delay: Duration,
}
Query
pub enum QueryMsg {
  GetOperationStatus {
    operation_id: Uint64,
  },
  GetExecutionTime {
    operation_id: Uint64,
  },
  GetAdmins {},
  GetOperations {
    start_after: Option<u64>,
    limit: Option<u32>,
  },
  GetMinDelay {},
  GetProposers {},
  GetExecutors {
    operation_id: Uint64,
  },
}

ExecuteMsg

pub enum ExecuteMsg {
  Schedule {
    target_address: String,
    data: Binary,
    title: String,
    description: String,
    execution_time: Scheduled,
    executors: Option<Vec<String>>,
  },
  Cancel {
    operation_id: Uint64,
  },
  Execute {
    operation_id: Uint64,
  },
  RevokeAdmin {
    admin_address: String,
  },
  AddProposer {
    proposer_address: String,
  },
  RemoveProposer {
    proposer_address: String,
  },
  UpdateMinDelay {
    new_delay: Duration,
  },
  Freeze {},
}

Ejemplo

Para crear un contrato de bloqueo de tiempo con CosmWasm, puede crear los siguientes archivos: lib.rs contract.rs msg.rs error.rs state.rs

lib.rs

pub mod contract;
mod error;
pub mod helpers;
pub mod msg;
pub mod state;
pub use crate::error::ContractError;

contract.rs

#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::WasmMsg::Execute;
use cosmwasm_std::{
    to_binary, Addr, Binary, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Order, Response, StdError,
    StdResult, Uint64,
};
use cw2::set_contract_version;
use cw_storage_plus::Bound;
use cw_utils::{Duration, Scheduled};
use std::ops::Add;
use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, OperationListResponse, QueryMsg};
use crate::state::{Operation, OperationStatus, Timelock, CONFIG, OPERATION_LIST, OPERATION_SEQ};
// version info for migration info
const CONTRACT_NAME: &str = "crates.io:timelock";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    msg: InstantiateMsg,
) -> Result<Response, ContractError> {
    let mut admins = vec![];
    match msg.admins {
        None => {
            admins.push(info.sender.clone());
        }
        Some(admin_list) => {
            for admin in admin_list {
                admins.push(deps.api.addr_validate(&admin)?);
            }
        }
    }
    admins.push(env.contract.address);
    let mut proposers = vec![];
    for proposer in msg.proposers {
        proposers.push(deps.api.addr_validate(&proposer)?);
    }
    let timelock = Timelock {
        min_time_delay: msg.min_delay,
        proposers,
        admins,
        frozen: false,
    };
    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
    OPERATION_SEQ.save(deps.storage, &Uint64::zero())?;
    CONFIG.save(deps.storage, &timelock)?;
    Ok(Response::new()
        .add_attribute("Method: ", "instantiate")
        .add_attribute("Admin: ", info.sender)
        .add_attribute(
            "Proposers: ",
            timelock
                .proposers
                .into_iter()
                .map(|item| item.to_string())
                .collect::<String>(),
        )
        .add_attribute("minTimeDelay: ", timelock.min_time_delay.to_string()))
}
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> Result<Response, ContractError> {
    match msg {
        ExecuteMsg::Schedule {
            target_address,
            data,
            title,
            description,
            execution_time,
            executors,
        } => execute_schedule(
            deps,
            _env,
            info,
            target_address,
            data,
            title,
            description,
            execution_time,
            executors,
        ),
        ExecuteMsg::Execute { operation_id } => execute_execute(deps, _env, info, operation_id),
        ExecuteMsg::Cancel { operation_id } => execute_cancel(deps, _env, info, operation_id),
        ExecuteMsg::RevokeAdmin { admin_address } => {
            execute_revoke_admin(deps, _env, info, admin_address)
        }
        ExecuteMsg::AddProposer { proposer_address } => {
            execute_add_proposer(deps, _env, info, proposer_address)
        }
        ExecuteMsg::RemoveProposer { proposer_address } => {
            execute_remove_proposer(deps, _env, info, proposer_address)
        }
        ExecuteMsg::UpdateMinDelay { new_delay } => {
            execute_update_min_delay(deps, _env, info, new_delay)
        }
        ExecuteMsg::Freeze {} => execute_freeze(deps, _env, info),
    }
}
/*eslint too-many-arguments-threshold:9 */
#[allow(clippy::too_many_arguments)]
pub fn execute_schedule(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    target_address: String,
    data: Binary,
    title: String,
    description: String,
    execution_time: Scheduled,
    executor_list: Option<Vec<String>>,
) -> Result<Response, ContractError> {
    let sender = deps.api.addr_validate(&info.sender.to_string())?;
    let target = deps.api.addr_validate(&target_address)?;
    let timelock = CONFIG.load(deps.storage)?;
    if !(timelock.proposers.contains(&sender)) {
        return Err(ContractError::Unauthorized {});
    }
    if Scheduled::AtTime(env.block.time).add(timelock.min_time_delay)? > execution_time {
        return Err(ContractError::MinDelayNotSatisfied {});
    }
    let id = OPERATION_SEQ.update::<_, StdError>(deps.storage, |id| Ok(id.add(Uint64::new(1))))?;
    let mut executors = None;
    match executor_list {
        None => {}
        Some(list) => {
            let mut checked_executors = vec![];
            for executor in list {
                checked_executors.push(deps.api.addr_validate(&executor)?);
            }
            executors = Option::from(checked_executors);
        }
    }
    let new_operation = Operation {
        id,
        status: OperationStatus::Pending,
        proposer: sender,
        executors,
        execution_time,
        target,
        data,
        title,
        description,
    };
    OPERATION_LIST.save(deps.storage, id.u64(), &new_operation)?;
    Ok(Response::new()
        .add_attribute("Schedule ", "success")
        .add_attribute("Operation ID: ", id)
        .add_attribute("Proposer: ", new_operation.proposer)
        .add_attribute("Target Address: ", new_operation.target.to_string())
        .add_attribute("Execution Time: ", new_operation.execution_time.to_string()))
}
pub fn execute_execute(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    operation_id: Uint64,
) -> Result<Response, ContractError> {
    let mut operation = OPERATION_LIST.load(deps.storage, operation_id.u64())?;
    //is delay ended
    if !operation.execution_time.is_triggered(&env.block) {
        return Err(ContractError::Unexpired {});
    }
    //has executer list if so sender is in it
    if operation.executors.is_some()
        && !operation
            .executors
            .clone()
            .map(|c| c.contains(&info.sender))
            .unwrap()
    {
        return Err(ContractError::Unauthorized {});
    }
    if operation.status == OperationStatus::Done {
        return Err(ContractError::Executed {});
    }
    //change operation status
    operation.status = OperationStatus::Done;
    OPERATION_LIST.save(deps.storage, operation_id.u64(), &operation)?;
    Ok(Response::new()
        .add_message(CosmosMsg::Wasm(Execute {
            contract_addr: operation.target.to_string(),
            msg: operation.data,
            funds: vec![],
        }))
        .add_attribute("executor", &info.sender.to_string()))
}
pub fn execute_cancel(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    operation_id: Uint64,
) -> Result<Response, ContractError> {
    let operation = OPERATION_LIST.load(deps.storage, operation_id.u64())?;
    if operation.status == OperationStatus::Done {
        return Err(ContractError::NotDeletable {});
    }
    if operation.proposer != info.sender {
        return Err(ContractError::Unauthorized {});
    }
    OPERATION_LIST.remove(deps.storage, operation_id.u64());
    Ok(Response::new()
        .add_attribute("Method", "cancel")
        .add_attribute("sender", &info.sender.to_string())
        .add_attribute("operation_id", operation_id.to_string())
        .add_attribute("Result", "Success"))
}
pub fn execute_revoke_admin(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    admin_address: String,
) -> Result<Response, ContractError> {
    let mut timelock = CONFIG.load(deps.storage)?;
    if timelock.frozen {
        return Err(ContractError::TimelockFrozen {});
    }
    if !timelock.admins.contains(&info.sender) {
        return Err(ContractError::Unauthorized {});
    }
    let admin_address = deps.api.addr_validate(&admin_address)?;
    let index = timelock
        .admins
        .iter()
        .position(|x| *x == admin_address.clone())
        .ok_or(ContractError::NotFound {
            address: admin_address.clone().to_string(),
        })?;
    timelock.admins.remove(index);
    CONFIG.save(deps.storage, &timelock)?;
    Ok(Response::new()
        .add_attribute("Method", "revoke admin")
        .add_attribute("sender", &info.sender)
        .add_attribute("Admin to revoke", admin_address)
        .add_attribute("Result", "Success"))
}
pub fn execute_add_proposer(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    proposer_address: String,
) -> Result<Response, ContractError> {
    let mut timelock = CONFIG.load(deps.storage)?;
    if timelock.frozen {
        return Err(ContractError::TimelockFrozen {});
    }
    if !timelock.admins.contains(&info.sender) {
        return Err(ContractError::Unauthorized {});
    }
    let proposer_address = deps.api.addr_validate(&proposer_address)?;
    //is in proposers list
    if timelock.proposers.contains(&proposer_address) {
        return Err(ContractError::AlreadyContainsProposerAddress {});
    }
    timelock.proposers.push(proposer_address);
    CONFIG.save(deps.storage, &timelock)?;
    Ok(Response::new()
        .add_attribute("Method", "add_proposer")
        .add_attribute("sender", &info.sender)
        .add_attribute("Result", "Success"))
}
pub fn execute_remove_proposer(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    proposer_address: String,
) -> Result<Response, ContractError> {
    let mut timelock = CONFIG.load(deps.storage)?;
    if timelock.frozen {
        return Err(ContractError::TimelockFrozen {});
    }
    if !timelock.admins.contains(&info.sender) {
        return Err(ContractError::Unauthorized {});
    }
    let proposer_address = deps.api.addr_validate(&proposer_address)?;
    //is in proposers
    let index = timelock
        .proposers
        .iter()
        .position(|x| *x == proposer_address.clone())
        .ok_or(ContractError::NotFound {
            address: proposer_address.clone().to_string(),
        })?;
    timelock.proposers.remove(index);
    CONFIG.save(deps.storage, &timelock)?;
    Ok(Response::new()
        .add_attribute("Method", "remove_proposer")
        .add_attribute("sender", &info.sender)
        .add_attribute("Result", "Success"))
}
pub fn execute_update_min_delay(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    new_delay: Duration,
) -> Result<Response, ContractError> {
    let mut timelock = CONFIG.load(deps.storage)?;
    if timelock.frozen {
        return Err(ContractError::TimelockFrozen {});
    }
    if !timelock.admins.contains(&info.sender) {
        return Err(ContractError::Unauthorized {});
    }
    timelock.min_time_delay = new_delay;
    CONFIG.save(deps.storage, &timelock)?;
    Ok(Response::new()
        .add_attribute("Method", "Update Min Delay")
        .add_attribute("Sender", &info.sender.to_string())
        .add_attribute("New Min Delay", timelock.min_time_delay.to_string())
        .add_attribute("Result", "Success"))
}
pub fn execute_freeze(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
) -> Result<Response, ContractError> {
    let mut timelock = CONFIG.load(deps.storage)?;
    if timelock.frozen {
        return Err(ContractError::TimelockFrozen {});
    }
    if !timelock.admins.contains(&info.sender) {
        return Err(ContractError::Unauthorized {});
    }
    timelock.frozen = true;
    CONFIG.save(deps.storage, &timelock)?;
    Ok(Response::new()
        .add_attribute("Method", "freeze")
        .add_attribute("sender", &info.sender)
        .add_attribute("Result", "Success"))
}
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
        QueryMsg::GetOperationStatus { operation_id } => {
            to_binary(&query_get_operation_status(deps, operation_id)?)
        }
        QueryMsg::GetExecutionTime { operation_id } => {
            to_binary(&query_get_execution_time(deps, operation_id)?)
        }
        QueryMsg::GetAdmins {} => to_binary(&query_get_admins(deps)?),
        QueryMsg::GetOperations { start_after, limit } => {
            to_binary(&query_get_operations(deps, start_after, limit)?)
        }
        QueryMsg::GetMinDelay {} => to_binary(&query_get_min_delay(deps)?),
        QueryMsg::GetProposers {} => to_binary(&query_get_proposers(deps)?),
        QueryMsg::GetExecutors { operation_id } => {
            to_binary(&query_get_executors(deps, operation_id)?)
        }
    }
}
pub fn query_get_operation_status(deps: Deps, operation_id: Uint64) -> StdResult<OperationStatus> {
    let operation = OPERATION_LIST.load(deps.storage, operation_id.u64())?;
    Ok(operation.status)
}
pub fn query_get_execution_time(deps: Deps, operation_id: Uint64) -> StdResult<String> {
    let operation = OPERATION_LIST.load(deps.storage, operation_id.u64())?;
    Ok(operation.execution_time.to_string())
}
pub fn query_get_admins(deps: Deps) -> StdResult<Vec<Addr>> {
    let timelock = CONFIG.load(deps.storage)?;
    Ok(timelock.admins)
}
// settings for pagination
const MAX_LIMIT: u32 = 30;
const DEFAULT_LIMIT: u32 = 10;
pub fn query_get_operations(
    deps: Deps,
    start_after: Option<u64>,
    limit: Option<u32>,
) -> StdResult<OperationListResponse> {
    let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize;
    let start = start_after.map(Bound::exclusive);
    let operations: StdResult<Vec<_>> = OPERATION_LIST
        .range(deps.storage, start, None, Order::Ascending)
        .take(limit)
        .collect();
    let res = OperationListResponse {
        operationList: operations?.into_iter().map(|l| l.1.into()).collect(),
    };
    Ok(res)
}
pub fn query_get_min_delay(deps: Deps) -> StdResult<String> {
    let timelock = CONFIG.load(deps.storage)?;
    Ok(timelock.min_time_delay.to_string())
}
pub fn query_get_proposers(deps: Deps) -> StdResult<Vec<Addr>> {
    let timelock = CONFIG.load(deps.storage)?;
    Ok(timelock.proposers)
}
pub fn query_get_executors(deps: Deps, operation_id: Uint64) -> StdResult<Vec<Addr>> {
    let operation = OPERATION_LIST.load(deps.storage, operation_id.u64())?;
    Ok(operation.executors.unwrap_or_default())
}
#[cfg(test)]
mod tests {
    use super::*;
    use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
    use cosmwasm_std::Timestamp;
    use cw_utils::Scheduled;
    #[test]
    fn test_no_executers() {
        let mut deps = mock_dependencies();
        let mut env = mock_env();
        env.block.time = Timestamp::from_seconds(100);
        let msg = InstantiateMsg {
            admins: Option::Some(vec!["owner".to_string(), "new_one".to_string()]),
            proposers: vec!["prop1".to_string(), "prop2".to_string()],
            min_delay: Duration::Time(10),
        };
        let info = mock_info("creator", &[]);
        let description = "test desc".to_string();
        let title = "Title Example ".to_string();
        // instantiate
        let res = instantiate(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
        println!("{:?}", res);
        let data = to_binary(&"data").unwrap();
        // try Schedule() with sender "creator"
        let res = execute_schedule(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "target".to_string(),
            data.clone(),
            title.clone(),
            description.clone(),
            Scheduled::AtTime(Timestamp::from_seconds(10)),
            Option::None,
        )
        .unwrap_err();
        assert_eq!(res, ContractError::Unauthorized {});
        //change sender to prop1
        let info = mock_info("prop1", &[]);
        //try Schedule() sender "prop1" execution_time < env.block.time
        let res = execute_schedule(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "target".to_string(),
            data.clone(),
            title.clone(),
            description.clone(),
            Scheduled::AtTime(Timestamp::from_seconds(1)),
            Option::None,
        )
        .unwrap_err();
        assert_eq!(res, ContractError::MinDelayNotSatisfied {});
        //Schedule() sender "prop1" execution_time > env.block.time && min_delay_time > execution_time - env.block.time
        let res = execute_schedule(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "target".to_string(),
            data.clone(),
            title.clone(),
            description.clone(),
            Scheduled::AtTime(Timestamp::from_seconds(120)),
            Option::None,
        )
        .unwrap();
        println!("{:?}", res);
        let res = query_get_execution_time(deps.as_ref(), Uint64::new(1));
        println!("{:?}, {}", res, env.block.time);
        //try Execute() sender "prop1" execution_time > env.block.time
        let res =
            execute_execute(deps.as_mut(), env.clone(), info.clone(), Uint64::new(1)).unwrap_err();
        assert_eq!(res, ContractError::Unexpired {});
        //time pass
        env.block.time = Timestamp::from_seconds(120);
        //try Execute() sender "prop1" execution_time <= env.block.time executors "none"
        let res =
            execute_execute(deps.as_mut(), env.clone(), info.clone(), Uint64::new(1)).unwrap();
        println!("{:?}", res);
    }
    #[test]
    fn test_with_executors() {
        let mut deps = mock_dependencies();
        let mut env = mock_env();
        env.block.time = Timestamp::from_seconds(100);
        let msg = InstantiateMsg {
            admins: Option::Some(vec!["owner".to_string(), "newone".to_string()]),
            proposers: vec!["prop1".to_string(), "prop2".to_string()],
            min_delay: Duration::Time(10),
        };
        let info = mock_info("creator", &[]);
        let title = "Title Example ".to_string();
        // instantiate
        let res = instantiate(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
        println!("{:?}", res);
        let data = to_binary(&"data").unwrap();
        let description = "test desc".to_string();
        //change sender to prop1
        let info = mock_info("prop1", &[]);
        //Schedule() sender "prop1" execution_time > env.block.time && min_delay_time > execution_time - env.block.time
        let res = execute_schedule(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "target".to_string(),
            data.clone(),
            title.clone(),
            description.clone(),
            Scheduled::AtTime(Timestamp::from_seconds(120)),
            Option::Some(vec!["exec1".to_string(), "exec2".to_string()]),
        )
        .unwrap();
        println!("{:?}", res);
        let res =
            query_get_operations(deps.as_ref(), Option::Some(0u64), Option::Some(1u32)).unwrap();
        println!("{:?}", res);
        //time pass
        env.block.time = Timestamp::from_seconds(120);
        //try Execute() sender "prop1" execution_time <= env.block.time executors "exec1, exec2"
        let res =
            execute_execute(deps.as_mut(), env.clone(), info.clone(), Uint64::new(1)).unwrap_err();
        assert_eq!(res, ContractError::Unauthorized {});
        let info = mock_info("exec1", &[]);
        //Execute() sender "exec1" execution_time <= env.block.time executors "exec1, exec2"
        let res =
            execute_execute(deps.as_mut(), env.clone(), info.clone(), Uint64::new(1)).unwrap();
        println!("{:?}", res);
    }
    #[test]
    fn test_cancel() {
        let mut deps = mock_dependencies();
        let mut env = mock_env();
        env.block.time = Timestamp::from_seconds(100);
        let msg = InstantiateMsg {
            admins: Option::Some(vec!["owner".to_string(), "newone".to_string()]),
            proposers: vec!["prop1".to_string(), "prop2".to_string()],
            min_delay: Duration::Time(10),
        };
        let info = mock_info("creator", &[]);
        let title = "Title Example ".to_string();
        // instantiate
        let res = instantiate(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
        println!("{:?}", res);
        let data = to_binary(&"data").unwrap();
        let description = "test desc".to_string();
        //change sender to prop1
        let info = mock_info("prop1", &[]);
        //Schedule() sender "prop1" execution_time > env.block.time && min_delay_time > execution_time - env.block.time
        let res = execute_schedule(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "target".to_string(),
            data.clone(),
            title.clone(),
            description.clone(),
            Scheduled::AtTime(Timestamp::from_seconds(120)),
            Option::None,
        )
        .unwrap();
        println!("{:?}", res);
        //time pass
        env.block.time = Timestamp::from_seconds(120);
        //Execute() sender "prop1" executors ""
        let res =
            execute_execute(deps.as_mut(), env.clone(), info.clone(), Uint64::new(1)).unwrap();
        println!("{:?}", res);
        //try Cancel() sender "prop1" operation_id "1" status "OperationStatus::Done"
        let res =
            execute_cancel(deps.as_mut(), env.clone(), info.clone(), Uint64::new(1)).unwrap_err();
        assert_eq!(res, ContractError::NotDeletable {});
        //Schedule() sender "prop1"
        let res = execute_schedule(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "target".to_string(),
            data.clone(),
            title.clone(),
            description.clone(),
            Scheduled::AtTime(Timestamp::from_seconds(140)),
            Option::None,
        )
        .unwrap();
        println!("{:?}", res);
        //Cancel() sender "prop1" operation_id "2" status "OperationStatus::Pending"
        let res = execute_cancel(deps.as_mut(), env.clone(), info.clone(), Uint64::new(2)).unwrap();
        println!("{:?}", res);
        //try Cancel() sender "nobody" operation_id "2" admin "creator" proposers "prop1, prop2"
        let res =
            execute_cancel(deps.as_mut(), env.clone(), info.clone(), Uint64::new(2)).unwrap_err();
        println!("{:?}", res);
        //Schedule() sender "prop1"
        let res = execute_schedule(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "target".to_string(),
            data.clone(),
            title.clone(),
            description.clone(),
            Scheduled::AtTime(Timestamp::from_seconds(140)),
            Option::None,
        )
        .unwrap();
        println!("{:?}", res);
        let info = mock_info("nobody", &[]);
        //try Cancel() sender "nobody" operation_id "3" admin "creator" proposers "prop1, prop2"
        let res =
            execute_cancel(deps.as_mut(), env.clone(), info.clone(), Uint64::new(3)).unwrap_err();
        assert_eq!(res, ContractError::Unauthorized {});
    }
    #[test]
    fn test_add_remove_proposer() {
        let mut deps = mock_dependencies();
        let mut env = mock_env();
        env.block.time = Timestamp::from_seconds(100);
        let msg = InstantiateMsg {
            admins: Option::None,
            proposers: vec![],
            min_delay: Duration::Time(10),
        };
        let info = mock_info("creator", &[]);
        // instantiate
        let res = instantiate(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
        println!("{:?}", res);
        //try remove_proposer sender "creator" proposer_address "prop1" proposers ""
        let res = execute_remove_proposer(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "prop1".to_string(),
        )
        .unwrap_err();
        assert_eq!(
            res,
            ContractError::NotFound {
                address: "prop1".to_string()
            }
        );
        let info = mock_info("no_admin", &[]);
        //try remove_proposer sender "no_admin" proposer_address "prop1" proposers ""
        let res = execute_remove_proposer(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "prop1".to_string(),
        )
        .unwrap_err();
        assert_eq!(res, ContractError::Unauthorized {});
        //try add_proposer sender "no_admin" proposer_address "prop1" proposers ""
        let res = execute_add_proposer(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "prop1".to_string(),
        )
        .unwrap_err();
        assert_eq!(res, ContractError::Unauthorized {});
        let info = mock_info("creator", &[]);
        //add_proposer sender "creator" proposer_address "prop1" proposers ""
        let res = execute_add_proposer(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "prop1".to_string(),
        )
        .unwrap();
        println!("{:?}", res);
        //remove_proposer sender "no_admin" proposer_address "prop1" proposers "prop1"
        let res = execute_remove_proposer(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "prop1".to_string(),
        )
        .unwrap();
        println!("{:?}", res);
    }
    #[test]
    fn test_update_min_delay() {
        let mut deps = mock_dependencies();
        let mut env = mock_env();
        env.block.time = Timestamp::from_seconds(100);
        let msg = InstantiateMsg {
            admins: Option::None,
            proposers: vec![],
            min_delay: Duration::Time(10),
        };
        let info = mock_info("creator", &[]);
        // instantiate
        let res = instantiate(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
        println!("{:?}", res);
        //update_min_delay() sender "creator"
        let res = execute_update_min_delay(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            Duration::Time(100),
        )
        .unwrap();
        println!("{:?}", res);
        let info = mock_info("no_admin", &[]);
        //try update_min_delay() sender "no_admin"
        let res = execute_update_min_delay(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            Duration::Time(100),
        )
        .unwrap_err();
        assert_eq!(res, ContractError::Unauthorized {});
    }
    #[test]
    fn test_revoke_admin() {
        let mut deps = mock_dependencies();
        let mut env = mock_env();
        env.block.time = Timestamp::from_seconds(100);
        let msg = InstantiateMsg {
            admins: Option::None,
            proposers: vec![],
            min_delay: Duration::Time(10),
        };
        let info = mock_info("creator", &[]);
        // instantiate
        let res = instantiate(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
        println!("{:?}", res);
        //try revoke_admin() sender "creator" admin_address "not_in_it" admin "creator"
        let res = execute_revoke_admin(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "not_in_it".to_string(),
        )
        .unwrap_err();
        assert_eq!(
            res,
            ContractError::NotFound {
                address: "not_in_it".to_string()
            }
        );
        //revoke_admin() sender "creator" admin_address "creator" admin "creator"
        let res = execute_revoke_admin(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "creator".to_string(),
        )
        .unwrap();
        println!("{:?}", res);
        //try revoke_admin() sender "creator" admin_address "creator" admin ""
        let res = execute_revoke_admin(
            deps.as_mut(),
            env.clone(),
            info.clone(),
            "creator".to_string(),
        )
        .unwrap_err();
        assert_eq!(res, ContractError::Unauthorized {});
    }
}

msg.rs

use crate::state::{Operation, OperationStatus};
use cosmwasm_std::{Addr, Binary, Uint64};
use cw_utils::{Duration, Scheduled};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
    pub admins: Option<Vec<String>>,
    pub proposers: Vec<String>,
    pub min_delay: Duration,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
    Schedule {
        target_address: String,
        data: Binary,
        title: String,
        description: String,
        execution_time: Scheduled,
        executors: Option<Vec<String>>,
    },
    Cancel {
        operation_id: Uint64,
    },
    Execute {
        operation_id: Uint64,
    },
    RevokeAdmin {
        admin_address: String,
    },
    AddProposer {
        proposer_address: String,
    },
    RemoveProposer {
        proposer_address: String,
    },
    UpdateMinDelay {
        new_delay: Duration,
    },
    Freeze {},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
    GetOperationStatus {
        operation_id: Uint64,
    },
    GetExecutionTime {
        operation_id: Uint64,
    },
    GetAdmins {},
    GetOperations {
        start_after: Option<u64>,
        limit: Option<u32>,
    },
    GetMinDelay {},
    GetProposers {},
    GetExecutors {
        operation_id: Uint64,
    },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct OperationResponse {
    pub id: Uint64,
    pub status: OperationStatus,
    pub proposer: Addr,
    pub executors: Option<Vec<Addr>>,
    pub execution_time: Scheduled,
    pub target: Addr,
    pub data: Binary,
    pub title: String,
    pub description: String,
}
//impl Into<OperationResponse> for Operation changed to from due to lint warning
impl From<Operation> for OperationResponse {
    fn from(operation: Operation) -> OperationResponse {
        OperationResponse {
            id: operation.id,
            status: operation.status,
            proposer: operation.proposer,
            executors: operation.executors,
            execution_time: operation.execution_time,
            target: operation.target,
            data: operation.data,
            title: operation.title,
            description: operation.description,
        }
    }
}
// We define a custom struct for each query response
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[allow(non_snake_case)]
pub struct OperationListResponse {
    pub operationList: Vec<OperationResponse>,
}

error.rs

use cosmwasm_std::StdError;
use thiserror::Error;
#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
    #[error("{0}")]
    Std(#[from] StdError),
    #[error("Unauthorized")]
    Unauthorized {},
    #[error("Delay time not ended")]
    Unexpired {},
    #[error("Address {address:?} not found in Proposers")]
    NotFound { address: String },
    #[error("Executed operations can not be cancelled.")]
    NotDeletable {},
    #[error("Proposers list already contains this proposer address")]
    AlreadyContainsProposerAddress {},
    #[error("Minimum Delay condition not satisfied.")]
    MinDelayNotSatisfied {},
    #[error("This operation already executed.")]
    Executed {},
    #[error("Changes can not be made on a frozen Timelock contract.")]
    TimelockFrozen {},
    // Add any other custom errors you like here.
    // Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details.
}

state.rs

use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_std::{Addr, Binary, Uint64};
use cw_storage_plus::{Item, Map};
use cw_utils::{Duration, Scheduled};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Timelock {
    pub admins: Vec<Addr>,
    pub proposers: Vec<Addr>,
    pub min_time_delay: Duration,
    pub frozen: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Operation {
    pub id: Uint64,
    pub status: OperationStatus,
    pub proposer: Addr,
    pub executors: Option<Vec<Addr>>,
    pub execution_time: Scheduled,
    pub target: Addr,
    pub data: Binary,
    pub title: String,
    pub description: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum OperationStatus {
    Pending,
    Ready,
    Done,
}
pub const CONFIG: Item<Timelock> = Item::new("timelock");
pub const OPERATION_LIST: Map<u64, Operation> = Map::new("operation_list");
pub const OPERATION_SEQ: Item<Uint64> = Item::new("operation_seq");

PreviousCrear una instancia de un contrato CosmWasmNextContrato Crowdfunding

Last updated 1 year ago

馃懡
馃帗