Skip to content

Commit

Permalink
Merge pull request #91 from liquity/avoid-storage-manipulation
Browse files Browse the repository at this point in the history
Avoid storage manipulation in `Governance` tests
  • Loading branch information
danielattilasimon authored Dec 3, 2024
2 parents 48afaad + 0965663 commit c326f0c
Showing 1 changed file with 57 additions and 118 deletions.
175 changes: 57 additions & 118 deletions test/Governance.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,33 @@ import {MockStakingV1} from "./mocks/MockStakingV1.sol";
import {MockStakingV1Deployer} from "./mocks/MockStakingV1Deployer.sol";
import "./constants.sol";

contract GovernanceTester is Governance {
constructor(
address _lqty,
address _lusd,
address _stakingV1,
address _bold,
Configuration memory _config,
address _owner,
address[] memory _initiatives
) Governance(_lqty, _lusd, _stakingV1, _bold, _config, _owner, _initiatives) {}

function tester_setVotesSnapshot(VoteSnapshot calldata _votesSnapshot) external {
votesSnapshot = _votesSnapshot;
}

function tester_setVotesForInitiativeSnapshot(
address _initiative,
InitiativeVoteSnapshot calldata _votesForInitiativeSnapshot
) external {
votesForInitiativeSnapshot[_initiative] = _votesForInitiativeSnapshot;
}

function tester_setBoldAccrued(uint256 _boldAccrued) external {
boldAccrued = _boldAccrued;
}
}

