Any user with non-zero balance have an ability to withdraw unlitimed amount of tokens.
As can be seen in TokenManager
, L113-129, once a related contract calls addTokenBalance
, the corresponding balance will be credited to the user via internal balance tracking.
More precisely, it adds the balance to userTokenBalanceMap
, which represents the amount of tokens a user has, determined by the user’s address, the specific token’s address, and the type of token balance (used in the system to differentiate between the multiple ways the user could have obtained the tokens).
Once a user obtains some tokens, they instantly become able to withdraw them by calling withdraw on TokenManager
, specifying the token’s address and the type of token balance.
As can be seen in the withdraw function, the contract assumes that the claimable amount of a token is equal to userTokenBalanceMap[_msgSender()][_tokenAddress][_tokenBalanceType]
.
While this is correct, the contract doesn’t update this value anywhere in the code, making it possible for the user to withdraw the token associated with _tokenAddress
indefinitely, until the contract is fully drained of _tokenAddress
token.
One more way to drain the CapitalPool
currently is to do so via reentrancy, since there is no reentrancy guard, and the balance doesn't get updated at all.
But reentrancy is not needed. Since the balance doesn't get updated, it's possible to drain CapitalPool
as was described above.
Any user is able to steal all tokens where they have a non-zero balance from CapitalPool
, making the system completely unsafe.
Also, when fixing this issue it's crucial to follow CEI pattern, since otherwise it will be possible to drain the CapitalPool
via reentrancy since there is no reentrancy guard.
Manual Review
Set userTokenBalanceMap[_msgSender()][_tokenAddress][_tokenBalanceType]
to 0, right after calculating claimAbleAmount
.
This way we ensure the user can't withdraw balance given to him multiple times, also following CEI pattern.
Valid critical severity finding, the lack of clearance of the `userTokenBalanceMap` mapping allows complete draining of the CapitalPool contract. Note: This would require the approval issues highlighted in other issues to be fixed first (i.e. wrong approval address within `_transfer` and lack of approvals within `_safe_transfer_from` during ERC20 withdrawals)
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.