diff --git a/src/BribeInitiative.sol b/src/BribeInitiative.sol index 15b18451..eab3322b 100644 --- a/src/BribeInitiative.sol +++ b/src/BribeInitiative.sol @@ -12,6 +12,7 @@ import {DoubleLinkedList} from "./utils/DoubleLinkedList.sol"; import {EncodingDecodingLib} from "src/utils/EncodingDecodingLib.sol"; +import {console} from "forge-std/console.sol"; contract BribeInitiative is IInitiative, IBribeInitiative { @@ -182,6 +183,20 @@ contract BribeInitiative is IInitiative, IBribeInitiative { return _decodeLQTYAllocation(lqtyAllocationByUserAtEpoch[_user].items[_epoch].value); } + /// @inheritdoc IBribeInitiative + function getMostRecentUserEpoch(address _user) external view returns (uint16) { + uint16 mostRecentUserEpoch = lqtyAllocationByUserAtEpoch[_user].getHead(); + + return mostRecentUserEpoch; + } + + /// @inheritdoc IBribeInitiative + function getMostRecentTotalEpoch() external view returns (uint16) { + uint16 mostRecentTotalEpoch = totalLQTYAllocationByEpoch.getHead(); + + return mostRecentTotalEpoch; + } + function onAfterAllocateLQTY( uint16 _currentEpoch, address _user, diff --git a/src/interfaces/IBribeInitiative.sol b/src/interfaces/IBribeInitiative.sol index 9d28d821..2748b48a 100644 --- a/src/interfaces/IBribeInitiative.sol +++ b/src/interfaces/IBribeInitiative.sol @@ -78,4 +78,10 @@ interface IBribeInitiative { function claimBribes(ClaimData[] calldata _claimData) external returns (uint256 boldAmount, uint256 bribeTokenAmount); + + /// @notice Given a user address return the last recorded epoch for their allocation + function getMostRecentUserEpoch(address _user) external view returns (uint16); + + /// @notice Return the last recorded epoch for the system + function getMostRecentTotalEpoch() external view returns (uint16); } diff --git a/test/recon/CryticToFoundry.sol b/test/recon/CryticToFoundry.sol index 4f334913..1b61290b 100644 --- a/test/recon/CryticToFoundry.sol +++ b/test/recon/CryticToFoundry.sol @@ -103,4 +103,24 @@ contract CryticToFoundry is Test, TargetFunctions, FoundryAsserts { initiative_claimBribes(0,3,0,0); property_BI11(); } + + + // forge test --match-test test_property_BI04_1 -vv + function test_property_BI04_1() public { + + + governance_depositLQTY(2); + + vm.roll(block.number + 1); + vm.warp(block.timestamp + 654326); + governance_allocateLQTY_clamped_single_initiative(0,1,0); + + + vm.roll(block.number + 1); + vm.warp(block.timestamp + 559510); + property_resetting_never_reverts(); + + property_BI04(); + + } } \ No newline at end of file diff --git a/test/recon/properties/BribeInitiativeProperties.sol b/test/recon/properties/BribeInitiativeProperties.sol index 8ce0fd90..c8fffe0d 100644 --- a/test/recon/properties/BribeInitiativeProperties.sol +++ b/test/recon/properties/BribeInitiativeProperties.sol @@ -89,14 +89,16 @@ function property_BI04() public { function _getLastLQTYAllocationKnown(IBribeInitiative initiative, uint16 targetEpoch) internal returns (uint88) { uint16 currenEpoch; uint88 found; - while(currenEpoch <= targetEpoch) { - (uint88 totalLQTYAllocatedAtEpoch, uint32 ts) = initiative.totalLQTYAllocatedByEpoch(currenEpoch++); - if(ts != 0) { - found = totalLQTYAllocatedAtEpoch; - } + + uint16 mostRecentTotalEpoch = initiative.getMostRecentTotalEpoch(); + + if(targetEpoch < mostRecentTotalEpoch) { + (uint88 totalLQTYAllocatedAtEpoch, uint32 ts) = initiative.totalLQTYAllocatedByEpoch(targetEpoch); + return totalLQTYAllocatedAtEpoch; } - return found; + (uint88 totalLQTYAllocatedAtEpoch, uint32 ts) = initiative.totalLQTYAllocatedByEpoch(mostRecentTotalEpoch); + return totalLQTYAllocatedAtEpoch; } function property_BI05() public {