abstract contract GovernanceTest is Test {
ILQTY internal lqty;
ILUSD internal lusd;
Expand All @@ -43,7 +70,7 @@ abstract contract GovernanceTest is Test {
uint32 private constant EPOCH_DURATION = 604800;
uint32 private constant EPOCH_VOTING_CUTOFF = 518400;

Governance private governance;
GovernanceTester private governance;
address[] private initialInitiatives;

address private baseInitiative2;
Expand All @@ -70,7 +97,7 @@ abstract contract GovernanceTest is Test {
epochVotingCutoff: EPOCH_VOTING_CUTOFF
});

governance = new Governance(
governance = new GovernanceTester(
address(lqty), address(lusd), address(stakingV1), address(lusd), config, address(this), new address[](0)
);

Expand Down Expand Up @@ -300,7 +327,7 @@ abstract contract GovernanceTest is Test {
}

function test_getLatestVotingThreshold() public {
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand All @@ -326,23 +353,15 @@ abstract contract GovernanceTest is Test {

// check that votingThreshold is is high enough such that MIN_CLAIM is met
IGovernance.VoteSnapshot memory snapshot = IGovernance.VoteSnapshot(1e18, 1);
vm.store(
address(governance),
bytes32(uint256(3)),
bytes32(abi.encodePacked(uint16(snapshot.forEpoch), uint240(snapshot.votes)))
);
(uint240 votes, uint16 forEpoch) = governance.votesSnapshot();
assertEq(votes, 1e18);
assertEq(forEpoch, 1);
governance.tester_setVotesSnapshot(snapshot);

uint256 boldAccrued = 1000e18;
vm.store(address(governance), bytes32(uint256(2)), bytes32(abi.encode(boldAccrued)));
assertEq(governance.boldAccrued(), 1000e18);
governance.tester_setBoldAccrued(boldAccrued);

assertEq(governance.getLatestVotingThreshold(), MIN_CLAIM / 1000);

// check that votingThreshold is 4% of votes of previous epoch
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand All @@ -364,18 +383,10 @@ abstract contract GovernanceTest is Test {
);

snapshot = IGovernance.VoteSnapshot(10000e18, 1);
vm.store(
address(governance),
bytes32(uint256(3)),
bytes32(abi.encodePacked(uint16(snapshot.forEpoch), uint240(snapshot.votes)))
);
(votes, forEpoch) = governance.votesSnapshot();
assertEq(votes, 10000e18);
assertEq(forEpoch, 1);
governance.tester_setVotesSnapshot(snapshot);

boldAccrued = 1000e18;
vm.store(address(governance), bytes32(uint256(2)), bytes32(abi.encode(boldAccrued)));
assertEq(governance.boldAccrued(), 1000e18);
governance.tester_setBoldAccrued(boldAccrued);

assertEq(governance.getLatestVotingThreshold(), 10000e18 * 0.04);
}
Expand All @@ -390,7 +401,7 @@ abstract contract GovernanceTest is Test {
) public {
_votingThresholdFactor = _votingThresholdFactor % 1e18;
/// Clamp to prevent misconfig
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand All @@ -412,17 +423,8 @@ abstract contract GovernanceTest is Test {
);

IGovernance.VoteSnapshot memory snapshot = IGovernance.VoteSnapshot(_votes, _forEpoch);
vm.store(
address(governance),
bytes32(uint256(3)),
bytes32(abi.encodePacked(uint16(snapshot.forEpoch), uint240(snapshot.votes)))
);
(uint240 votes, uint16 forEpoch) = governance.votesSnapshot();
assertEq(votes, _votes);
assertEq(forEpoch, _forEpoch);

vm.store(address(governance), bytes32(uint256(2)), bytes32(abi.encode(_boldAccrued)));
assertEq(governance.boldAccrued(), _boldAccrued);
governance.tester_setVotesSnapshot(snapshot);
governance.tester_setBoldAccrued(_boldAccrued);

governance.getLatestVotingThreshold();
}
Expand All @@ -433,13 +435,7 @@ abstract contract GovernanceTest is Test {
address userProxy = governance.deployUserProxy();

IGovernance.VoteSnapshot memory snapshot = IGovernance.VoteSnapshot(1e18, 1);
vm.store(
address(governance),
bytes32(uint256(3)),
bytes32(abi.encodePacked(uint16(snapshot.forEpoch), uint240(snapshot.votes)))
);
(uint240 votes,) = governance.votesSnapshot();
assertEq(votes, 1e18);
governance.tester_setVotesSnapshot(snapshot);

// should revert if the `REGISTRATION_FEE` > `lusd.balanceOf(msg.sender)`
_expectInsufficientAllowanceAndBalance();
Expand Down Expand Up @@ -488,14 +484,7 @@ abstract contract GovernanceTest is Test {
address userProxy = governance.deployUserProxy();

IGovernance.VoteSnapshot memory snapshot = IGovernance.VoteSnapshot(1e18, 1);
vm.store(
address(governance),
bytes32(uint256(3)),
bytes32(abi.encodePacked(uint16(snapshot.forEpoch), uint240(snapshot.votes)))
);
(uint240 votes, uint16 forEpoch) = governance.votesSnapshot();
assertEq(votes, 1e18);
assertEq(forEpoch, 1);
governance.tester_setVotesSnapshot(snapshot);

vm.stopPrank();

Expand Down Expand Up @@ -530,14 +519,7 @@ abstract contract GovernanceTest is Test {
governance.unregisterInitiative(baseInitiative3);

snapshot = IGovernance.VoteSnapshot(1e18, governance.epoch() - 1);
vm.store(
address(governance),
bytes32(uint256(3)),
bytes32(abi.encodePacked(uint16(snapshot.forEpoch), uint240(snapshot.votes)))
);
(votes, forEpoch) = governance.votesSnapshot();
assertEq(votes, 1e18);
assertEq(forEpoch, governance.epoch() - 1);
governance.tester_setVotesSnapshot(snapshot);

vm.warp(block.timestamp + governance.EPOCH_DURATION() * UNREGISTRATION_AFTER_EPOCHS);

Expand Down Expand Up @@ -1486,14 +1468,7 @@ abstract contract GovernanceTest is Test {
address userProxy = governance.deployUserProxy();
IGovernance.VoteSnapshot memory snapshot = IGovernance.VoteSnapshot(1e18, 1);
vm.store(
address(governance),
bytes32(uint256(3)),
bytes32(abi.encodePacked(uint16(snapshot.forEpoch), uint240(snapshot.votes)))
);
(uint240 votes, uint16 forEpoch) = governance.votesSnapshot();
assertEq(votes, 1e18);
assertEq(forEpoch, 1);
governance.tester_setVotesSnapshot(snapshot);
vm.startPrank(lusdHolder);
lusd.transfer(user, 2e18);
Expand Down Expand Up @@ -1521,54 +1496,18 @@ abstract contract GovernanceTest is Test {
// check that votingThreshold is is high enough such that MIN_CLAIM is met
snapshot = IGovernance.VoteSnapshot(1, governance.epoch() - 1);
vm.store(
address(governance),
bytes32(uint256(3)),
bytes32(abi.encodePacked(uint16(snapshot.forEpoch), uint240(snapshot.votes)))
);
(votes, forEpoch) = governance.votesSnapshot();
assertEq(votes, 1);
assertEq(forEpoch, governance.epoch() - 1);
governance.tester_setVotesSnapshot(snapshot);
IGovernance.InitiativeVoteSnapshot memory initiativeSnapshot =
IGovernance.InitiativeVoteSnapshot(1, governance.epoch() - 1, governance.epoch() - 1, 0);
vm.store(
address(governance),
keccak256(abi.encode(address(mockInitiative), uint256(4))),
bytes32(
abi.encodePacked(
uint16(initiativeSnapshot.lastCountedEpoch),
uint16(initiativeSnapshot.forEpoch),
uint224(initiativeSnapshot.votes)
)
)
);
(uint224 votes_, uint16 forEpoch_, uint16 lastCountedEpoch,) =
governance.votesForInitiativeSnapshot(address(mockInitiative));
assertEq(votes_, 1);
assertEq(forEpoch_, governance.epoch() - 1);
assertEq(lastCountedEpoch, governance.epoch() - 1);
governance.tester_setVotesForInitiativeSnapshot(address(mockInitiative), initiativeSnapshot);
governance.claimForInitiative(address(mockInitiative));
vm.warp(block.timestamp + governance.EPOCH_DURATION());
initiativeSnapshot = IGovernance.InitiativeVoteSnapshot(0, governance.epoch() - 1, 0, 0);
vm.store(
address(governance),
keccak256(abi.encode(address(mockInitiative), uint256(4))),
bytes32(
abi.encodePacked(
uint16(initiativeSnapshot.lastCountedEpoch),
uint16(initiativeSnapshot.forEpoch),
uint224(initiativeSnapshot.votes)
)
)
);
(votes_, forEpoch_, lastCountedEpoch,) = governance.votesForInitiativeSnapshot(address(mockInitiative));
assertEq(votes_, 0, "votes");
assertEq(forEpoch_, governance.epoch() - 1, "forEpoch_");
assertEq(lastCountedEpoch, 0, "lastCountedEpoch");
governance.tester_setVotesForInitiativeSnapshot(address(mockInitiative), initiativeSnapshot);
vm.warp(block.timestamp + governance.EPOCH_DURATION() * 4);
Expand Down Expand Up @@ -1609,7 +1548,7 @@ abstract contract GovernanceTest is Test {

function test_voting_power_increase() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -1738,7 +1677,7 @@ abstract contract GovernanceTest is Test {
// increase in user voting power and initiative voting power should be equivalent
function test_voting_power_in_same_epoch_as_allocation() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -1827,7 +1766,7 @@ abstract contract GovernanceTest is Test {
// |====== epoch 1=====|==== epoch 2 =====|==== epoch 3 ====|
function test_voting_power_increase_in_an_epoch() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -1887,7 +1826,7 @@ abstract contract GovernanceTest is Test {
// checking that voting power calculated from lqtyAllocatedByUserToInitiative is equivalent to the voting power using values returned by userStates
function test_voting_power_lqtyAllocatedByUserToInitiative() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -1936,7 +1875,7 @@ abstract contract GovernanceTest is Test {
// checking if allocating to a different initiative in a different epoch modifies the avgStakingTimestamp
function test_average_timestamp() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -1988,7 +1927,7 @@ abstract contract GovernanceTest is Test {
// forge test --match-test test_average_timestamp_same_initiative -vv
function test_average_timestamp_same_initiative() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -2038,7 +1977,7 @@ abstract contract GovernanceTest is Test {
// checking if allocating to same initiative modifies the average timestamp
function test_average_timestamp_allocate_same_initiative_fuzz(uint256 allocateAmount) public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -2094,7 +2033,7 @@ abstract contract GovernanceTest is Test {

function test_voting_snapshot_start_vs_end_epoch() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -2169,7 +2108,7 @@ abstract contract GovernanceTest is Test {
// checks that there's no difference to resulting voting power from allocating at start or end of epoch
function test_voting_power_no_difference_in_allocating_start_or_end_of_epoch() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -2241,7 +2180,7 @@ abstract contract GovernanceTest is Test {
// deallocating is correctly reflected in voting power for next epoch
function test_voting_power_decreases_next_epoch() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -2303,7 +2242,7 @@ abstract contract GovernanceTest is Test {
// checking if deallocating changes the averageStakingTimestamp
function test_deallocating_decreases_avg_timestamp() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down Expand Up @@ -2350,7 +2289,7 @@ abstract contract GovernanceTest is Test {
// vetoing shouldn't affect voting power of the initiative
function test_vote_and_veto() public {
// =========== epoch 1 ==================
governance = new Governance(
governance = new GovernanceTester(
address(lqty),
address(lusd),
address(stakingV1),
Expand Down

0 comments on commit c326f0c

Please sign in to comment.