diff --git a/src/interfaces/staking/ISnapshotStakingPool.sol b/src/interfaces/staking/ISnapshotStakingPool.sol index 6c8adf3..d9c602f 100644 --- a/src/interfaces/staking/ISnapshotStakingPool.sol +++ b/src/interfaces/staking/ISnapshotStakingPool.sol @@ -88,6 +88,11 @@ interface ISnapshotStakingPool is IERC20 { /// @return The total pool reward at the time `snapshotId` function rewardAt(uint256 snapshotId) external view returns (uint256); + /// @notice Retrieves the rewards across all snapshots for `account`. + /// @param account The account to retrieve rewards for + /// @return The rewards across all snapshots for `account` + function getLifetimeRewards(address account) external view returns (uint256); + /// @notice Check if rewards can be accrued. /// @return Boolean indicating if rewards can be accrued function canAccrue() external view returns (bool); diff --git a/src/staking/SnapshotStakingPool.sol b/src/staking/SnapshotStakingPool.sol index 7831055..6a81974 100644 --- a/src/staking/SnapshotStakingPool.sol +++ b/src/staking/SnapshotStakingPool.sol @@ -201,6 +201,11 @@ contract SnapshotStakingPool is ISnapshotStakingPool, Ownable, ERC20Snapshot, Re return rewardSnapshots; } + /// @inheritdoc ISnapshotStakingPool + function getLifetimeRewards(address account) public view returns (uint256) { + return rewardOfInRange(account, 1, _getCurrentSnapshotId()); + } + /// @inheritdoc ISnapshotStakingPool function canAccrue() public view returns (bool) { return block.timestamp >= lastSnapshotTime + snapshotDelay; diff --git a/test/staking/SnapshotStakingPool.t.sol b/test/staking/SnapshotStakingPool.t.sol index 1ad4cd9..bb4f664 100644 --- a/test/staking/SnapshotStakingPool.t.sol +++ b/test/staking/SnapshotStakingPool.t.sol @@ -293,6 +293,29 @@ contract SnapshotStakingPoolTest is Test { assertEq(snapshotStakingPool.getRewardSnapshots()[1], 2 ether); } + function testGetLifetimeRewards() public { + vm.expectRevert(SnapshotStakingPool.NonExistentSnapshotId.selector); + snapshotStakingPool.getLifetimeRewards(bob.addr); + + _stake(bob.addr, 1 ether); + _stake(alice.addr, 1 ether); + _snapshot(2 ether); + + assertEq(snapshotStakingPool.getLifetimeRewards(bob.addr), 1 ether); + assertEq(snapshotStakingPool.getLifetimeRewards(alice.addr), 1 ether); + + _snapshot(2 ether); + + assertEq(snapshotStakingPool.getLifetimeRewards(bob.addr), 2 ether); + assertEq(snapshotStakingPool.getLifetimeRewards(alice.addr), 2 ether); + + _unstake(alice.addr, 1 ether); + _snapshot(1 ether); + + assertEq(snapshotStakingPool.getLifetimeRewards(bob.addr), 3 ether); + assertEq(snapshotStakingPool.getLifetimeRewards(alice.addr), 2 ether); + } + function testCanAccrue() public { assertEq(snapshotStakingPool.canAccrue(), false);