Skip to content

Commit 84fc1e8

Browse files
committed
feat: test_crit_accounting_mismatchand test_canAlwaysRemoveAllocation
1 parent a06b94b commit 84fc1e8

File tree

1 file changed

+148
-1
lines changed

1 file changed

+148
-1
lines changed

test/Governance.t.sol

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ contract GovernanceTest is Test {
567567
vm.stopPrank();
568568
}
569569

570+
// TODO: Broken: Fix it by simplifying most likely
570571
function test_unregisterInitiative() public {
571572
vm.startPrank(user);
572573

@@ -738,6 +739,152 @@ contract GovernanceTest is Test {
738739
vm.stopPrank();
739740
}
740741

742+
// Test: You can always remove allocation
743+
// forge test --match-test test_crit_accounting_mismatch -vv
744+
function test_crit_accounting_mismatch() public {
745+
// User setup
746+
vm.startPrank(user);
747+
address userProxy = governance.deployUserProxy();
748+
749+
lqty.approve(address(userProxy), 1_000e18);
750+
governance.depositLQTY(1_000e18);
751+
752+
vm.warp(block.timestamp + governance.EPOCH_DURATION());
753+
754+
/// Setup and vote for 2 initiatives, 0.1% vs 99.9%
755+
address[] memory initiatives = new address[](2);
756+
initiatives[0] = baseInitiative1;
757+
initiatives[1] = baseInitiative2;
758+
int176[] memory deltaLQTYVotes = new int176[](2);
759+
deltaLQTYVotes[0] = 1e18;
760+
deltaLQTYVotes[1] = 999e18;
761+
int176[] memory deltaLQTYVetos = new int176[](2);
762+
763+
governance.allocateLQTY(initiatives, deltaLQTYVotes, deltaLQTYVetos);
764+
765+
(uint256 allocatedLQTY,) = governance.userStates(user);
766+
assertEq(allocatedLQTY, 1_000e18);
767+
768+
(
769+
uint88 voteLQTY1,
770+
,
771+
uint32 averageStakingTimestampVoteLQTY1,
772+
,
773+
uint16 counted1,
774+
) = governance.initiativeStates(baseInitiative1);
775+
776+
(
777+
uint88 voteLQTY2,
778+
,
779+
,
780+
,
781+
uint16 counted2,
782+
) = governance.initiativeStates(baseInitiative2);
783+
784+
// Get power at time of vote
785+
uint256 votingPower = governance.lqtyToVotes(voteLQTY1, block.timestamp, averageStakingTimestampVoteLQTY1);
786+
assertGt(votingPower, 0, "Non zero power");
787+
788+
/// @audit TODO Fully digest and explain the bug
789+
// Warp to end so we check the threshold against future threshold
790+
791+
{
792+
vm.warp(block.timestamp + governance.EPOCH_DURATION());
793+
794+
(IGovernance.VoteSnapshot memory snapshot, IGovernance.InitiativeVoteSnapshot memory initiativeVoteSnapshot1) = governance.snapshotVotesForInitiative(baseInitiative1);
795+
(, IGovernance.InitiativeVoteSnapshot memory initiativeVoteSnapshot2) = governance.snapshotVotesForInitiative(baseInitiative2);
796+
797+
798+
(
799+
,
800+
,
801+
,
802+
,
803+
uint16 counted1again,
804+
) = governance.initiativeStates(baseInitiative1);
805+
assertEq(counted1, 1, "1 is counted inspite below voting");
806+
assertEq(counted1again, 1, "Counted is true");
807+
uint256 threshold = governance.calculateVotingThreshold();
808+
assertEq(initiativeVoteSnapshot1.votes, 0, "it didn't get votes");
809+
810+
uint256 votingPowerWithProjection = governance.lqtyToVotes(voteLQTY1, governance.epochStart() + governance.EPOCH_DURATION(), averageStakingTimestampVoteLQTY1);
811+
assertLt(votingPower, threshold, "Current Power is not enough - Desynch A");
812+
assertLt(votingPowerWithProjection, threshold, "Future Power is also not enough - Desynch B");
813+
814+
assertEq(counted1, counted2, "both counted");
815+
}
816+
}
817+
818+
// TODO: test_canAlwaysRemoveAllocation
819+
// Same setup as above (but no need for bug)
820+
// Show that you cannot withdraw
821+
// forge test --match-test test_canAlwaysRemoveAllocation -vv
822+
function test_canAlwaysRemoveAllocation() public {
823+
// User setup
824+
vm.startPrank(user);
825+
address userProxy = governance.deployUserProxy();
826+
827+
lqty.approve(address(userProxy), 1_000e18);
828+
governance.depositLQTY(1_000e18);
829+
830+
vm.warp(block.timestamp + governance.EPOCH_DURATION());
831+
832+
/// Setup and vote for 2 initiatives, 0.1% vs 99.9%
833+
address[] memory initiatives = new address[](2);
834+
initiatives[0] = baseInitiative1;
835+
initiatives[1] = baseInitiative2;
836+
int176[] memory deltaLQTYVotes = new int176[](2);
837+
deltaLQTYVotes[0] = 1e18;
838+
deltaLQTYVotes[1] = 999e18;
839+
int176[] memory deltaLQTYVetos = new int176[](2);
840+
841+
governance.allocateLQTY(initiatives, deltaLQTYVotes, deltaLQTYVetos);
842+
843+
844+
// Warp to end so we check the threshold against future threshold
845+
846+
{
847+
vm.warp(block.timestamp + governance.EPOCH_DURATION());
848+
849+
(IGovernance.VoteSnapshot memory snapshot, IGovernance.InitiativeVoteSnapshot memory initiativeVoteSnapshot1) = governance.snapshotVotesForInitiative(baseInitiative1);
850+
851+
uint256 threshold = governance.calculateVotingThreshold();
852+
assertEq(initiativeVoteSnapshot1.votes, 0, "it didn't get votes");
853+
}
854+
855+
// Roll for
856+
vm.warp(block.timestamp + governance.UNREGISTRATION_AFTER_EPOCHS() * governance.EPOCH_DURATION());
857+
governance.unregisterInitiative(baseInitiative1);
858+
859+
// @audit Warmup is not necessary
860+
// Warmup would only work for urgent veto
861+
// But urgent veto is not relevant here
862+
// TODO: Check and prob separate
863+
864+
// CRIT - I want to remove my allocation
865+
// I cannot
866+
address[] memory removeInitiatives = new address[](1);
867+
initiatives[0] = baseInitiative1;
868+
int176[] memory removeDeltaLQTYVotes = new int176[](1);
869+
deltaLQTYVotes[0] = -1e18;
870+
int176[] memory removeDeltaLQTYVetos = new int176[](1);
871+
872+
/// @audit the next call MUST not revert - this is a critical bug
873+
// vm.expectRevert("Governance: initiative-not-active");
874+
governance.allocateLQTY(removeInitiatives, removeDeltaLQTYVotes, removeDeltaLQTYVetos);
875+
876+
877+
address[] memory reAddInitiatives = new address[](1);
878+
initiatives[0] = baseInitiative1;
879+
int176[] memory reAddDeltaLQTYVotes = new int176[](1);
880+
deltaLQTYVotes[0] = -1e18;
881+
int176[] memory reAddDeltaLQTYVetos = new int176[](1);
882+
883+
/// @audit This MUST revert, an initiative should not be re-votable once disabled
884+
vm.expectRevert("Governance: initiative-not-active");
885+
governance.allocateLQTY(reAddInitiatives, reAddDeltaLQTYVotes, reAddDeltaLQTYVetos);
886+
}
887+
741888
function test_allocateLQTY() public {
742889
vm.startPrank(user);
743890

@@ -959,7 +1106,7 @@ contract GovernanceTest is Test {
9591106
vm.warp(block.timestamp + 365 days);
9601107

9611108
governance.allocateLQTY(initiatives, deltaLQTYVotes, deltaLQTYVetos);
962-
1109+
/// @audit needs overflow tests!!
9631110
vm.stopPrank();
9641111
}
9651112

0 commit comments

Comments
 (0)