Crypto Pre-Markets 'Tadle' is a new marketplace where traders and investors can trade tokens and points before their official launch. The vulnerability in question is critical, allowing an attacker to drain the entire capital pool once it accumulates funds from various actions by market participants, such as creating offers or takers.
This vulnerability occurs within the withdraw function described below.
https://gist.github.com/parkttule/3e51d5ce700f4f61694341f1f8175da6
This function can be called by anyone externally, and if a value is assigned to the claimAbleAmount variable, it allows the withdrawal of that amount from the capital pool.
However, within the function, there is no logic either before or after the withdrawal that resets the balance in the userTokenBalanceMap[_msgSender()][_tokenAddress][_tokenBalanceType] mapping by the amount withdrawn.
By exploiting this, an attacker can manipulate the mapping value as desired during the process of creating an offer and subsequently creating a taker themselves. This allows them to repeatedly call the withdraw function, draining all the funds in the capital pool.
Below is the Proof of Concept (PoC) code that reflects the attack scenario.
https://gist.github.com/parkttule/ab02d80c01fc69ba868a2478cc1c4050
Based on the test/PreMarkets.t.sol test file, the PoC code has been written, and the attack scenario is as follows:
user represents a regular user who, during the process of creating an offer, submits a collateral amount equivalent to 1.2 ether to the capital pool. This step reflects typical usage activity within Tadle.
user1 is the attacker. user1 also creates an offer in the same way as a regular user.
Subsequently, user1 creates a taker based on their self-created offer and manipulates the tokenmanager mapping value to their desired amount.
user1 then creates a taker themselves and proceeds to make unlimited withdrawals based on the manipulated value.
The balances of the capital pool and user1 before and after the attack are compared.
Executing this PoC code allows the attacker to drain the balance existing in the capital pool.
The impact of this attack is significant, as it has the potential to drain all the funds stored in the capital pool, which holds the collateral provided by users. While the current PoC code simplifies the process by minimizing the use of functions and does not drain all the funds, theoretically, an attacker could create offers with multiple accounts and manipulate the claimAbleAmount during the taker creation process. This would allow them to drain the entire capital pool, making it a critical vulnerability.
I have written the PoC code using Foundry.
To address the vulnerability, the following patch should be applied within the withdraw function. This patch ensures that the userTokenBalanceMap[_msgSender()][_tokenAddress][_tokenBalanceType] value is reset by the amount withdrawn. Here's an example of how the code might be updated
https://gist.github.com/parkttule/6af7dab9efc67b579d03339f38ae2f8b
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.