Tadle

Tadle
DeFi
30,000 USDC
Ended
View results
Submission Details
Severity: high
Valid

Rounding Issue in `abortBidTaker` Causes Loss of Funds For the Takers

Summary

In preMarket contract, the abortBidTaker function is designed to allow users to abort their bids and receive a refund of their deposit. However, a rounding issue in the getDepositAmount function leads to incorrect calculations of the required deposit, causing the system to give 0 deposit amount for refund. This results in users losing their deposited funds when attempting to abort their bids.

Vulnerability Details

  • The abortBidTaker function is designed to allow users to abort their bids and receive a refund of their deposit.

  • The depositAmount calculation in the abortBidTaker function makes a rounding issue making the deposit amount to be 0.

  • Due to this rounding error, the system will not add any balance to the user's account and mark's the stock status as "finished,"leading to the user's inability to retrieve their deposited funds when calling abortBidTaker.

Impact

  • Users are unable to recover their deposited funds due to the incorrect stock status triggered by the rounding issue.

  • This results in a direct loss of funds for users who attempt to abort their bids under these conditions.

  • The loss of users funds gets locked in the captialPool contract and can't be retrieved.

Proof of Concept

  1. Bob is taker and trades with the preMarket contract.

  2. Bob deposits buys 500 point tokens from alice(maker).

  3. Bob lists his offer and waits for takers to accept.

  4. Alice aborts her ask offer.

  5. Bob tries to abort his bid taker to get back his deposited collateral as the settlement type is Protected.

  6. Due to the rounding issue in the abortBidTaker function, Bob's deposit amount is calculated as 0.

  7. Bob's funds are locked in the contract, and he is unable to retrieve his deposited amount.

Proof of Code

For testing the POC, run the following command:

forge testc --mt test_FortisAudits_AbortBidTaker_RoundingIssue -vvvv

Add the following code to the PreMarkets.t.sol contract:

function test_FortisAudits_AbortBidTaker_RoundingIssue() public {
address alice = address(0x123);
address bob = address(0x456);
deal(address(mockUSDCToken), alice, 12e15);
deal(address(mockUSDCToken), bob, 5175e12 + 12e15);

vm.startPrank(alice);
mockUSDCToken.approve(address(tokenManager), type(uint256).max);
preMarktes.createOffer(
CreateOfferParams(
marketPlace,
address(mockUSDCToken),
1000,
0.01 * 1e18,
12000,
300,
OfferType.Ask,
OfferSettleType.Protected
)
);
vm.stopPrank();

vm.startPrank(bob);
console2.log("Bob balance Before Offer Taken:", mockUSDCToken.balanceOf(bob));
mockUSDCToken.approve(address(tokenManager), type(uint256).max);
address offerAddr = GenerateAddress.generateOfferAddress(0);
address stockAddr = GenerateAddress.generateStockAddress(0);
address stock1Addr = GenerateAddress.generateStockAddress(1);
preMarktes.createTaker(offerAddr, 500);

preMarktes.listOffer(stock1Addr, 0.01 * 1e18, 12000);
vm.stopPrank();

vm.prank(address(capitalPool));
capitalPool.approve(address(mockUSDCToken));

Here is the output of the test:

Logs:
Bob balance Before Offer Taken: 17175000000000000
Bob balance After Offer Taken And Listed The Offer: 0
Bob balance After Abort Bid Offer: 0
Tokens stuck in the contract: 17025000000000000

Tools Used

  • Manual Review

Recommendation

  • Fix the Rounding Issue: Modify the depositAmount calculation to ensure that rounding errors are mitigated, possibly by using more precise calculations or by adjusting how deposits are calculated.

Updates

Community Judging Commences

Community Judging Judge
7 months ago
Community Judgement Published
57.1% Invalid

Lead Judging Commences

0xnevi Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

[invalid] finding-Premarkets-depositAmount-precision-loss

Valid medium, given the free nature of the markets, it may be possible that such an offer type where both low amount of points correspond to lower decimal and lower amount of collateral value, so I believe medium severity is appropriate.

Appeal created

0xnevi Lead Judge
6 months ago

The rounding is adequtely proven in the PoC, although the recommendation and root cause identification seems to be off, but I believe this is arguably a duplicate of #1504

0xnevi Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-PreMarkets-abortBidTaker-amount-wrong-StockInfo-points

Valid high severity, due to incorrect computation of `depositAmount` within `abortBidTaker`, when aborting bid offers created by takers, the collateral refund will be completely wrong for the taker, and depending on the difference between the value of `points` and `amount`, it can possibly even round down to zero, causing definite loss of funds. If not, if points were worth less than the collateral, this could instead be used to drain the CapitalPool contract instead.

Support

FAQs

Can’t find an answer? Join our Discord or follow us on Twitter.

Cyfrin
Updraft
CodeHawks
Solodit
Resources