Open sherlock-admin4 opened 3 months ago
The protocol team fixed this issue in the following PRs/commits: https://github.com/unioncredit/union-v2-contracts/pull/179
The protocol team fixed this issue in the following PRs/commits: unioncredit/union-v2-contracts#179
Fix looks ok
KungFuPanda
High
The _totalStaked tracker calculation is incorrect and will be inflated due to the improper logic in the writeOffDebt function of the UserManager contract, leading to wrong Comptroller gInflationIndex being calculated and wrong user rewards being issued
Summary
During
debtWriteOff
call in theUserManager
, subtracting theamount
instead ofrealAmount
will lead to the wholegInflationIndex
being inflated in theComptroller
contract, as well as general accounting inflation.Due to the
UserManager
's_totalStaked
being coupled with theComptroller
'sgInflationIndex
, theuserInfo
stake'sinflationIndex
will be calculated absolutely incorrectly:And due to that, the whole user rewards calculation will be incorrect:
(https://github.com/sherlock-audit/2024-06-union-finance-update-2/blob/7ffe43f68a1b8e8de1dfd9de5a4d89c90fd6f710/union-v2-contracts/contracts/token/Comptroller.sol#L293)
Furthermore, during the reward accrual, there's another outcome of the miscalculated
_totalStaked
andgInflationIndex
values:Above is a reference from the
Comptroller
contract: https://github.com/sherlock-audit/2024-06-union-finance-update-2/blob/7ffe43f68a1b8e8de1dfd9de5a4d89c90fd6f710/union-v2-contracts/contracts/token/Comptroller.sol#L220C1-L238C6.References for the main problem:
The culprit's details are further explained below.
This is due to using a non-scaled
amount
instead of the scaledrealAmount
in thedebtWriteOff
function here, in this line: https://github.com/sherlock-audit/2024-06-union-finance-update-2/blob/7ffe43f68a1b8e8de1dfd9de5a4d89c90fd6f710/union-v2-contracts/contracts/user/UserManager.sol#L834Root Cause
In this update Union Finance adds distinct definitions for the
actualAmount
being the real scaled token amount, and theamount
being an unscaled nominal amount that is to be scaled bystakingTokenDecimal
, and is usually accepted as an argument for functions within theUserManager
contract.Both
stake
andunstake
functions track thetotalStaked
balance as a scaled AND real token amount, as can be seen here: https://github.com/sherlock-audit/2024-06-union-finance-update-2/blob/7ffe43f68a1b8e8de1dfd9de5a4d89c90fd6f710/union-v2-contracts/contracts/user/UserManager.sol#L784. The snippet:And for
stake
it'sactualAmount
too (https://github.com/sherlock-audit/2024-06-union-finance-update-2/blob/7ffe43f68a1b8e8de1dfd9de5a4d89c90fd6f710/union-v2-contracts/contracts/user/UserManager.sol#L748), correspondingly:However, the
debtWriteOff
function doesn't subtract theactualAmount
, but decreases the_totalStaked
counter by a non-scaledamount
value:Then here later in the
batchUpdateFrozenInfo
function (that can be called by anyone and is unrestricted!), theComptroller
contract is notified of the new_totalStaked
amount (https://github.com/sherlock-audit/2024-06-union-finance-update-2/blob/7ffe43f68a1b8e8de1dfd9de5a4d89c90fd6f710/union-v2-contracts/contracts/user/UserManager.sol#L1121):The problem lies in this change here: https://github.com/unioncredit/union-v2-contracts/pull/172/files#diff-e274f419b6384471f87c2b7d6a2c75150b95d37f3174a21d7d675ad20e3e4464R834
The
Comptroller
'supdateTotalStaked
function gets called:And finally, the
gInflationIndex
value will be inflated.Internal pre-conditions
debtWriteOff
call, because the culprit is an improper calculation.batchUpdateFrozenInfo
to inflate thegInflationIndex
value intentionally and cause theComptroller
's_getInflationIndexNew
to return incorrect results:External pre-conditions
None. The bug is just implicitly there.
Attack Path
As it's a mistake in the
_totalStaked
calculation logic, there's no particular trigger for this attack, as it will happen if any userwrite
'sOffDebt
.Impact
The whole
gInflationIndex
will be inflated, and will be calculated incorrectly.Besides that, tracking the wrong amount of the currently active staked tokens will be misleading for the external users that refer to that value.
PoC
None. Please leave me a comment if you request one from me.
Mitigation
Instead of subtracting
amount
, you should subtract theactualAmount
from the_totalStaked
variable here inwriteOffDebt
: