Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculation of unlockable gold #10731

Merged
merged 16 commits into from
Jan 30, 2024
Merged
19 changes: 16 additions & 3 deletions packages/protocol/contracts/governance/Governance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ contract Governance is
* @return Patch version of the contract.
*/
function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) {
return (1, 4, 0, 0);
return (1, 4, 0, 1);
}

/**
Expand Down Expand Up @@ -1472,14 +1472,20 @@ contract Governance is

uint256 maxUsed = 0;
for (uint256 index = 0; index < dequeued.length; index = index.add(1)) {
Proposals.Proposal storage proposal = proposals[dequeued[index]];
uint256 proposalId = dequeued[index];
Proposals.Proposal storage proposal = proposals[proposalId];
pahor167 marked this conversation as resolved.
Show resolved Hide resolved
bool isVotingReferendum = (getProposalDequeuedStage(proposal) == Proposals.Stage.Referendum);

if (!isVotingReferendum) {
continue;
}

VoteRecord storage voteRecord = voter.referendumVotes[index];
// skip if vote record is not for this proposal
if (voteRecord.proposalId != proposalId) {
continue;
pahor167 marked this conversation as resolved.
Show resolved Hide resolved
}

uint256 votesCast = voteRecord.yesVotes.add(voteRecord.noVotes).add(voteRecord.abstainVotes);
maxUsed = Math.max(
maxUsed,
Expand Down Expand Up @@ -1515,14 +1521,21 @@ contract Governance is
Voter storage voter = voters[account];

for (uint256 index = 0; index < dequeued.length; index = index.add(1)) {
Proposals.Proposal storage proposal = proposals[dequeued[index]];
pahor167 marked this conversation as resolved.
Show resolved Hide resolved
uint256 proposalId = dequeued[index];
Proposals.Proposal storage proposal = proposals[proposalId];
bool isVotingReferendum = (getProposalDequeuedStage(proposal) == Proposals.Stage.Referendum);

if (!isVotingReferendum) {
continue;
}

VoteRecord storage voteRecord = voter.referendumVotes[index];

// skip if vote record is not for this proposal
if (voteRecord.proposalId != proposalId) {
continue;
}

uint256 sumOfVotes = voteRecord.yesVotes.add(voteRecord.noVotes).add(voteRecord.abstainVotes);

if (sumOfVotes > newVotingPower) {
Expand Down
10 changes: 7 additions & 3 deletions packages/protocol/contracts/governance/test/GovernanceTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@ contract GovernanceTest is Governance(true) {
_removeVotesWhenRevokingDelegatedVotes(account, maxAmountAllowed);
}

function setDeprecatedWeight(address voterAddress, uint256 proposalIndex, uint256 weight)
external
{
function setDeprecatedWeight(
address voterAddress,
uint256 proposalIndex,
uint256 weight,
uint256 proposalId
) external {
Voter storage voter = voters[voterAddress];
VoteRecord storage voteRecord = voter.referendumVotes[proposalIndex];
voteRecord.deprecated_weight = weight;
voteRecord.proposalId = proposalId;
}
}
37 changes: 36 additions & 1 deletion packages/protocol/test/governance/network/governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4187,6 +4187,8 @@ contract('Governance', (accounts: string[]) => {
})
pahor167 marked this conversation as resolved.
Show resolved Hide resolved

describe('proposal dequeued', () => {
const originalDequeuedIndex = 0
const proposalId = 1
beforeEach(async () => {
await governance.propose(
[transactionSuccess1.value],
Expand All @@ -4201,11 +4203,12 @@ contract('Governance', (accounts: string[]) => {
await timeTravel(dequeueFrequency, web3)
await governance.approve(1, 0)
await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes)
assertEqualBN(await governance.dequeued(originalDequeuedIndex), proposalId)
})

describe('When account voted on proposal in V8', () => {
beforeEach(async () => {
await governance.setDeprecatedWeight(accounts[0], 0, 100)
await governance.setDeprecatedWeight(accounts[0], 0, 100, 1)
})

it('Should return correct number of votes', async () => {
Expand Down Expand Up @@ -4236,6 +4239,38 @@ contract('Governance', (accounts: string[]) => {

assertEqualBN(totalVotesByAccount, 0)
})

describe('When index of proposal gets reused', () => {
const newProposalId = 2
const newDequeuedIndex = 0
beforeEach(async () => {
// expire the proposal
await timeTravel(executionStageDuration + referendumStageDuration + 1, web3)
// delete expired proposal
await governance.approve(proposalId, originalDequeuedIndex)

await governance.propose(
[transactionSuccess1.value],
[transactionSuccess1.destination],
// @ts-ignore bytes type
transactionSuccess1.data,
[transactionSuccess1.data.length],
descriptionUrl,
// @ts-ignore:
{ value: minDeposit }
)
await timeTravel(dequeueFrequency + 1, web3)
await governance.dequeueProposalsIfReady()
await governance.approve(newProposalId, newDequeuedIndex)
assertEqualBN(await governance.dequeued(newDequeuedIndex), newProposalId)
})

it('Should return 0 votes since user never voted for new proposal', async () => {
const totalVotesByAccount = await governance.getAmountOfGoldUsedForVoting(accounts[0])

assertEqualBN(totalVotesByAccount, 0)
})
})
})
})

Expand Down
24 changes: 24 additions & 0 deletions packages/sdk/contractkit/src/wrappers/Governance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,30 @@ testWithGanache('Governance Wrapper', (web3: Web3) => {
expect(voteRecord?.abstainVotes).toEqBigNumber(0)
})

it('#getVoteRecord for same index proposal', async () => {
const voter = accounts[2]
await proposeFn(accounts[0])
await timeTravel(expConfig.dequeueFrequency, web3)
await governance.dequeueProposalsIfReady().sendAndWaitForReceipt()
await approveFn()
await voteFn(voter)
// expire & delete proposal
await timeTravel(expConfig.referendumStageDuration + expConfig.executionStageDuration, web3)
await approveFn()
// propose new proposal with same index
await proposeFn(accounts[0])
await timeTravel(expConfig.dequeueFrequency, web3)
await governance.dequeueProposalsIfReady().sendAndWaitForReceipt()

const yesVotes = (await governance.getVotes(proposalID))[VoteValue.Yes]
expect(yesVotes).toEqBigNumber(0)

const voteRecord = await governance.getVoteRecord(voter, proposalID)
expect(voteRecord?.yesVotes ?? 0).toEqBigNumber(0)
pahor167 marked this conversation as resolved.
Show resolved Hide resolved
expect(voteRecord?.noVotes ?? 0).toEqBigNumber(0)
expect(voteRecord?.abstainVotes ?? 0).toEqBigNumber(0)
})

it('#votePartially', async () => {
await proposeFn(accounts[0])
await timeTravel(expConfig.dequeueFrequency, web3)
Expand Down
8 changes: 7 additions & 1 deletion packages/sdk/contractkit/src/wrappers/Governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,14 @@ export class GovernanceWrapper extends BaseWrapperForGoverning<Governance> {
try {
const proposalIndex = await this.getDequeueIndex(proposalID)
const res = await this.contract.methods.getVoteRecord(voter, proposalIndex).call()
const returnedProposalId = valueToBigNumber(res[0])
// Vote record is for a different historical proposal with same index
if (returnedProposalId.toString() !== proposalID.toString()) {
return null
}

return {
proposalID: valueToBigNumber(res[0]),
proposalID: returnedProposalId,
value: Object.keys(VoteValue)[valueToInt(res[1])] as VoteValue,
votes: valueToBigNumber(res[2]),
yesVotes: valueToBigNumber(res[3]),
Expand Down
Loading