Closed sherlock-admin4 closed 5 months ago
Invalid issue.
Inflation is realized when calling delegate()
since the sync()
function is being called. Which means we only need to check if the latest delegatee
has participated.
I've added a unit test to test the scenario outlined by the watson: https://github.com/MZero-Labs/ttg/pull/262
xiaoming90
high
Users do not receive inflation if the delegatee is updated
Summary
Users do not receive inflation if the delegatee is updated, leading to a loss of assets for the affected users.
Vulnerability Detail
Assume that:
Alice performs a sync on Epoch 104 via the
_sync
function. Note that thelastEpoch_
parameter of the_getUnrealizedInflation
function at Line 137 is set to the current epoch (Epoch 104)https://github.com/sherlock-audit/2023-10-mzero/blob/main/ttg/src/abstract/EpochBasedInflationaryVoteToken.sol#L135
The
_getUnrealizedInflation
function to compute her unrealized inflation. Alice's_getLastSync
is 99. Thus, the function will start looking for inflation from Epoch 99 to Epoch 103 per the for-loop's condition at Line 289.Note that in Line 282 below, the
delegatee_
is set to_getDelegatee(Alice, 104)
, which will be set to Charles. As a result, the delegatee will be "locked" to Charles for the entire for-loop.Let's run through the for-loop to determine the number of inflation that Alice will obtain:
continue
is executed. No inflation.continue
is executed. No inflation._hasParticipatedAt(delegatee_, epoch_)
will be executed, which will be evaluated to_hasParticipatedAt(Charles, 101)
. Since Bob participated instead of Charles in Epoch 101, the function will return false. No inflation.continue
is executed. No inflation._hasParticipatedAt(delegatee_, epoch_)
will be executed, which will be evaluated to_hasParticipatedAt(Charles, 103)
. Charles participated in Epoch 101, so Alice's balance will be inflated.In summary, the above shows that only one inflation occurred instead of the two (2) that Alice is entitled to. In fact, a user will lose all their inflation gained during voting epochs where their previous delegatee took part.
https://github.com/sherlock-audit/2023-10-mzero/blob/main/ttg/src/abstract/EpochBasedInflationaryVoteToken.sol#L275
Impact
Loss of power tokens for the affected users.
Code Snippet
https://github.com/sherlock-audit/2023-10-mzero/blob/main/ttg/src/abstract/EpochBasedInflationaryVoteToken.sol#L135
https://github.com/sherlock-audit/2023-10-mzero/blob/main/ttg/src/abstract/EpochBasedInflationaryVoteToken.sol#L275
Tool used
Manual Review
Recommendation
The delegatee of a user is not constant and can change between the last sync epoch and the current epoch. Thus, consider the following change to ensure that the correct delegatee is fetched for an epoch within the for-loop.