AnsehenDAO ("ánsiindao") es una plataforma de gestión de reputación que busca premiar las contribuciones que sus miembros realizan a la organización. Los fondos se reparten a los miembros en base a su reputación en cada ronda de reparto.
El nombre AnsehenDAO viene de la unión de Ansehen y DAO, donde Ansehen significa "reputación" en alemán y DAO, del inglés Decentralized Autonomous Organization, significa "organización autónoma descentralizada".
Los miembros "contribuyentes" aportan distintos tipos de acciones off-chain a la organización, ya sea trabajo físico o intelectual; mientras que la organización, a través de sus miembros "administradores", realizan distintas rondas de votación con fondos que la organización consigue para repartir (on-chain) entre sus contribuyentes en base a la reputación de cada contribuyente en cada ronda, esta reputación es calculada a partir de los votos que cada contribuyente realiza en las rondas. Los contribuyentes con mayor reputación tendrán a su vez mayor poder de voto. Al finalizar cada ronda se entregan certificados NFT a los 3 contribuyentes con mayor reputación y se reinicializan los valores de reputación y cantidad de votos emitidos de cada contribuyente.
-
Se emiten tres tipos de eventos, uno cuando se crea una ronda de votación (
NewRound
), uno cuando se cierra la ronda de votación (CloseRound
) y otro cuando se emite un voto (VoteCast
). -
Los votos se pueden emitir pero no eliminar, para evitar que una vez emitidos los votos, algún contribuyente elimine los suyos y con mayor reputación cambie su votación.
-
El
storage
del contrato tiene los siguientes campos:-
rounds
: es un mapping que almacena todas las rondas creadas, recuperables con su ID que es un número creciente, comenzando por 1 siendo la última ronda creada la almacenada en el campocurrent_round_id
. -
current_round_id
: ID de la última ronda creada. Se considera un sistema con una sola ronda activa a la vez -
min_elapsed_milliseconds
: tiempo mínimo para que una ronda quede abierta. -
members
: un mapping que almacena los id de todos los miembros y su rol (admin
,contributor
). -
contributors
: un mapping que almacena los id de todos los contribuyentes y su información actual, la cual consta de la reputación y los votos emitidos en la ronda actual. -
contributors_list
: lista con todos los id de los contribuyentes para poder iterar sobre ellos al momento de hacer la distribución de los fondos y el reseteo de los valores de reputación y votos emitidos. Este campo fue marcado comoLazy
para evitar que se cargue con cada llamada al contrato, ya que es un vector. -
nft_ref
: una referencia al contrato de los NFT, recompensa para los tres contribuyentes con mayor reputación.
-
-
El cálculo de la reputación de un contribuyente se realiza con la ecuación propuesta en el enunciado. Con la modificación de que el cálculo de la raíz cuadrada de la reputación del que emite el voto se realiza con una fórmula rápida que da un resultado aproximado (archivo
tools.rs
). -
Se pueden agregar mas de un administrador a la organización, sin embargo al eliminarlos el que elimina no puede auto-eliminarse para evitar que se quede sin administradores la organización.
-
Se pueden agregar y eliminar contribuyentes a la organización, sin embargo no debe estar activa una ronda para evitar manipulaciones mientras se vota.
-
Una ronda puede ser abierta solo si no hay una ya abierta no finalizada y el contrato tiene suficientes fondos (según el valor pasado por parámetro) y que quede al menos la cantidad mínima de existencia.
-
Al cerrar una ronda se calculan las cantidades que le corresponde a cada contribuyente, se resetean su valores y luego se envían los NFT a los 3 contribuyentes con mayor reputación, esta se realiza ordenando una lista temporal que se crea y se van sacando del final (
.pop()
) en caso de no haber contribuyentes simplemente no se envían los NFTs. -
Se tienen métodos de consulta para saber el tiempo mínimo para una ronda, la dirección del contrato para hacer aportes y el tiempo (timestamp) actual.
-
Por otro lado se implementa el trait
VoteTrait
el cual permite emitir un voto y consultar la reputación. -
Todos los mensajes (transacciones) devuelven un
Result
con el valor correspondiente o nada, o un error de los definidos en el archivo de errores, en principio no debería generar ningún panic.
-
Las pruebas de integración deberían ampliarse para cubrir todos los casos válidos y todos los casos de error, ya se que comprueban muchas situaciones.
-
Los NFT podrían almacenar mas información sobre la ronda, reputación, cantidad de votantes, etc.
-
Se podría crear una UI para interactuar con la organización de forma mas sencilla, ya que es uno de los mayores obstáculos en el mundo de la blockchain.
- Web: https://www.rust-lang.org/tools/install
- Acción:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- Webs:
- Acciones:
rustup install 1.72
rustup default 1.72
rustup component add rust-src --toolchain 1.72
rustup component add clippy --toolchain 1.72
rustup target add wasm32-unknown-unknown --toolchain 1.72
cargo install --force --version 3.2.0 cargo-contract
cargo check
- Web: https://github.com/paritytech/substrate-contracts-node/releases
- Acciones:
- Descargar
substrate-contracts-node-linux.tar.gz
- Colocar
substrate-contracts-node
en una carpeta del PATH del sistema
- Descargar
Software | Versión |
---|---|
OS | Debian Testing (13 "trixie") |
rustup | 1.26.0 (5af9b9484 2023-04-05) |
rustc | 1.72.0 (5680fa18f 2023-08-23) |
cargo | 1.72.0 (103a7ff2e 2023-08-15) |
cargo-contract | 3.2.0-unknown-x86_64-unknown-linux-gnu |
substrate-contracts-node | 0.31.0-c8863fe08b7 |
cargo test --lib --features e2e-tests -- --nocapture
cargo contract build --target wasm --manifest-path contracts/organization/Cargo.toml
# Resultado en: target/ink/nft/nft.contract
cargo contract build --target wasm --manifest-path contracts/nft/Cargo.toml
# Resultado en: target/ink/organization/organization.contract
- Ejecutar
substrate-contracts-node
- Webs:
Objetivo: Armar una organización que premie a sus contribuyentes según su reputación.
- Configurar el entorno de desarrollo local
- Generar un contrato flipper
- Generar un repositorio git personal para el seguimiento del trabajo práctico
- Subir el código del contrato generado
- Compartir el repositorio en el canal de discord para el trackeo del mismo
cargo contract new flipper cd flipper cargo test --package flipper --lib -- flipper::tests --nocapture cargo contract build --target wasm git init git add . git commit -m "class #1" git branch -M master git remote add origin [email protected]:schcriher/curso-ink.git git push -u origin master
Modificar el smart contract para empezar a darle forma a nuestra organización:
Storage:
- Incluir a los contribuyentes con su reputación asociada (usar vectores).
- Incluir una cuenta administradora, que podrá agregar/eliminar contribuyentes.
Mensajes:
- Agregar/Eliminar contribuyente
- Votar (sólamente un contribuyente puede votar a otro)
- Consultar reputación de contribuyente
Notas: para esta etapa del desarrollo se asumen las siguientes condiciones:
- La "reputación" es la suma de votos que tiene un contribuyente
- Un contribuyente puede votar infinitamente a otros contribuyentes
- Modificar el storage para utilizar Mappings en lugar de Vectores
- Modificar lógica para que el poder de voto se corresponda con la reputación del contribuyente (mayor reputación → mayor poder de voto)
- Emitir un evento por cada voto
- Agregar los siguientes controles:
- El único que puede agregar o eliminar contribuyentes es el Admin
- Los únicos que pueden votar son los contribuyentes registrados
- La reputación es privada. Cada contribuyente puede consultar únicamente la propia
Notas: Proyecto renombrado a "Organization", además se asumen las siguientes condiciones:
Hasta tener una definición mas completa de la lógica de negocio:
Se mantiene la emisión ilimitada de votos
Se mantiene la emisión de votos positivos unicamente
El poder de voto se divide en dos categorías:
- contribuyentes con menos de 10 votos: suman 1 a la reputación con cada voto
- contribuyentes con 10 o mas votos: suman 2 a la reputación con cada voto
El evento emitido en la votación contiene las direcciones del votante y el votado
- Crear un contrato PSP34 (Utilizar Templates de OpenBrush) que sirva de certificado de votación
- Transferir al contribuyente un NFT que certifique su voto
- Definir un trait que represente el comportamiento de votación e implementarlo en el contrato:
- Votar
- Obtener reputación/votos de un contribuyente
Problema de dependencias:
- Conflicto:
subxt-codegen v0.31.0
(paquete no manejado directamente) depende derustc >= 1.70
cargo-contract v3.2.0
(paquete nuevo) soportarustc > 1.69
- Acciones:
- Pasos de la sección de instalacion de Ink! (actualizado)
Notas:
- Al interactuar con un segundo contrato ya no es posible realizar pruebas unitarias con datos falsos como se estaba haciendo hasta ahora. El archivo
ink_env-4.3.0/src/engine/off_chain/impls.rs
en su funcióninstantiate_contract
(línea 488) lo define como "no implementado" con el mensaje "off-chain environment does not support contract instantiation", por lo tanto se eliminan todas las pruebas unitarias (quedan en el historial de git).
Clase teórica sobre Chain Extensions, sin cambios en el proyecto.
- Agregar tests de integración y E2E al código de la clase #4. No hace falta que cubran el 100% del código.
Notas:
- Se agregó una prueba unitaria, no se agregaron pruebas de integración debido a que el contrato principal instancia un segundo contrato y para probar esto es necesario hacerlo on-chain, y por úlitmo se agregaron pruebas end-2-end que testean las cuatro funciones para casos correctos, en las cuales se hizo uso de macros para disminuir la cantidad de líneas de código.
- El testeo de casos de error se deja para la entrega final.
Enunciado final: El objetivo del trabajo práctico es crear una plataforma de gestión de reputación según las contribuciones realizadas a una organización.
Reglas:
-
Organización
- Una organización tiene miembros.
- Los miembros tienen roles: Admin o Contributor.
- Los contributors participan haciendo aportes off-chain.
- Los aportes off-chain se valorizarán mediante votos on-chain entre contributors.
- La organización, mediante su Admin, abrirá rondas de votación con una duración determinada que podrá variar entre las diferentes rondas.
- Al momento de crear la ronda de votación, el Admin deberá indicar:
- el monto de fondos a repartir entre los contributors.
- la cantidad de votos que podrá efectuar cada uno de ellos.
- Los fondos deberán ser cargados por el Admin.
-
Votación
- Los contributors podrán votar de forma positiva o negativa a otros contributors.
- Estos votos impactarán en el valor de reputación del contributor votado.
- El valor de reputación de un contributor nunca podrá ser menor a 1.
- El poder de voto de cada contributor será proporcional a su valor de reputación. La fórmula quedará a criterio de cada uno.
- Ejemplo: f(member_pts, target_pts, value) = target_pts + value * sqrroot(member_pts)
- Value = +PTS o -PTS
-
Premiación
- Al finalizar la ronda de votación, los fondos se repartirán entre los contributors en base a su valor de reputación a partir de una transacción ejecutada por el Admin.
- Luego de que se repartan los fondos, los valores de reputación se resetearán.
- Se entregarán badges (NFTs) a los 3 contributors con mayor valor de reputación (Gold, Silver and Bronze).
Entregable:
- Se deberá presentar un repositorio de código con los contratos.
- El README del repo deberá contener la explicación de la solución.