From d4b4c6c9080e886459bceff354747c1d5d1fc999 Mon Sep 17 00:00:00 2001 From: jlqty <172397380+jltqy@users.noreply.github.com> Date: Tue, 8 Oct 2024 15:55:44 +0100 Subject: [PATCH 1/7] Fix bribing accounting by converting lqty to votes --- src/BribeInitiative.sol | 130 ++++---- src/Governance.sol | 2 +- src/interfaces/IBribeInitiative.sol | 14 +- src/interfaces/IInitiative.sol | 15 +- src/utils/DoubleLinkedList.sol | 6 +- test/BribeInitiative.t.sol | 16 +- test/BribeInitiativeAllocate.t.sol | 468 ++++++++++++++++------------ test/mocks/MockGovernance.sol | 13 + test/mocks/MockInitiative.sol | 8 +- 9 files changed, 385 insertions(+), 287 deletions(-) diff --git a/src/BribeInitiative.sol b/src/BribeInitiative.sol index dd313ae..d855a19 100644 --- a/src/BribeInitiative.sol +++ b/src/BribeInitiative.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; +import {console} from "forge-std/console.sol"; + import {IERC20} from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -43,13 +45,13 @@ contract BribeInitiative is IInitiative, IBribeInitiative { } /// @inheritdoc IBribeInitiative - function totalLQTYAllocatedByEpoch(uint16 _epoch) external view returns (uint88) { - return totalLQTYAllocationByEpoch.getValue(_epoch); + function totalLQTYAllocatedByEpoch(uint16 _epoch) external view returns (uint88, uint32) { + return _loadTotalLQTYAllocation(_epoch); } /// @inheritdoc IBribeInitiative - function lqtyAllocatedByUserAtEpoch(address _user, uint16 _epoch) external view returns (uint88) { - return lqtyAllocationByUserAtEpoch[_user].getValue(_epoch); + function lqtyAllocatedByUserAtEpoch(address _user, uint16 _epoch) external view returns (uint88, uint32) { + return _loadLQTYAllocation(_user, _epoch); } /// @inheritdoc IBribeInitiative @@ -96,9 +98,14 @@ contract BribeInitiative is IInitiative, IBribeInitiative { "BribeInitiative: invalid-prev-total-lqty-allocation-epoch" ); - boldAmount = uint256(bribe.boldAmount) * uint256(lqtyAllocation.value) / uint256(totalLQTYAllocation.value); - bribeTokenAmount = - uint256(bribe.bribeTokenAmount) * uint256(lqtyAllocation.value) / uint256(totalLQTYAllocation.value); + (uint88 totalLQTY, uint32 totalAverageTimestamp) = _decodeLQTYAllocation(totalLQTYAllocation.value); + uint240 totalVotes = governance.lqtyToVotes(totalLQTY, block.timestamp, totalAverageTimestamp); + if (totalVotes != 0) { + (uint88 lqty, uint32 averageTimestamp) = _decodeLQTYAllocation(lqtyAllocation.value); + uint240 votes = governance.lqtyToVotes(lqty, block.timestamp, averageTimestamp); + boldAmount = uint256(bribe.boldAmount) * uint256(votes) / uint256(totalVotes); + bribeTokenAmount = uint256(bribe.bribeTokenAmount) * uint256(votes) / uint256(totalVotes); + } claimedBribeAtEpoch[_user][_epoch] = true; @@ -129,92 +136,81 @@ contract BribeInitiative is IInitiative, IBribeInitiative { /// @inheritdoc IInitiative function onUnregisterInitiative(uint16) external virtual override onlyGovernance {} - function _setTotalLQTYAllocationByEpoch(uint16 _epoch, uint88 _value, bool _insert) private { + function _setTotalLQTYAllocationByEpoch(uint16 _epoch, uint88 _lqty, uint32 _averageTimestamp, bool _insert) + private + { + uint224 value = (uint224(_lqty) << 32) | _averageTimestamp; if (_insert) { - totalLQTYAllocationByEpoch.insert(_epoch, _value, 0); + totalLQTYAllocationByEpoch.insert(_epoch, value, 0); } else { - totalLQTYAllocationByEpoch.items[_epoch].value = _value; + totalLQTYAllocationByEpoch.items[_epoch].value = value; } - emit ModifyTotalLQTYAllocation(_epoch, _value); + emit ModifyTotalLQTYAllocation(_epoch, _lqty, _averageTimestamp); } - function _setLQTYAllocationByUserAtEpoch(address _user, uint16 _epoch, uint88 _value, bool _insert) private { + function _setLQTYAllocationByUserAtEpoch( + address _user, + uint16 _epoch, + uint88 _lqty, + uint32 _averageTimestamp, + bool _insert + ) private { + uint224 value = (uint224(_lqty) << 32) | _averageTimestamp; if (_insert) { - lqtyAllocationByUserAtEpoch[_user].insert(_epoch, _value, 0); + lqtyAllocationByUserAtEpoch[_user].insert(_epoch, value, 0); } else { - lqtyAllocationByUserAtEpoch[_user].items[_epoch].value = _value; + lqtyAllocationByUserAtEpoch[_user].items[_epoch].value = value; } - emit ModifyLQTYAllocation(_user, _epoch, _value); + emit ModifyLQTYAllocation(_user, _epoch, _lqty, _averageTimestamp); + } + + function _decodeLQTYAllocation(uint224 _value) private pure returns (uint88, uint32) { + return (uint88(_value >> 32), uint32(_value)); + } + + function _loadTotalLQTYAllocation(uint16 _epoch) private view returns (uint88, uint32) { + return _decodeLQTYAllocation(totalLQTYAllocationByEpoch.items[_epoch].value); + } + + function _loadLQTYAllocation(address _user, uint16 _epoch) private view returns (uint88, uint32) { + return _decodeLQTYAllocation(lqtyAllocationByUserAtEpoch[_user].items[_epoch].value); } /// @inheritdoc IInitiative - function onAfterAllocateLQTY(uint16 _currentEpoch, address _user, uint88 _voteLQTY, uint88 _vetoLQTY) - external - virtual - onlyGovernance - { + function onAfterAllocateLQTY( + uint16 _currentEpoch, + address _user, + IGovernance.UserState calldata _userState, + IGovernance.Allocation calldata _allocation, + IGovernance.InitiativeState calldata _initiativeState + ) external virtual onlyGovernance { uint16 mostRecentUserEpoch = lqtyAllocationByUserAtEpoch[_user].getHead(); if (_currentEpoch == 0) return; // if this is the first user allocation in the epoch, then insert a new item into the user allocation DLL if (mostRecentUserEpoch != _currentEpoch) { - uint88 prevVoteLQTY = lqtyAllocationByUserAtEpoch[_user].items[mostRecentUserEpoch].value; - uint88 newVoteLQTY = (_vetoLQTY == 0) ? _voteLQTY : 0; + uint88 newVoteLQTY = (_allocation.vetoLQTY == 0) ? _allocation.voteLQTY : 0; uint16 mostRecentTotalEpoch = totalLQTYAllocationByEpoch.getHead(); // if this is the first allocation in the epoch, then insert a new item into the total allocation DLL if (mostRecentTotalEpoch != _currentEpoch) { - uint88 prevTotalLQTYAllocation = totalLQTYAllocationByEpoch.items[mostRecentTotalEpoch].value; - if (_vetoLQTY == 0) { - // no veto to no veto - _setTotalLQTYAllocationByEpoch( - _currentEpoch, prevTotalLQTYAllocation + newVoteLQTY - prevVoteLQTY, true - ); - } else { - if (prevVoteLQTY != 0) { - // if the prev user allocation was counted in, then remove the prev user allocation from the - // total allocation (no veto to veto) - _setTotalLQTYAllocationByEpoch(_currentEpoch, prevTotalLQTYAllocation - prevVoteLQTY, true); - } else { - // veto to veto - _setTotalLQTYAllocationByEpoch(_currentEpoch, prevTotalLQTYAllocation, true); - } - } - } else { - if (_vetoLQTY == 0) { - // no veto to no veto - _setTotalLQTYAllocationByEpoch( - _currentEpoch, - totalLQTYAllocationByEpoch.items[_currentEpoch].value + newVoteLQTY - prevVoteLQTY, - false - ); - } else if (prevVoteLQTY != 0) { - // no veto to veto - _setTotalLQTYAllocationByEpoch( - _currentEpoch, totalLQTYAllocationByEpoch.items[_currentEpoch].value - prevVoteLQTY, false - ); - } - } - // insert a new item into the user allocation DLL - _setLQTYAllocationByUserAtEpoch(_user, _currentEpoch, newVoteLQTY, true); - } else { - uint88 prevVoteLQTY = lqtyAllocationByUserAtEpoch[_user].getItem(_currentEpoch).value; - if (_vetoLQTY == 0) { - // update the allocation for the current epoch by adding the new allocation and subtracting - // the previous one (no veto to no veto) _setTotalLQTYAllocationByEpoch( - _currentEpoch, - totalLQTYAllocationByEpoch.items[_currentEpoch].value + _voteLQTY - prevVoteLQTY, - false + _currentEpoch, _initiativeState.voteLQTY, _initiativeState.averageStakingTimestampVoteLQTY, true ); - _setLQTYAllocationByUserAtEpoch(_user, _currentEpoch, _voteLQTY, false); } else { - // if the user vetoed the initiative, subtract the allocation from the DLLs (no veto to veto) _setTotalLQTYAllocationByEpoch( - _currentEpoch, totalLQTYAllocationByEpoch.items[_currentEpoch].value - prevVoteLQTY, false + _currentEpoch, _initiativeState.voteLQTY, _initiativeState.averageStakingTimestampVoteLQTY, false ); - _setLQTYAllocationByUserAtEpoch(_user, _currentEpoch, 0, false); } + _setLQTYAllocationByUserAtEpoch(_user, _currentEpoch, newVoteLQTY, _userState.averageStakingTimestamp, true); + } else { + _setTotalLQTYAllocationByEpoch( + _currentEpoch, _initiativeState.voteLQTY, _initiativeState.averageStakingTimestampVoteLQTY, false + ); + uint88 newVoteLQTY = (_allocation.vetoLQTY == 0) ? _allocation.voteLQTY : 0; + _setLQTYAllocationByUserAtEpoch( + _user, _currentEpoch, newVoteLQTY, _userState.averageStakingTimestamp, false + ); } } diff --git a/src/Governance.sol b/src/Governance.sol index 2f361b3..a51b443 100644 --- a/src/Governance.sol +++ b/src/Governance.sol @@ -478,7 +478,7 @@ contract Governance is Multicall, UserProxyFactory, ReentrancyGuard, IGovernance emit AllocateLQTY(msg.sender, initiative, deltaLQTYVotes, deltaLQTYVetos, currentEpoch); try IInitiative(initiative).onAfterAllocateLQTY( - currentEpoch, msg.sender, allocation.voteLQTY, allocation.vetoLQTY + currentEpoch, msg.sender, userState, allocation, initiativeState ) {} catch {} } diff --git a/src/interfaces/IBribeInitiative.sol b/src/interfaces/IBribeInitiative.sol index 7f8838e..9d28d82 100644 --- a/src/interfaces/IBribeInitiative.sol +++ b/src/interfaces/IBribeInitiative.sol @@ -7,8 +7,8 @@ import {IGovernance} from "./IGovernance.sol"; interface IBribeInitiative { event DepositBribe(address depositor, uint128 boldAmount, uint128 bribeTokenAmount, uint16 epoch); - event ModifyLQTYAllocation(address user, uint16 epoch, uint88 lqtyAllocated); - event ModifyTotalLQTYAllocation(uint16 epoch, uint88 totalLQTYAllocated); + event ModifyLQTYAllocation(address user, uint16 epoch, uint88 lqtyAllocated, uint32 averageTimestamp); + event ModifyTotalLQTYAllocation(uint16 epoch, uint88 totalLQTYAllocated, uint32 averageTimestamp); event ClaimBribe(address user, uint16 epoch, uint256 boldAmount, uint256 bribeTokenAmount); /// @notice Address of the governance contract @@ -40,12 +40,18 @@ interface IBribeInitiative { /// @notice Total LQTY allocated to the initiative at a given epoch /// @param _epoch Epoch at which the LQTY was allocated /// @return totalLQTYAllocated Total LQTY allocated - function totalLQTYAllocatedByEpoch(uint16 _epoch) external view returns (uint88 totalLQTYAllocated); + function totalLQTYAllocatedByEpoch(uint16 _epoch) + external + view + returns (uint88 totalLQTYAllocated, uint32 averageTimestamp); /// @notice LQTY allocated by a user to the initiative at a given epoch /// @param _user Address of the user /// @param _epoch Epoch at which the LQTY was allocated by the user /// @return lqtyAllocated LQTY allocated by the user - function lqtyAllocatedByUserAtEpoch(address _user, uint16 _epoch) external view returns (uint88 lqtyAllocated); + function lqtyAllocatedByUserAtEpoch(address _user, uint16 _epoch) + external + view + returns (uint88 lqtyAllocated, uint32 averageTimestamp); /// @notice Deposit bribe tokens for a given epoch /// @dev The caller has to approve this contract to spend the BOLD and bribe tokens. diff --git a/src/interfaces/IInitiative.sol b/src/interfaces/IInitiative.sol index b530291..ddb3179 100644 --- a/src/interfaces/IInitiative.sol +++ b/src/interfaces/IInitiative.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; +import {IGovernance} from "./IGovernance.sol"; + interface IInitiative { /// @notice Callback hook that is called by Governance after the initiative was successfully registered /// @param _atEpoch Epoch at which the initiative is registered @@ -13,9 +15,16 @@ interface IInitiative { /// @notice Callback hook that is called by Governance after the LQTY allocation is updated by a user /// @param _currentEpoch Epoch at which the LQTY allocation is updated /// @param _user Address of the user that updated their LQTY allocation - /// @param _voteLQTY Allocated voting LQTY - /// @param _vetoLQTY Allocated vetoing LQTY - function onAfterAllocateLQTY(uint16 _currentEpoch, address _user, uint88 _voteLQTY, uint88 _vetoLQTY) external; + /// @param _userState User state + /// @param _allocation Allocation state from user to initiative + /// @param _initiativeState Initiative state + function onAfterAllocateLQTY( + uint16 _currentEpoch, + address _user, + IGovernance.UserState calldata _userState, + IGovernance.Allocation calldata _allocation, + IGovernance.InitiativeState calldata _initiativeState + ) external; /// @notice Callback hook that is called by Governance after the claim for the last epoch was distributed /// to the initiative diff --git a/src/utils/DoubleLinkedList.sol b/src/utils/DoubleLinkedList.sol index 7624d59..e91cb14 100644 --- a/src/utils/DoubleLinkedList.sol +++ b/src/utils/DoubleLinkedList.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.24; /// and the tail is defined as the null item's next pointer ([tail][prev][item][next][head]) library DoubleLinkedList { struct Item { - uint88 value; + uint224 value; uint16 prev; uint16 next; } @@ -53,7 +53,7 @@ library DoubleLinkedList { /// @param list Linked list which contains the item /// @param id Id of the item /// @return _ Value of the item - function getValue(List storage list, uint16 id) internal view returns (uint88) { + function getValue(List storage list, uint16 id) internal view returns (uint224) { return list.items[id].value; } @@ -81,7 +81,7 @@ library DoubleLinkedList { /// @param id Id of the item to insert /// @param value Value of the item to insert /// @param next Id of the item which should follow item `id` - function insert(List storage list, uint16 id, uint88 value, uint16 next) internal { + function insert(List storage list, uint16 id, uint224 value, uint16 next) internal { if (contains(list, id)) revert ItemInList(); if (next != 0 && !contains(list, next)) revert ItemNotInList(); uint16 prev = list.items[next].prev; diff --git a/test/BribeInitiative.t.sol b/test/BribeInitiative.t.sol index 6f8df63..35ad992 100644 --- a/test/BribeInitiative.t.sol +++ b/test/BribeInitiative.t.sol @@ -106,8 +106,14 @@ contract BribeInitiativeTest is Test { deltaVoteLQTY[0] = 1e18; int176[] memory deltaVetoLQTY = new int176[](1); governance.allocateLQTY(initiatives, deltaVoteLQTY, deltaVetoLQTY); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1e18); + (uint88 totalLQTYAllocated, uint32 averageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(averageTimestamp, block.timestamp - 365 days - 365 days); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, block.timestamp - 365 days - 365 days); // should be zero since user was not deposited at that time BribeInitiative.ClaimData[] memory epochs = new BribeInitiative.ClaimData[](1); @@ -144,8 +150,10 @@ contract BribeInitiativeTest is Test { deltaVoteLQTY[0] = -0.5e18; governance.allocateLQTY(initiatives, deltaVoteLQTY, deltaVetoLQTY); governance.allocateLQTY(initiatives, deltaVoteLQTY, deltaVetoLQTY); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 0); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + (userLQTYAllocated, userAverageTimestamp) = bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 0); + (totalLQTYAllocated, averageTimestamp) = bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 0); vm.stopPrank(); } } diff --git a/test/BribeInitiativeAllocate.t.sol b/test/BribeInitiativeAllocate.t.sol index 8fa21b1..9a57e5c 100644 --- a/test/BribeInitiativeAllocate.t.sol +++ b/test/BribeInitiativeAllocate.t.sol @@ -2,11 +2,14 @@ pragma solidity ^0.8.24; import {Test} from "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; import {MockERC20} from "forge-std/mocks/MockERC20.sol"; import {Governance} from "../src/Governance.sol"; import {BribeInitiative} from "../src/BribeInitiative.sol"; +import {IGovernance} from "../src/interfaces/IGovernance.sol"; + import {MockStakingV1} from "./mocks/MockStakingV1.sol"; import {MockGovernance} from "./mocks/MockGovernance.sol"; @@ -64,13 +67,51 @@ contract BribeInitiativeAllocateTest is Test { vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); - - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: 1}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 0 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); + } + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + + { + IGovernance.UserState memory userState2 = + IGovernance.UserState({allocatedLQTY: 1000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation2 = + IGovernance.Allocation({voteLQTY: 1000e18, vetoLQTY: 0, atEpoch: 1}); + IGovernance.InitiativeState memory initiativeState2 = IGovernance.InitiativeState({ + voteLQTY: 1001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 0 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState2, allocation2, initiativeState2); + } + + (uint88 totalLQTYAllocated2, uint32 totalAverageTimestamp2) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated2, 1001e18); + assertEq(totalAverageTimestamp2, block.timestamp); + (uint88 userLQTYAllocated2, uint32 userAverageTimestamp2) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated2, 1000e18); + assertEq(userAverageTimestamp2, block.timestamp); vm.startPrank(lusdHolder); lqty.approve(address(bribeInitiative), 1000e18); @@ -81,10 +122,27 @@ contract BribeInitiativeAllocateTest is Test { vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); - - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 2000e18, averageStakingTimestamp: uint32(1)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 2000e18, vetoLQTY: 0, atEpoch: 2}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 2001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(1), + averageStakingTimestampVetoLQTY: 0, + counted: 0 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); + } + + (totalLQTYAllocated, totalAverageTimestamp) = bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 2001e18); + assertEq(totalAverageTimestamp, 1); + (userLQTYAllocated, userAverageTimestamp) = bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 2000e18); + assertEq(userAverageTimestamp, 1); governance.setEpoch(3); @@ -94,267 +152,269 @@ contract BribeInitiativeAllocateTest is Test { claimData[0].epoch = 2; claimData[0].prevLQTYAllocationEpoch = 2; claimData[0].prevTotalLQTYAllocationEpoch = 2; - bribeInitiative.claimBribes(claimData); + (uint256 boldAmount, uint256 bribeTokenAmount) = bribeInitiative.claimBribes(claimData); + assertGt(boldAmount, 999e18); + assertGt(bribeTokenAmount, 999e18); } - function test_onAfterAllocateLQTY_newEpoch_NoVetoToVeto() public { - governance.setEpoch(1); + // function test_onAfterAllocateLQTY_newEpoch_NoVetoToVeto() public { + // governance.setEpoch(1); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); - vm.startPrank(lusdHolder); - lqty.approve(address(bribeInitiative), 1000e18); - lusd.approve(address(bribeInitiative), 1000e18); - bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - vm.stopPrank(); + // vm.startPrank(lusdHolder); + // lqty.approve(address(bribeInitiative), 1000e18); + // lusd.approve(address(bribeInitiative), 1000e18); + // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + // vm.stopPrank(); - governance.setEpoch(2); + // governance.setEpoch(2); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 0); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 0); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 0); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 0); - governance.setEpoch(3); + // governance.setEpoch(3); - vm.startPrank(address(user)); + // vm.startPrank(address(user)); - BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - claimData[0].epoch = 2; - claimData[0].prevLQTYAllocationEpoch = 2; - claimData[0].prevTotalLQTYAllocationEpoch = 2; - vm.expectRevert("BribeInitiative: invalid-prev-lqty-allocation-epoch"); // nothing to claim - bribeInitiative.claimBribes(claimData); - } + // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + // claimData[0].epoch = 2; + // claimData[0].prevLQTYAllocationEpoch = 2; + // claimData[0].prevTotalLQTYAllocationEpoch = 2; + // vm.expectRevert("BribeInitiative: invalid-prev-lqty-allocation-epoch"); // nothing to claim + // bribeInitiative.claimBribes(claimData); + // } - function test_onAfterAllocateLQTY_newEpoch_VetoToNoVeto() public { - governance.setEpoch(1); + // function test_onAfterAllocateLQTY_newEpoch_VetoToNoVeto() public { + // governance.setEpoch(1); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); - governance.setEpoch(2); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + // governance.setEpoch(2); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - vm.startPrank(lusdHolder); - lqty.approve(address(bribeInitiative), 1000e18); - lusd.approve(address(bribeInitiative), 1000e18); - bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - vm.stopPrank(); + // vm.startPrank(lusdHolder); + // lqty.approve(address(bribeInitiative), 1000e18); + // lusd.approve(address(bribeInitiative), 1000e18); + // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + // vm.stopPrank(); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - governance.setEpoch(3); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); + // governance.setEpoch(3); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); - governance.setEpoch(4); + // governance.setEpoch(4); - vm.startPrank(address(user)); + // vm.startPrank(address(user)); - BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - claimData[0].epoch = 3; - claimData[0].prevLQTYAllocationEpoch = 3; - claimData[0].prevTotalLQTYAllocationEpoch = 3; - bribeInitiative.claimBribes(claimData); - } + // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + // claimData[0].epoch = 3; + // claimData[0].prevLQTYAllocationEpoch = 3; + // claimData[0].prevTotalLQTYAllocationEpoch = 3; + // bribeInitiative.claimBribes(claimData); + // } - function test_onAfterAllocateLQTY_newEpoch_VetoToVeto() public { - governance.setEpoch(1); + // function test_onAfterAllocateLQTY_newEpoch_VetoToVeto() public { + // governance.setEpoch(1); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); - governance.setEpoch(2); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + // governance.setEpoch(2); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - governance.setEpoch(3); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - } + // governance.setEpoch(3); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + // } - function test_onAfterAllocateLQTY_sameEpoch_NoVetoToNoVeto() public { - vm.startPrank(lusdHolder); - lqty.approve(address(bribeInitiative), 1000e18); - lusd.approve(address(bribeInitiative), 1000e18); - bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - vm.stopPrank(); + // function test_onAfterAllocateLQTY_sameEpoch_NoVetoToNoVeto() public { + // vm.startPrank(lusdHolder); + // lqty.approve(address(bribeInitiative), 1000e18); + // lusd.approve(address(bribeInitiative), 1000e18); + // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + // vm.stopPrank(); - governance.setEpoch(1); + // governance.setEpoch(1); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); - governance.setEpoch(2); + // governance.setEpoch(2); - vm.startPrank(address(user)); + // vm.startPrank(address(user)); - BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - claimData[0].epoch = 1; - claimData[0].prevLQTYAllocationEpoch = 1; - claimData[0].prevTotalLQTYAllocationEpoch = 1; - bribeInitiative.claimBribes(claimData); - } + // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + // claimData[0].epoch = 1; + // claimData[0].prevLQTYAllocationEpoch = 1; + // claimData[0].prevTotalLQTYAllocationEpoch = 1; + // bribeInitiative.claimBribes(claimData); + // } - function test_onAfterAllocateLQTY_sameEpoch_NoVetoToVeto() public { - vm.startPrank(lusdHolder); - lqty.approve(address(bribeInitiative), 1000e18); - lusd.approve(address(bribeInitiative), 1000e18); - bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - vm.stopPrank(); + // function test_onAfterAllocateLQTY_sameEpoch_NoVetoToVeto() public { + // vm.startPrank(lusdHolder); + // lqty.approve(address(bribeInitiative), 1000e18); + // lusd.approve(address(bribeInitiative), 1000e18); + // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + // vm.stopPrank(); - governance.setEpoch(1); + // governance.setEpoch(1); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - governance.setEpoch(2); + // governance.setEpoch(2); - vm.startPrank(address(user)); + // vm.startPrank(address(user)); - BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - claimData[0].epoch = 1; - claimData[0].prevLQTYAllocationEpoch = 1; - claimData[0].prevTotalLQTYAllocationEpoch = 1; - vm.expectRevert("BribeInitiative: invalid-prev-lqty-allocation-epoch"); // nothing to claim - bribeInitiative.claimBribes(claimData); - } + // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + // claimData[0].epoch = 1; + // claimData[0].prevLQTYAllocationEpoch = 1; + // claimData[0].prevTotalLQTYAllocationEpoch = 1; + // vm.expectRevert("BribeInitiative: invalid-prev-lqty-allocation-epoch"); // nothing to claim + // bribeInitiative.claimBribes(claimData); + // } - function test_onAfterAllocateLQTY_sameEpoch_VetoToNoVeto() public { - vm.startPrank(lusdHolder); - lqty.approve(address(bribeInitiative), 1000e18); - lusd.approve(address(bribeInitiative), 1000e18); - bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - vm.stopPrank(); + // function test_onAfterAllocateLQTY_sameEpoch_VetoToNoVeto() public { + // vm.startPrank(lusdHolder); + // lqty.approve(address(bribeInitiative), 1000e18); + // lusd.approve(address(bribeInitiative), 1000e18); + // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + // vm.stopPrank(); - governance.setEpoch(1); + // governance.setEpoch(1); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); - governance.setEpoch(2); + // governance.setEpoch(2); - vm.startPrank(address(user)); + // vm.startPrank(address(user)); - BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - claimData[0].epoch = 1; - claimData[0].prevLQTYAllocationEpoch = 1; - claimData[0].prevTotalLQTYAllocationEpoch = 1; - bribeInitiative.claimBribes(claimData); - } + // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + // claimData[0].epoch = 1; + // claimData[0].prevLQTYAllocationEpoch = 1; + // claimData[0].prevTotalLQTYAllocationEpoch = 1; + // bribeInitiative.claimBribes(claimData); + // } - function test_onAfterAllocateLQTY_sameEpoch_VetoToVeto() public { - governance.setEpoch(1); + // function test_onAfterAllocateLQTY_sameEpoch_VetoToVeto() public { + // governance.setEpoch(1); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 1); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - } + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 1); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + // } - function test_onAfterAllocateLQTY() public { - governance.setEpoch(1); + // function test_onAfterAllocateLQTY() public { + // governance.setEpoch(1); - vm.startPrank(address(governance)); + // vm.startPrank(address(governance)); - // first total deposit, first user deposit - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1000e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + // // first total deposit, first user deposit + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1000e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); - // second total deposit, second user deposit - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1000e18); // should stay the same - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); // should stay the same + // // second total deposit, second user deposit + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1000e18); // should stay the same + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); // should stay the same - // third total deposit, first user deposit - bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1000e18, 0); - assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2000e18); - assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1000e18); + // // third total deposit, first user deposit + // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1000e18, 0); + // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2000e18); + // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1000e18); - vm.stopPrank(); - } + // vm.stopPrank(); + // } } diff --git a/test/mocks/MockGovernance.sol b/test/mocks/MockGovernance.sol index 3d34b14..3ed3e75 100644 --- a/test/mocks/MockGovernance.sol +++ b/test/mocks/MockGovernance.sol @@ -15,4 +15,17 @@ contract MockGovernance { function epoch() external view returns (uint16) { return __epoch; } + + function _averageAge(uint32 _currentTimestamp, uint32 _averageTimestamp) internal pure returns (uint32) { + if (_averageTimestamp == 0 || _currentTimestamp < _averageTimestamp) return 0; + return _currentTimestamp - _averageTimestamp; + } + + function lqtyToVotes(uint88 _lqtyAmount, uint256 _currentTimestamp, uint32 _averageTimestamp) + public + pure + returns (uint240) + { + return uint240(_lqtyAmount) * _averageAge(uint32(_currentTimestamp), _averageTimestamp); + } } diff --git a/test/mocks/MockInitiative.sol b/test/mocks/MockInitiative.sol index 8861f42..b5402cc 100644 --- a/test/mocks/MockInitiative.sol +++ b/test/mocks/MockInitiative.sol @@ -22,7 +22,13 @@ contract MockInitiative is IInitiative { } /// @inheritdoc IInitiative - function onAfterAllocateLQTY(uint16, address, uint88, uint88) external virtual { + function onAfterAllocateLQTY( + uint16, + address, + IGovernance.UserState calldata, + IGovernance.Allocation calldata, + IGovernance.InitiativeState calldata + ) external virtual { address[] memory initiatives = new address[](0); int176[] memory deltaLQTYVotes = new int176[](0); int176[] memory deltaLQTYVetos = new int176[](0); From df8cabf02b23bd6f196742d33f8f04e5dc1d07e8 Mon Sep 17 00:00:00 2001 From: jlqty <172397380+jltqy@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:19:01 +0100 Subject: [PATCH 2/7] Simplify bribing accounting --- src/BribeInitiative.sol | 8 +- test/BribeInitiativeAllocate.t.sol | 135 ++++++++++++++++++++++------- 2 files changed, 108 insertions(+), 35 deletions(-) diff --git a/src/BribeInitiative.sol b/src/BribeInitiative.sol index d855a19..1d261a3 100644 --- a/src/BribeInitiative.sol +++ b/src/BribeInitiative.sol @@ -190,7 +190,6 @@ contract BribeInitiative is IInitiative, IBribeInitiative { // if this is the first user allocation in the epoch, then insert a new item into the user allocation DLL if (mostRecentUserEpoch != _currentEpoch) { - uint88 newVoteLQTY = (_allocation.vetoLQTY == 0) ? _allocation.voteLQTY : 0; uint16 mostRecentTotalEpoch = totalLQTYAllocationByEpoch.getHead(); // if this is the first allocation in the epoch, then insert a new item into the total allocation DLL if (mostRecentTotalEpoch != _currentEpoch) { @@ -202,14 +201,15 @@ contract BribeInitiative is IInitiative, IBribeInitiative { _currentEpoch, _initiativeState.voteLQTY, _initiativeState.averageStakingTimestampVoteLQTY, false ); } - _setLQTYAllocationByUserAtEpoch(_user, _currentEpoch, newVoteLQTY, _userState.averageStakingTimestamp, true); + _setLQTYAllocationByUserAtEpoch( + _user, _currentEpoch, _allocation.voteLQTY, _userState.averageStakingTimestamp, true + ); } else { _setTotalLQTYAllocationByEpoch( _currentEpoch, _initiativeState.voteLQTY, _initiativeState.averageStakingTimestampVoteLQTY, false ); - uint88 newVoteLQTY = (_allocation.vetoLQTY == 0) ? _allocation.voteLQTY : 0; _setLQTYAllocationByUserAtEpoch( - _user, _currentEpoch, newVoteLQTY, _userState.averageStakingTimestamp, false + _user, _currentEpoch, _allocation.voteLQTY, _userState.averageStakingTimestamp, false ); } } diff --git a/test/BribeInitiativeAllocate.t.sol b/test/BribeInitiativeAllocate.t.sol index 9a57e5c..165d531 100644 --- a/test/BribeInitiativeAllocate.t.sol +++ b/test/BribeInitiativeAllocate.t.sol @@ -157,48 +157,121 @@ contract BribeInitiativeAllocateTest is Test { assertGt(bribeTokenAmount, 999e18); } - // function test_onAfterAllocateLQTY_newEpoch_NoVetoToVeto() public { - // governance.setEpoch(1); + function test_onAfterAllocateLQTY_newEpoch_NoVetoToVeto() public { + governance.setEpoch(1); - // vm.startPrank(address(governance)); + vm.startPrank(address(governance)); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: 1}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 0 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: 1}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 0 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1001e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // vm.startPrank(lusdHolder); - // lqty.approve(address(bribeInitiative), 1000e18); - // lusd.approve(address(bribeInitiative), 1000e18); - // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - // vm.stopPrank(); + vm.startPrank(lusdHolder); + lqty.approve(address(bribeInitiative), 1000e18); + lusd.approve(address(bribeInitiative), 1000e18); + bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + vm.stopPrank(); - // governance.setEpoch(2); + governance.setEpoch(2); - // vm.startPrank(address(governance)); + vm.startPrank(address(governance)); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1, atEpoch: 1}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 0, + vetoLQTY: 1, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 0 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 0); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 0); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 0); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 0); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1, atEpoch: 1}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 0, + vetoLQTY: 1, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 0 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 0); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 0); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // governance.setEpoch(3); + governance.setEpoch(3); - // vm.startPrank(address(user)); + vm.startPrank(address(user)); - // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - // claimData[0].epoch = 2; - // claimData[0].prevLQTYAllocationEpoch = 2; - // claimData[0].prevTotalLQTYAllocationEpoch = 2; - // vm.expectRevert("BribeInitiative: invalid-prev-lqty-allocation-epoch"); // nothing to claim - // bribeInitiative.claimBribes(claimData); - // } + BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + claimData[0].epoch = 2; + claimData[0].prevLQTYAllocationEpoch = 2; + claimData[0].prevTotalLQTYAllocationEpoch = 2; + (uint256 boldAmount, uint256 bribeTokenAmount) = bribeInitiative.claimBribes(claimData); + assertEq(boldAmount, 0); + assertEq(bribeTokenAmount, 0); + } // function test_onAfterAllocateLQTY_newEpoch_VetoToNoVeto() public { // governance.setEpoch(1); From 91ccc634cfc03250346cd3c85e535c3cdf22c44f Mon Sep 17 00:00:00 2001 From: jlqty <172397380+jltqy@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:02:29 +0100 Subject: [PATCH 3/7] Update tests --- test/BribeInitiativeAllocate.t.sol | 370 +++++++++++++++++++++++------ 1 file changed, 296 insertions(+), 74 deletions(-) diff --git a/test/BribeInitiativeAllocate.t.sol b/test/BribeInitiativeAllocate.t.sol index 165d531..bb62e5d 100644 --- a/test/BribeInitiativeAllocate.t.sol +++ b/test/BribeInitiativeAllocate.t.sol @@ -273,105 +273,327 @@ contract BribeInitiativeAllocateTest is Test { assertEq(bribeTokenAmount, 0); } - // function test_onAfterAllocateLQTY_newEpoch_VetoToNoVeto() public { - // governance.setEpoch(1); + function test_onAfterAllocateLQTY_newEpoch_VetoToNoVeto() public { + governance.setEpoch(1); - // vm.startPrank(address(governance)); + vm.startPrank(address(governance)); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); - // governance.setEpoch(2); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + IGovernance.UserState memory userStateVeto = + IGovernance.UserState({allocatedLQTY: 1000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocationVeto = + IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1000e18, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeStateVeto = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 1000e18, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: uint32(block.timestamp), + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY( + governance.epoch(), user, userStateVeto, allocationVeto, initiativeStateVeto + ); + + (uint88 totalLQTYAllocatedAfterVeto, uint32 totalAverageTimestampAfterVeto) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocatedAfterVeto, 1e18); + assertEq(totalAverageTimestampAfterVeto, uint32(block.timestamp)); + (uint88 userLQTYAllocatedAfterVeto, uint32 userAverageTimestampAfterVeto) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocatedAfterVeto, 0); + assertEq(userAverageTimestampAfterVeto, uint32(block.timestamp)); - // vm.startPrank(lusdHolder); - // lqty.approve(address(bribeInitiative), 1000e18); - // lusd.approve(address(bribeInitiative), 1000e18); - // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - // vm.stopPrank(); + governance.setEpoch(2); - // vm.startPrank(address(governance)); + IGovernance.UserState memory userStateNewEpoch = + IGovernance.UserState({allocatedLQTY: 1, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocationNewEpoch = + IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeStateNewEpoch = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 1, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: uint32(block.timestamp), + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY( + governance.epoch(), user, userStateNewEpoch, allocationNewEpoch, initiativeStateNewEpoch + ); + + (uint88 totalLQTYAllocatedNewEpoch, uint32 totalAverageTimestampNewEpoch) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocatedNewEpoch, 1e18); + assertEq(totalAverageTimestampNewEpoch, uint32(block.timestamp)); + (uint88 userLQTYAllocatedNewEpoch, uint32 userAverageTimestampNewEpoch) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocatedNewEpoch, 0); + assertEq(userAverageTimestampNewEpoch, uint32(block.timestamp)); - // governance.setEpoch(3); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); + vm.startPrank(lusdHolder); + lqty.approve(address(bribeInitiative), 1000e18); + lusd.approve(address(bribeInitiative), 1000e18); + bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + vm.stopPrank(); - // governance.setEpoch(4); + vm.startPrank(address(governance)); - // vm.startPrank(address(user)); + governance.setEpoch(3); - // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - // claimData[0].epoch = 3; - // claimData[0].prevLQTYAllocationEpoch = 3; - // claimData[0].prevTotalLQTYAllocationEpoch = 3; - // bribeInitiative.claimBribes(claimData); - // } + IGovernance.UserState memory userStateNewEpoch3 = + IGovernance.UserState({allocatedLQTY: 2000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocationNewEpoch3 = + IGovernance.Allocation({voteLQTY: 2000e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeStateNewEpoch3 = IGovernance.InitiativeState({ + voteLQTY: 2001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY( + governance.epoch(), user, userStateNewEpoch3, allocationNewEpoch3, initiativeStateNewEpoch3 + ); + + (uint88 totalLQTYAllocatedNewEpoch3, uint32 totalAverageTimestampNewEpoch3) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocatedNewEpoch3, 2001e18); + assertEq(totalAverageTimestampNewEpoch3, uint32(block.timestamp)); + (uint88 userLQTYAllocatedNewEpoch3, uint32 userAverageTimestampNewEpoch3) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocatedNewEpoch3, 2000e18); + assertEq(userAverageTimestampNewEpoch3, uint32(block.timestamp)); - // function test_onAfterAllocateLQTY_newEpoch_VetoToVeto() public { - // governance.setEpoch(1); + governance.setEpoch(4); - // vm.startPrank(address(governance)); + vm.startPrank(address(user)); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + claimData[0].epoch = 3; + claimData[0].prevLQTYAllocationEpoch = 3; + claimData[0].prevTotalLQTYAllocationEpoch = 3; + bribeInitiative.claimBribes(claimData); + } - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + function test_onAfterAllocateLQTY_newEpoch_VetoToVeto() public { + governance.setEpoch(1); - // governance.setEpoch(2); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + vm.startPrank(address(governance)); - // governance.setEpoch(3); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - // } + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); - // function test_onAfterAllocateLQTY_sameEpoch_NoVetoToNoVeto() public { - // vm.startPrank(lusdHolder); - // lqty.approve(address(bribeInitiative), 1000e18); - // lusd.approve(address(bribeInitiative), 1000e18); - // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - // vm.stopPrank(); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // governance.setEpoch(1); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1000e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); - // vm.startPrank(address(governance)); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1001e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 1000e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + governance.setEpoch(2); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 0); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // governance.setEpoch(2); + governance.setEpoch(3); - // vm.startPrank(address(user)); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); - // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - // claimData[0].epoch = 1; - // claimData[0].prevLQTYAllocationEpoch = 1; - // claimData[0].prevTotalLQTYAllocationEpoch = 1; - // bribeInitiative.claimBribes(claimData); - // } + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 0); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + } + + function test_onAfterAllocateLQTY_sameEpoch_NoVetoToNoVeto() public { + vm.startPrank(lusdHolder); + lqty.approve(address(bribeInitiative), 1000e18); + lusd.approve(address(bribeInitiative), 1000e18); + bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + vm.stopPrank(); + + governance.setEpoch(1); + + vm.startPrank(address(governance)); + + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); + + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1000e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); + + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1001e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 1000e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 2000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 2000e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 2001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); + + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 2001e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 2000e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + + governance.setEpoch(2); + + vm.startPrank(address(user)); + + BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + claimData[0].epoch = 1; + claimData[0].prevLQTYAllocationEpoch = 1; + claimData[0].prevTotalLQTYAllocationEpoch = 1; + bribeInitiative.claimBribes(claimData); + } // function test_onAfterAllocateLQTY_sameEpoch_NoVetoToVeto() public { // vm.startPrank(lusdHolder); From 6360513667968500ac7622e18c70bd2c56325afc Mon Sep 17 00:00:00 2001 From: jlqty <172397380+jltqy@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:25:09 +0100 Subject: [PATCH 4/7] Further simplify onAllocateLQTY logic --- src/BribeInitiative.sol | 42 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/src/BribeInitiative.sol b/src/BribeInitiative.sol index 1d261a3..8da4d51 100644 --- a/src/BribeInitiative.sol +++ b/src/BribeInitiative.sol @@ -176,7 +176,6 @@ contract BribeInitiative is IInitiative, IBribeInitiative { return _decodeLQTYAllocation(lqtyAllocationByUserAtEpoch[_user].items[_epoch].value); } - /// @inheritdoc IInitiative function onAfterAllocateLQTY( uint16 _currentEpoch, address _user, @@ -184,34 +183,25 @@ contract BribeInitiative is IInitiative, IBribeInitiative { IGovernance.Allocation calldata _allocation, IGovernance.InitiativeState calldata _initiativeState ) external virtual onlyGovernance { + if (_currentEpoch == 0) return; + uint16 mostRecentUserEpoch = lqtyAllocationByUserAtEpoch[_user].getHead(); + uint16 mostRecentTotalEpoch = totalLQTYAllocationByEpoch.getHead(); - if (_currentEpoch == 0) return; + _setTotalLQTYAllocationByEpoch( + _currentEpoch, + _initiativeState.voteLQTY, + _initiativeState.averageStakingTimestampVoteLQTY, + mostRecentTotalEpoch != _currentEpoch // Insert if current > recent + ); - // if this is the first user allocation in the epoch, then insert a new item into the user allocation DLL - if (mostRecentUserEpoch != _currentEpoch) { - uint16 mostRecentTotalEpoch = totalLQTYAllocationByEpoch.getHead(); - // if this is the first allocation in the epoch, then insert a new item into the total allocation DLL - if (mostRecentTotalEpoch != _currentEpoch) { - _setTotalLQTYAllocationByEpoch( - _currentEpoch, _initiativeState.voteLQTY, _initiativeState.averageStakingTimestampVoteLQTY, true - ); - } else { - _setTotalLQTYAllocationByEpoch( - _currentEpoch, _initiativeState.voteLQTY, _initiativeState.averageStakingTimestampVoteLQTY, false - ); - } - _setLQTYAllocationByUserAtEpoch( - _user, _currentEpoch, _allocation.voteLQTY, _userState.averageStakingTimestamp, true - ); - } else { - _setTotalLQTYAllocationByEpoch( - _currentEpoch, _initiativeState.voteLQTY, _initiativeState.averageStakingTimestampVoteLQTY, false - ); - _setLQTYAllocationByUserAtEpoch( - _user, _currentEpoch, _allocation.voteLQTY, _userState.averageStakingTimestamp, false - ); - } + _setLQTYAllocationByUserAtEpoch( + _user, + _currentEpoch, + _allocation.voteLQTY, + _userState.averageStakingTimestamp, + mostRecentUserEpoch != _currentEpoch // Insert if user current > recent + ); } /// @inheritdoc IInitiative From 3c1dd7e141c133f6ae3b9549820dfa0cfbb82376 Mon Sep 17 00:00:00 2001 From: jlqty <172397380+jltqy@users.noreply.github.com> Date: Wed, 9 Oct 2024 17:02:24 +0100 Subject: [PATCH 5/7] Update tests --- test/BribeInitiativeAllocate.t.sol | 361 +++++++++++++++++++++++------ 1 file changed, 291 insertions(+), 70 deletions(-) diff --git a/test/BribeInitiativeAllocate.t.sol b/test/BribeInitiativeAllocate.t.sol index bb62e5d..3bfa44f 100644 --- a/test/BribeInitiativeAllocate.t.sol +++ b/test/BribeInitiativeAllocate.t.sol @@ -595,100 +595,321 @@ contract BribeInitiativeAllocateTest is Test { bribeInitiative.claimBribes(claimData); } - // function test_onAfterAllocateLQTY_sameEpoch_NoVetoToVeto() public { - // vm.startPrank(lusdHolder); - // lqty.approve(address(bribeInitiative), 1000e18); - // lusd.approve(address(bribeInitiative), 1000e18); - // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - // vm.stopPrank(); + function test_onAfterAllocateLQTY_sameEpoch_NoVetoToVeto() public { + vm.startPrank(lusdHolder); + lqty.approve(address(bribeInitiative), 1000e18); + lusd.approve(address(bribeInitiative), 1000e18); + bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + vm.stopPrank(); - // governance.setEpoch(1); + governance.setEpoch(1); - // vm.startPrank(address(governance)); + vm.startPrank(address(governance)); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1000e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); - // governance.setEpoch(2); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1001e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 1000e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // vm.startPrank(address(user)); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); - // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - // claimData[0].epoch = 1; - // claimData[0].prevLQTYAllocationEpoch = 1; - // claimData[0].prevTotalLQTYAllocationEpoch = 1; - // vm.expectRevert("BribeInitiative: invalid-prev-lqty-allocation-epoch"); // nothing to claim - // bribeInitiative.claimBribes(claimData); - // } + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 0); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // function test_onAfterAllocateLQTY_sameEpoch_VetoToNoVeto() public { - // vm.startPrank(lusdHolder); - // lqty.approve(address(bribeInitiative), 1000e18); - // lusd.approve(address(bribeInitiative), 1000e18); - // bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); - // vm.stopPrank(); + governance.setEpoch(2); - // governance.setEpoch(1); + vm.startPrank(address(user)); - // vm.startPrank(address(governance)); + BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + claimData[0].epoch = 1; + claimData[0].prevLQTYAllocationEpoch = 1; + claimData[0].prevTotalLQTYAllocationEpoch = 1; + (uint256 boldAmount, uint256 bribeTokenAmount) = bribeInitiative.claimBribes(claimData); + assertEq(boldAmount, 0); + assertEq(bribeTokenAmount, 0); + } - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + function test_onAfterAllocateLQTY_sameEpoch_VetoToNoVeto() public { + vm.startPrank(lusdHolder); + lqty.approve(address(bribeInitiative), 1000e18); + lusd.approve(address(bribeInitiative), 1000e18); + bribeInitiative.depositBribe(1000e18, 1000e18, governance.epoch() + 1); + vm.stopPrank(); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + governance.setEpoch(1); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + vm.startPrank(address(governance)); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 2001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 2000e18); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); - // governance.setEpoch(2); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // vm.startPrank(address(user)); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1000e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); - // BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); - // claimData[0].epoch = 1; - // claimData[0].prevLQTYAllocationEpoch = 1; - // claimData[0].prevTotalLQTYAllocationEpoch = 1; - // bribeInitiative.claimBribes(claimData); - // } + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1001e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 1000e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // function test_onAfterAllocateLQTY_sameEpoch_VetoToVeto() public { - // governance.setEpoch(1); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); - // vm.startPrank(address(governance)); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 0); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, 1e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()), 1e18); + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 2000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 2000e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 2001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 0); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1001e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 1000e18); + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 2001e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 2000e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + + governance.setEpoch(2); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 2000e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); + vm.startPrank(address(user)); - // bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, 1000e18, 1); - // assertEq(bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()), 1e18); - // assertEq(bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()), 0); - // } + BribeInitiative.ClaimData[] memory claimData = new BribeInitiative.ClaimData[](1); + claimData[0].epoch = 1; + claimData[0].prevLQTYAllocationEpoch = 1; + claimData[0].prevTotalLQTYAllocationEpoch = 1; + bribeInitiative.claimBribes(claimData); + } + + function test_onAfterAllocateLQTY_sameEpoch_VetoToVeto() public { + governance.setEpoch(1); + + vm.startPrank(address(governance)); + + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user2, userState, allocation, initiativeState); + + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user2, governance.epoch()); + assertEq(userLQTYAllocated, 1e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1000e18, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 1000e18, vetoLQTY: 0, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1001e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); + + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1001e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 1000e18); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 1, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 1, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); + + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 0); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + + { + IGovernance.UserState memory userState = + IGovernance.UserState({allocatedLQTY: 2, averageStakingTimestamp: uint32(block.timestamp)}); + IGovernance.Allocation memory allocation = + IGovernance.Allocation({voteLQTY: 0, vetoLQTY: 2, atEpoch: uint16(governance.epoch())}); + IGovernance.InitiativeState memory initiativeState = IGovernance.InitiativeState({ + voteLQTY: 1e18, + vetoLQTY: 0, + averageStakingTimestampVoteLQTY: uint32(block.timestamp), + averageStakingTimestampVetoLQTY: 0, + counted: 1 + }); + bribeInitiative.onAfterAllocateLQTY(governance.epoch(), user, userState, allocation, initiativeState); + + (uint88 totalLQTYAllocated, uint32 totalAverageTimestamp) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 1e18); + assertEq(totalAverageTimestamp, uint32(block.timestamp)); + (uint88 userLQTYAllocated, uint32 userAverageTimestamp) = + bribeInitiative.lqtyAllocatedByUserAtEpoch(user, governance.epoch()); + assertEq(userLQTYAllocated, 0); + assertEq(userAverageTimestamp, uint32(block.timestamp)); + } + } // function test_onAfterAllocateLQTY() public { // governance.setEpoch(1); From faed8534a6b41ea95240a21b33e1ed37663a8168 Mon Sep 17 00:00:00 2001 From: nelson-pereira8 <94120714+nican0r@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:05:31 -0300 Subject: [PATCH 6/7] chore: tests for BribeInitiative --- test/BribeInitiative.t.sol | 87 +++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/test/BribeInitiative.t.sol b/test/BribeInitiative.t.sol index 35ad992..7ca6ee6 100644 --- a/test/BribeInitiative.t.sol +++ b/test/BribeInitiative.t.sol @@ -29,7 +29,7 @@ contract BribeInitiativeTest is Test { uint128 private constant VOTING_THRESHOLD_FACTOR = 0.04e18; uint88 private constant MIN_CLAIM = 500e18; uint88 private constant MIN_ACCRUAL = 1000e18; - uint32 private constant EPOCH_DURATION = 604800; + uint32 private constant EPOCH_DURATION = 7 days; // 7 days uint32 private constant EPOCH_VOTING_CUTOFF = 518400; Governance private governance; @@ -41,8 +41,8 @@ contract BribeInitiativeTest is Test { lqty = deployMockERC20("Liquity", "LQTY", 18); lusd = deployMockERC20("Liquity USD", "LUSD", 18); - vm.store(address(lqty), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10000e18))); - vm.store(address(lusd), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10000e18))); + vm.store(address(lqty), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10_000_000e18))); + vm.store(address(lusd), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10_000_000e18))); stakingV1 = address(new MockStakingV1(address(lqty))); @@ -76,11 +76,64 @@ contract BribeInitiativeTest is Test { ); vm.startPrank(lusdHolder); - lqty.transfer(user, 1e18); - lusd.transfer(user, 1e18); + lqty.transfer(user, 1_000_000e18); + lusd.transfer(user, 1_000_000e18); vm.stopPrank(); } + // test total allocation vote case + function test_totalLQTYAllocatedByEpoch_vote() public { + // staking LQTY into governance for user in first epoch + _stakeLQTY(user, 10e18); + + // fast forward to second epoch + vm.warp(block.timestamp + EPOCH_DURATION); + + // allocate LQTY to the bribeInitiative + _allocateLQTY(user, 10e18, 0); + // total LQTY allocated for this epoch should increase + (uint88 totalLQTYAllocated, ) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 10e18); + } + + // test total allocation veto case + function test_totalLQTYAllocatedByEpoch_veto() public { + _stakeLQTY(user, 10e18); + + // fast forward to second epoch + vm.warp(block.timestamp + EPOCH_DURATION); + + // allocate LQTY to the bribeInitiative + _allocateLQTY(user, 0, 10e18); + // total LQTY allocated for this epoch should not increase + (uint88 totalLQTYAllocated, ) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + assertEq(totalLQTYAllocated, 0); + } + + // TODO: test total allocations at start/end of epoch + + // user tries to allocate multiple times in different epochs + function test_allocating_same_initiative_multiple_epochs_reverts() public { + _stakeLQTY(user, 10e18); + + // fast forward to second epoch + vm.warp(block.timestamp + EPOCH_DURATION); + + // allocate LQTY to the bribeInitiative + _allocateLQTY(user, 10e18, 0); + // total LQTY allocated for this epoch should increase + (uint88 totalLQTYAllocated1, ) = + bribeInitiative.totalLQTYAllocatedByEpoch(governance.epoch()); + + // fast forward to third epoch + vm.warp(block.timestamp + EPOCH_DURATION); + + vm.expectRevert(); + _allocateLQTY(user, 10e18, 0); + } + function test_claimBribes() public { vm.startPrank(user); address userProxy = governance.deployUserProxy(); @@ -156,4 +209,28 @@ contract BribeInitiativeTest is Test { assertEq(totalLQTYAllocated, 0); vm.stopPrank(); } + + function _stakeLQTY(address staker, uint88 amount) public { + vm.startPrank(staker); + address userProxy = governance.deployUserProxy(); + lqty.approve(address(userProxy), amount); + governance.depositLQTY(amount); + vm.stopPrank(); + } + + function _allocateLQTY(address staker, int176 deltaVoteLQTYAmt, int176 deltaVetoLQTYAmt) public { + vm.startPrank(staker); + address[] memory initiatives = new address[](1); + initiatives[0] = address(bribeInitiative); + + // voting in favor of the initiative with half of user's stake + int176[] memory deltaVoteLQTY = new int176[](1); + deltaVoteLQTY[0] = deltaVoteLQTYAmt; + + int176[] memory deltaVetoLQTY = new int176[](1); + deltaVetoLQTY[0] = deltaVetoLQTYAmt; + + governance.allocateLQTY(initiatives, deltaVoteLQTY, deltaVetoLQTY); + vm.stopPrank(); + } } From 8eb5bb28549f46ef173b312905bbfafbc7ad299b Mon Sep 17 00:00:00 2001 From: nelson-pereira8 <94120714+nican0r@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:06:09 -0300 Subject: [PATCH 7/7] chore: fix revert statement in allocateLQTY --- src/Governance.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Governance.sol b/src/Governance.sol index a51b443..7e2f860 100644 --- a/src/Governance.sol +++ b/src/Governance.sol @@ -485,7 +485,7 @@ contract Governance is Multicall, UserProxyFactory, ReentrancyGuard, IGovernance require( userState.allocatedLQTY == 0 || userState.allocatedLQTY <= uint88(stakingV1.stakes(deriveUserProxyAddress(msg.sender))), - "Governance: insufficient-or-unallocated-lqty" + "Governance: insufficient-or-allocated-lqty" ); globalState = state;