A malicious user can create an offer in the PreMarktes (hereon PreMarkets) contract which is immediately closed, so the user is eligible for a refund.
The CapitalPool can be made to give infinite approval to the TokenManager contract for any user supplied ERC-20 token address.
Claimable amounts (i.e. the refund) for user/token address/balance types are not cleared after withdrawal.
Given the above, the malicious user can repeatedly call withdraw and drain the capital pool of any token in the CapitalPool contract.
An attacker can exploit the protocol in a transaction/s that performs the following calls to the protocol:
CapitalPool.approve: this can be done before or after the createOffer/closeOffer calls.
PreMarkets.createOffer
PreMarkets.closeOffer
A sequence of TokenManager.withdraw calls until the CapitalPool contract is drained of the collateral token
The attacker is made possible because of:
Anyone can call CapitalPool.approve. Developers intended only for the token manager to call this function.
Offers can be immediately closed (they are still Virgin).
The userTokenBalanceMap
in the TokenManager contract is incremented since: stockInfo.preOffer == address(0x0)
is satisfied in closeOffer
. And, the user can withdraw tokens directly from the token manager and the userTokenBalanceMap
is not updated after the withdrawal. This allows for the user to repeatedly withdraw their userTokenBalanceMap
amount.
Attacker: Interacts directly with the protocol's contracts (as written) & must hold ERC-20 tokens they wish to drain from the capital pool.
Victim: User's of the protocol that have transferred ERC-20 tokens to the CapitalPool contract through regular protocol use -- for example, via createOffer
in PreMarkets contract.
Protocol: Contracts under question: CapitalPool, PreMarkets, TokenManager
High. Protocol user funds are at risk.
Foundry.
In the withdraw
function from TokenManager, zero the userTokenBalanceMap for the user/token/balance type after a successful transfer of the claimableAmount to the caller.
Amend the approve
function in the CapitalPool contract so that only the TokenManager can call this function, as intended.
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.