const { time, loadFixture, } = require('@nomicfoundation/hardhat-toolbox/network-helpers'); const { expect } = require('chai'); const { ethers } = require('hardhat'); describe('DAO', () => { // We define a fixture to reuse the same setup in every test. // We use loadFixture to run this setup once, snapshot that state, // and reset Hardhat Network to that snapshot in every test. async function deployDAO() { // Contracts are deployed using the first signer/account by default const [account1, account2] = await ethers.getSigners(); const DAO = await ethers.getContractFactory('DAO'); const dao = await DAO.deploy(); return { dao, account1, account2 }; } it('Should deploy', async () => { const { dao } = await loadFixture(deployDAO); expect(dao).to.exist; expect(await dao.totalValue()).to.equal(0); }); describe('Validation Pool', () => { let dao; let account1; const POOL_DURATION = 3600; // 1 hour const fee = 100; beforeEach(async () => { const setup = await loadFixture(deployDAO); dao = setup.dao; account1 = setup.account1; const init = () => dao.initiateValidationPool(account1, POOL_DURATION, { value: fee }); await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(0); expect(await dao.validationPoolCount()).to.equal(1); expect(await dao.memberCount()).to.equal(0); expect(await dao.balanceOf(account1)).to.equal(0); }); it('should not be able to initiate a validation pool without a fee', async () => { const setup = await loadFixture(deployDAO); const init = () => setup.dao.initiateValidationPool(setup.account1, POOL_DURATION); await expect(init()).to.be.revertedWith('Fee is required to initiate validation pool'); }); it('should be able to initiate a second validation pool', async () => { const init = () => dao.initiateValidationPool(account1, POOL_DURATION, { value: fee }); await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1); expect(await dao.validationPoolCount()).to.equal(2); }); it('Should be able to fetch pool instance', async () => { const pool = await dao.validationPools(0); expect(pool).to.exist; expect(pool.duration).to.equal(POOL_DURATION); }); it('should not be able to evaluate outcome before duration has elapsed', async () => { await expect(dao.evaluateOutcome(0)).to.be.revertedWith('Pool end time has not yet arrived'); }); it('should be able to evaluate outcome after duration has elapsed', async () => { time.increase(POOL_DURATION + 1); await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(true); expect(await dao.memberCount()).to.equal(1); expect(await dao.balanceOf(account1)).to.equal(100); }); it('should not be able to evaluate outcome more than once', async () => { time.increase(POOL_DURATION + 1); await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(true); await expect(dao.evaluateOutcome(0)).to.be.revertedWith('Pool is already resolved'); }); it('should be able to evaluate outcome of second validation pool', async () => { const init = () => dao.initiateValidationPool(account1, POOL_DURATION, { value: fee }); await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1); expect(await dao.validationPoolCount()).to.equal(2); time.increase(POOL_DURATION + 1); await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(true); expect(await dao.balanceOf(account1)).to.equal(100); await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(true); expect(await dao.balanceOf(account1)).to.equal(200); }); }); });