UNPKG

@vechain/vebetterdao-contracts

Version:

Open-source repository that houses the smart contracts powering the decentralized VeBetterDAO on the VeChain Thor blockchain.

137 lines (136 loc) 7.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const mocha_1 = require("mocha"); const chai_1 = require("chai"); const hardhat_1 = require("hardhat"); const typechain_types_1 = require("../../../typechain-types"); const common_1 = require("../../helpers/common"); const fixture_test_1 = require("../fixture.test"); /** * V3 widens updateMilestoneMetadataURI from proposer-only to * proposer + grants receiver + GRANTS_APPROVER_ROLE + GOVERNANCE_ROLE. * * In production the grants approver wallet acts as the proposer for nearly every grant, so the * receiving app cannot persist expenditure reports under the V2 rule. V3 unblocks that flow. */ (0, mocha_1.describe)("GrantsManager - V3 Metadata URI Access - @shard4k", function () { let governor; let vot3; let b3tr; let minterAccount; let proposer; let secondaryAccount; // grants receiver let outsider; let approver; let treasury; let grantsManager; let owner; let voter; let veBetterPassport; let timeLock; let grantsManagerAddress; let treasuryAddress; let emissions; let xAllocationVoting; let contractToPassToMethods; let treasuryContract; let grantsManagerInterface; (0, mocha_1.beforeEach)(async function () { const fixture = await (0, fixture_test_1.setupGovernanceFixtureWithEmissions)(); governor = fixture.governor; vot3 = fixture.vot3; b3tr = fixture.b3tr; minterAccount = fixture.minterAccount; proposer = fixture.proposer; secondaryAccount = fixture.otherAccount; treasury = fixture.treasury; grantsManager = fixture.grantsManager; owner = fixture.owner; voter = fixture.voter; veBetterPassport = fixture.veBetterPassport; timeLock = fixture.timeLock; emissions = fixture.emissions; xAllocationVoting = fixture.xAllocationVoting; outsider = fixture.otherAccounts[2]; approver = fixture.otherAccounts[3]; await emissions.connect(minterAccount).start(); await (0, fixture_test_1.setupProposer)(proposer, b3tr, vot3, minterAccount); await (0, fixture_test_1.setupVoter)(voter, b3tr, vot3, minterAccount, owner, veBetterPassport); await vot3.connect(proposer).approve(await governor.getAddress(), hardhat_1.ethers.parseEther("1000")); grantsManagerAddress = await grantsManager.getAddress(); treasuryAddress = await treasury.getAddress(); treasuryContract = await hardhat_1.ethers.getContractFactory("Treasury"); contractToPassToMethods = { b3tr, vot3, minterAccount, governor, treasury, emissions, xAllocationVoting, veBetterPassport, owner, timeLock, grantsManager, }; grantsManagerInterface = typechain_types_1.GrantsManager__factory.createInterface(); }); async function createGrantWithSecondaryReceiver() { const description = `metadata-access-${Date.now()}-${Math.random()}`; const milestonesDetailsMetadataURI = "ipfs://Qm-initial"; const values = [hardhat_1.ethers.parseEther("10000"), hardhat_1.ethers.parseEther("10000")]; const { proposalId } = await (0, common_1.createProposalWithMultipleFunctionsAndExecuteItGrant)(proposer, voter, [treasury, treasury], treasuryContract, description, ["transferB3TR", "transferB3TR"], [ [grantsManagerAddress, values[0]], [grantsManagerAddress, values[1]], ], "0", secondaryAccount.address, milestonesDetailsMetadataURI, contractToPassToMethods); return BigInt(proposalId); } (0, mocha_1.it)("reports version 3", async () => { (0, chai_1.expect)(await grantsManager.version()).to.equal(3n); }); (0, mocha_1.it)("proposer can update milestone metadata URI", async () => { const proposalId = await createGrantWithSecondaryReceiver(); const newURI = "ipfs://Qm-proposer"; await grantsManager.connect(proposer).updateMilestoneMetadataURI(proposalId, newURI); (0, chai_1.expect)((await grantsManager.getGrantProposal(proposalId)).metadataURI).to.equal(newURI); }); (0, mocha_1.it)("grants receiver can update milestone metadata URI (V3)", async () => { const proposalId = await createGrantWithSecondaryReceiver(); const newURI = "ipfs://Qm-receiver"; await grantsManager.connect(secondaryAccount).updateMilestoneMetadataURI(proposalId, newURI); (0, chai_1.expect)((await grantsManager.getGrantProposal(proposalId)).metadataURI).to.equal(newURI); }); (0, mocha_1.it)("GRANTS_APPROVER_ROLE holder can update milestone metadata URI (V3)", async () => { const proposalId = await createGrantWithSecondaryReceiver(); await grantsManager.connect(owner).grantRole(await grantsManager.GRANTS_APPROVER_ROLE(), approver.address); const newURI = "ipfs://Qm-approver"; await grantsManager.connect(approver).updateMilestoneMetadataURI(proposalId, newURI); (0, chai_1.expect)((await grantsManager.getGrantProposal(proposalId)).metadataURI).to.equal(newURI); }); (0, mocha_1.it)("GOVERNANCE_ROLE holder can update milestone metadata URI (V3)", async () => { const proposalId = await createGrantWithSecondaryReceiver(); await grantsManager.connect(owner).grantRole(await grantsManager.GOVERNANCE_ROLE(), owner.address); const newURI = "ipfs://Qm-governance"; await grantsManager.connect(owner).updateMilestoneMetadataURI(proposalId, newURI); (0, chai_1.expect)((await grantsManager.getGrantProposal(proposalId)).metadataURI).to.equal(newURI); }); (0, mocha_1.it)("unrelated account cannot update milestone metadata URI", async () => { const proposalId = await createGrantWithSecondaryReceiver(); await (0, chai_1.expect)(grantsManager.connect(outsider).updateMilestoneMetadataURI(proposalId, "ipfs://Qm-bad")).to.be.revertedWithCustomError({ interface: grantsManagerInterface }, "NotAuthorized"); }); (0, mocha_1.it)("emits MilestoneMetadataURIUpdated for every authorized writer", async () => { const proposalId = await createGrantWithSecondaryReceiver(); await grantsManager.connect(owner).grantRole(await grantsManager.GRANTS_APPROVER_ROLE(), approver.address); await (0, chai_1.expect)(grantsManager.connect(proposer).updateMilestoneMetadataURI(proposalId, "ipfs://Qm-p")) .to.emit(grantsManager, "MilestoneMetadataURIUpdated") .withArgs(proposalId, "ipfs://Qm-p"); await (0, chai_1.expect)(grantsManager.connect(secondaryAccount).updateMilestoneMetadataURI(proposalId, "ipfs://Qm-r")) .to.emit(grantsManager, "MilestoneMetadataURIUpdated") .withArgs(proposalId, "ipfs://Qm-r"); await (0, chai_1.expect)(grantsManager.connect(approver).updateMilestoneMetadataURI(proposalId, "ipfs://Qm-a")) .to.emit(grantsManager, "MilestoneMetadataURIUpdated") .withArgs(proposalId, "ipfs://Qm-a"); }); // Silence unused-import lint warnings for helpers referenced via contractToPassToMethods. void common_1.waitForCurrentRoundToEnd; });