1+ import { expect } from "chai" ;
2+ import { ethers } from "hardhat" ;
3+ import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers" ;
4+ import { BiodiversityCredits_LatinHack } from "../typechain-types" ;
5+
6+ // Describe el conjunto de pruebas para el contrato BiodiversityCredits_LatinHack con verificador por proyecto
7+ describe ( "BiodiversityCredits_LatinHack" , function ( ) {
8+
9+ let contract : BiodiversityCredits_LatinHack ;
10+ let admin : HardhatEthersSigner ;
11+ let developer : HardhatEthersSigner ;
12+ let verifier1 : HardhatEthersSigner ;
13+ let verifier2 : HardhatEthersSigner ; // Un segundo verificador para probar la lógica de permisos
14+ let creditOwner : HardhatEthersSigner ;
15+ let anotherUser : HardhatEthersSigner ;
16+
17+ const projectURI = "ipfs://some-project-metadata" ;
18+ const methodologyHash = ethers . encodeBytes32String ( "METODOLOGIA_V1" ) ;
19+ const PROJECT_ID_0 = 0 ;
20+ const STATUS_PENDING = 0 ;
21+ const STATUS_APPROVED = 1 ;
22+ const STATUS_REJECTED = 2 ;
23+
24+ beforeEach ( async function ( ) {
25+ [ admin , developer , verifier1 , verifier2 , creditOwner , anotherUser ] = await ethers . getSigners ( ) ;
26+ const Factory = await ethers . getContractFactory ( "BiodiversityCredits_LatinHack" ) ;
27+ contract = await Factory . deploy ( admin . address ) ;
28+ await contract . waitForDeployment ( ) ;
29+ } ) ;
30+
31+ describe ( "Despliegue y Roles Iniciales" , function ( ) {
32+ it ( "Debería establecer el admin correctamente en el despliegue" , async function ( ) {
33+ expect ( await contract . admin ( ) ) . to . equal ( admin . address ) ;
34+ } ) ;
35+ } ) ;
36+
37+ describe ( "Ciclo de Vida del Proyecto" , function ( ) {
38+ it ( "Debería permitir a un desarrollador registrar un nuevo proyecto" , async function ( ) {
39+ await expect ( contract . connect ( developer ) . registerProject ( verifier1 . address , projectURI , methodologyHash ) )
40+ . to . emit ( contract , "ProjectRegistered" )
41+ . withArgs ( PROJECT_ID_0 , developer . address , verifier1 . address ) ;
42+
43+ const project = await contract . projects ( PROJECT_ID_0 ) ;
44+ expect ( project . developer ) . to . equal ( developer . address ) ;
45+ expect ( project . verifier ) . to . equal ( verifier1 . address ) ;
46+ expect ( project . status ) . to . equal ( STATUS_PENDING ) ;
47+ } ) ;
48+
49+ it ( "Debería permitir al admin aprobar un proyecto" , async function ( ) {
50+ await contract . connect ( developer ) . registerProject ( verifier1 . address , projectURI , methodologyHash ) ;
51+ await expect ( contract . connect ( admin ) . updateProjectStatus ( PROJECT_ID_0 , STATUS_APPROVED ) )
52+ . to . emit ( contract , "ProjectStatusUpdated" )
53+ . withArgs ( PROJECT_ID_0 , STATUS_APPROVED ) ;
54+
55+ const project = await contract . projects ( PROJECT_ID_0 ) ;
56+ expect ( project . status ) . to . equal ( STATUS_APPROVED ) ;
57+ } ) ;
58+
59+ it ( "Debería impedir que un no-admin actualice el estado de un proyecto" , async function ( ) {
60+ await contract . connect ( developer ) . registerProject ( verifier1 . address , projectURI , methodologyHash ) ;
61+ await expect (
62+ contract . connect ( developer ) . updateProjectStatus ( PROJECT_ID_0 , STATUS_APPROVED )
63+ ) . to . be . revertedWith ( "Llamador no es el admin" ) ;
64+ } ) ;
65+ } ) ;
66+
67+ describe ( "certifyAndMintBatch (Acuñación)" , function ( ) {
68+ beforeEach ( async function ( ) {
69+ // Preparamos un proyecto aprobado para los tests de acuñación
70+ await contract . connect ( developer ) . registerProject ( verifier1 . address , projectURI , methodologyHash ) ;
71+ await contract . connect ( admin ) . updateProjectStatus ( PROJECT_ID_0 , STATUS_APPROVED ) ;
72+ } ) ;
73+
74+ it ( "Debería permitir al verificador del proyecto acuñar créditos" , async function ( ) {
75+ const amount = 100 ;
76+ const FIRST_CREDIT_ID = 0 ;
77+ await expect ( contract . connect ( verifier1 ) . certifyAndMintBatch ( PROJECT_ID_0 , creditOwner . address , amount ) )
78+ . to . emit ( contract , "CreditBatchCertified" ) ;
79+
80+ expect ( await contract . balanceOf ( creditOwner . address , FIRST_CREDIT_ID ) ) . to . equal ( amount ) ;
81+ const batchDetails = await contract . creditBatchDetails ( FIRST_CREDIT_ID ) ;
82+ expect ( batchDetails . projectId ) . to . equal ( PROJECT_ID_0 ) ;
83+ } ) ;
84+
85+ it ( "Debería impedir que un verificador de OTRO proyecto acuñe créditos" , async function ( ) {
86+ const amount = 100 ;
87+ await expect (
88+ contract . connect ( verifier2 ) . certifyAndMintBatch ( PROJECT_ID_0 , creditOwner . address , amount )
89+ ) . to . be . revertedWith ( "Llamador no es el verificador de este proyecto" ) ;
90+ } ) ;
91+
92+ it ( "Debería impedir la acuñación para un proyecto que no está aprobado" , async function ( ) {
93+ const NEW_PROJECT_ID = 1 ;
94+ await contract . connect ( developer ) . registerProject ( verifier1 . address , "uri2" , methodologyHash ) ; // Este proyecto está 'Pending'
95+ const amount = 100 ;
96+ await expect (
97+ contract . connect ( verifier1 ) . certifyAndMintBatch ( NEW_PROJECT_ID , creditOwner . address , amount )
98+ ) . to . be . revertedWith ( "El proyecto no esta aprobado" ) ;
99+ } ) ;
100+ } ) ;
101+
102+ describe ( "Funcionalidad ERC-1155 (Transferencia, Quema, Aprobación)" , function ( ) {
103+ const amountMinted = 1000 ;
104+ const FIRST_CREDIT_ID = 0 ;
105+
106+ beforeEach ( async function ( ) {
107+ // Flujo completo para tener créditos con los que trabajar
108+ await contract . connect ( developer ) . registerProject ( verifier1 . address , projectURI , methodologyHash ) ;
109+ await contract . connect ( admin ) . updateProjectStatus ( PROJECT_ID_0 , STATUS_APPROVED ) ;
110+ await contract . connect ( verifier1 ) . certifyAndMintBatch ( PROJECT_ID_0 , creditOwner . address , amountMinted ) ;
111+ } ) ;
112+
113+ it ( "Debería permitir al dueño de los créditos transferir una porción" , async function ( ) {
114+ const transferAmount = 300 ;
115+ await contract . connect ( creditOwner ) . safeTransferFrom ( creditOwner . address , anotherUser . address , FIRST_CREDIT_ID , transferAmount , "0x" ) ;
116+
117+ const ownerBalance = amountMinted - transferAmount ;
118+ expect ( await contract . balanceOf ( creditOwner . address , FIRST_CREDIT_ID ) ) . to . equal ( ownerBalance ) ;
119+ expect ( await contract . balanceOf ( anotherUser . address , FIRST_CREDIT_ID ) ) . to . equal ( transferAmount ) ;
120+ } ) ;
121+
122+ it ( "Debería permitir a un operador aprobado transferir créditos" , async function ( ) {
123+ const transferAmount = 500 ;
124+ await contract . connect ( creditOwner ) . setApprovalForAll ( admin . address , true ) ;
125+ await contract . connect ( admin ) . safeTransferFrom ( creditOwner . address , anotherUser . address , FIRST_CREDIT_ID , transferAmount , "0x" ) ;
126+
127+ const ownerBalance = amountMinted - transferAmount ;
128+ expect ( await contract . balanceOf ( creditOwner . address , FIRST_CREDIT_ID ) ) . to . equal ( ownerBalance ) ;
129+ } ) ;
130+
131+ it ( "Debería permitir al dueño de los créditos retirarlos (quemarlos)" , async function ( ) {
132+ const retireAmount = 250 ;
133+ await contract . connect ( creditOwner ) . retireCredits ( FIRST_CREDIT_ID , retireAmount ) ;
134+
135+ const ownerBalance = amountMinted - retireAmount ;
136+ expect ( await contract . balanceOf ( creditOwner . address , FIRST_CREDIT_ID ) ) . to . equal ( ownerBalance ) ;
137+ } ) ;
138+ } ) ;
139+ } ) ;
0 commit comments