Note
There is a bug in TokenManager::_transfer()
which makes ETH withdrawls fail. For this test to work, the withdraw function has to be fixed first.
I have reported this bug in another finding.
Description: TokenManager.sol::withdraw()
checks how much funds the caller is able to withdraw the following way:
Then transfer the claimAbleAmount
to the caller.
However it does not deduct the balance of the user stored in the mapping. And the deduction is not made anywhere else in the codebase.
Impact:
This attack works as long as a user has some kind of balance in the protocol accounting, whether it maybe from SalesRevenue or RefundAmout. So a user can just create an offer, close the offer and start the attack.
This lets any user withdraw again and again as long as they have a balance in the userTokenBalanceMap
mapping, eventually draining the entire contract.
Proof of Concept:
User creates an Offer.
The offer is filled and the user gets his Sales Revenue balance updated.
This allows the user to withdraw his Sales revenue til the pool runs out of funds.
Proof of Code:
Paste the following function into PreMarkets.t.sol
:
Recommended Mitigation:
Add a function to deduct balance of users after they make withdrawls
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.