Closed code423n4 closed 1 year ago
MikeHathaway marked the issue as sponsor disputed
Staked positions can't be redeemed. The POC is invalid due to its use of changePrank(address(_rewardsManager));
I thought _rewardsManager
has the right to redeem the staked positions, if that's not true, please forgive my mistake:)
Picodes marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/RewardsManager.sol#L289-L294
Vulnerability details
Impact
RewardsManager's
unstake()
usedelete stakeInfo.snapshot[positionIndexes[i]]
to clear old stake snapshot info. But thepositionIndexes
can be changed betweenstake
andunstake
, the oldstakeInfo.snapshot[positionIndexes[i]]
may not be reset.Attackers could leverage this to obtain extra rewards (interest earned will be counted from the first stake time for old positions) at the expense of other stakers.
Proof of Concept
According to the old audit results at sherlock H-1, if the old snapshot info is not reset completely, attackers could reuse the old snapshot to obtain extra rewards.
The patch iterates the
stakeInfo.snapshot
to reset the nested mappings.This is problematic because it calls
positionManager.getPositionIndexes
to get the keys of nested mappings. The results ofpositionManager.getPositionIndexes
will change betweenstake
andunstake
. Therefore, ifpositionIndexes
remove some old indexes, its correspondingstakeInfo.snapshot
will not be reset and can be reused.If
rewardsManager
callreedemPositions
betweenstake
andunstake
, thepositionIndexes
will be cleared, andunstake
cannot reset the old snapshot. Please see the POC for more info.POC: Add
import "@std/console.sol";
to RewardsManager.t.sol and add this test.Run test with
forge test -m testStakeAndUnstakeBetweenReedem -vvv
The result shows that after unstake, snapshot is not reset.
Tools Used
Manual Review
Recommended Mitigation Steps
Store the keys of the snapshot in a separate vector and delete the snapshot according to the stored keys rather than the positionIndexes.
Assessed type
Other