@vechain/vebetterdao-contracts
Version:
Open-source repository that houses the smart contracts powering the decentralized VeBetterDAO on the VeChain Thor blockchain.
109 lines (108 loc) • 6.23 kB
JavaScript
import { expect } from "chai";
import { ethers } from "hardhat";
import { describe, it } from "mocha";
import { createProposal, getProposalIdFromTx, waitForCurrentRoundToEnd } from "../helpers/common";
import { setupGovernanceFixtureWithEmissions, setupProposer, setupSupporter, setupVoter, startNewRoundAndGetRoundId, } from "./fixture.test";
describe("Governance - V9 Compatibility - @shard4h", function () {
let governor;
let vot3;
let b3tr;
let b3trContract;
let minterAccount;
let proposer;
let owner;
let emissions;
let otherAccounts;
let veBetterPassport;
let xAllocationVoting;
beforeEach(async function () {
const fixture = await setupGovernanceFixtureWithEmissions();
governor = fixture.governor;
vot3 = fixture.vot3;
b3tr = fixture.b3tr;
b3trContract = fixture.b3trContract;
minterAccount = fixture.minterAccount;
proposer = fixture.proposer;
owner = fixture.owner;
otherAccounts = fixture.otherAccounts;
emissions = fixture.emissions;
veBetterPassport = fixture.veBetterPassport;
xAllocationVoting = fixture.xAllocationVoting;
await emissions.connect(minterAccount).start();
await setupProposer(proposer, b3tr, vot3, minterAccount);
await setupVoter(otherAccounts[0], b3tr, vot3, minterAccount, owner, veBetterPassport);
await setupVoter(otherAccounts[1], b3tr, vot3, minterAccount, owner, veBetterPassport);
await setupVoter(otherAccounts[2], b3tr, vot3, minterAccount, owner, veBetterPassport);
await setupVoter(otherAccounts[3], b3tr, vot3, minterAccount, owner, veBetterPassport);
});
describe("Governance - Latest Version - Proposal Lifecycle", function () {
it("Should be able to create, deposit, and cancel a proposal", async () => {
const functionToCall = "tokenDetails";
const encodedFunctionCall = b3trContract.interface.encodeFunctionData(functionToCall, []);
const tx = await createProposal(b3tr, b3trContract, proposer, `description ${this.title}`, functionToCall, []);
const proposalId = await getProposalIdFromTx(tx);
const stateBeforeCancel = await governor.state(proposalId);
expect(stateBeforeCancel).to.equal(0); // pending
await governor
.connect(proposer)
.cancel([await b3tr.getAddress()], [0], [encodedFunctionCall], ethers.keccak256(ethers.toUtf8Bytes(`description ${this.title}`)), "reason");
const stateAfterCancel = await governor.state(proposalId);
expect(stateAfterCancel).to.equal(2); // cancelled
});
it("Should be able to vote on a proposal", async () => {
const functionToCall = "tokenDetails";
const tx = await createProposal(b3tr, b3trContract, proposer, `description ${this.title}`, functionToCall, []);
const proposalId = await getProposalIdFromTx(tx);
// Deposit enough to meet threshold
const depositThreshold = await governor.proposalDepositThreshold(proposalId);
const currentDeposit = await governor.getProposalDeposits(proposalId);
if (currentDeposit < depositThreshold) {
const remaining = depositThreshold - currentDeposit;
await setupSupporter(proposer, vot3, remaining, governor);
await governor.connect(proposer).deposit(remaining, proposalId);
}
// Wait for round to become active
await waitForCurrentRoundToEnd();
await startNewRoundAndGetRoundId(emissions, xAllocationVoting);
// Cast vote
const voter = otherAccounts[0];
await governor.connect(voter).castVote(proposalId, 1); // for
expect(await governor.hasVoted(proposalId, voter.address)).to.be.true;
});
it("Should be able to mark as in development and completed", async () => {
const functionToCall = "tokenDetails";
const encodedFunctionCall = b3trContract.interface.encodeFunctionData(functionToCall, []);
const tx = await createProposal(b3tr, b3trContract, proposer, `description ${this.title}`, functionToCall, []);
const proposalId = await getProposalIdFromTx(tx);
// Deposit enough to meet threshold
const depositThreshold = await governor.proposalDepositThreshold(proposalId);
const currentDeposit = await governor.getProposalDeposits(proposalId);
if (currentDeposit < depositThreshold) {
const remaining = depositThreshold - currentDeposit;
await setupSupporter(proposer, vot3, remaining, governor);
await governor.connect(proposer).deposit(remaining, proposalId);
}
await waitForCurrentRoundToEnd();
await startNewRoundAndGetRoundId(emissions, xAllocationVoting);
// Vote for the proposal
for (let i = 0; i < 4; i++) {
await governor.connect(otherAccounts[i]).castVote(proposalId, 1); // for
}
await waitForCurrentRoundToEnd();
// Queue and execute
const descriptionHash = ethers.keccak256(ethers.toUtf8Bytes(`description ${this.title}`));
await governor.queue([await b3tr.getAddress()], [0], [encodedFunctionCall], descriptionHash);
await governor.execute([await b3tr.getAddress()], [0], [encodedFunctionCall], descriptionHash);
const stateAfterExecute = await governor.state(proposalId);
expect(stateAfterExecute).to.equal(6); // Executed
// Mark as in development
await governor.connect(owner).markAsInDevelopment(proposalId);
const stateAfterMarkInDev = await governor.state(proposalId);
expect(stateAfterMarkInDev).to.equal(8); // InDevelopment
// Mark as completed
await governor.connect(owner).markAsCompleted(proposalId);
const stateAfterMarkCompleted = await governor.state(proposalId);
expect(stateAfterMarkCompleted).to.equal(9); // Completed
});
});
});