Due to the fact that the withdraw
function from the TokenManager
contract does not reset users' balances after withdrawals, users can repeat withdrawals from the contract an unlimited number of times, thus stealing funds from other users.
In the withdraw
function of the TokenManager
contract, it is possible to unlimitedly withdraw tokens from the CapitalPool
contract.
The withdraw
function allows any user to withdraw tokens they have earned on their balance, but the user's balance is not updated anywhere after the withdrawal.
The code for getting the user's balance:
As an example, let's consider the simplest scenario of an attack on a system that will exploit the found vulnerability:
First, the user needs to make it so that they have some sort of balance within the TokenManager
contract.
To do this, it is enough to create an offer using the createOffer
function of the PreMarkets
contract. During creation, the user will send some tokens as a collateral.
Then it is necessary to abort the offer immediately using the abortAskOffer
function of the PreMarkets
contract. This abort will add a refund amount to the user's balance in the TokenManager
contract.
Send a huge number of transactions, within which there will be a call to the TokenManager
contract withdraw
function. The number of transactions will depend on how many tokens are inside the CapitalPool
contract.
This is the simplest attack option, but it is possible to create a special contract on whose behalf to interact with the protocol. Then the attack can be accomplished in a single transaction, which will be much more efficient.
To run the test, its code without changes should be placed in the PreMarkets.t.sol file.
It is possible to withdraw absolutely all funds from CapitalPool contract, so this bug is critical.
The bug was found by manually auditing the contract code. To validate the vulnerability and demonstrate it, a unit test was written.
Update value in userTokenBalanceMap
inside withdraw
function.
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.