Tadle

Tadle
DeFiFoundry
27,750 USDC
View results
Submission Details
Severity: high
Valid

Incorrect calculation of MakerRefund leads to loss of funds

Summary

Due to the incorrect calculation of depositAmount in the abortBidTaker function of PreMarkets, the MakerRefund is calculated incorrectly. Depending on the parameters of stock, this could result in a critical amount of losses for the protocol or the maker entity.

Vulnerability Details

In abortBidTaker function of PreMarkets, depositAmount (that being the amount of tokens the stock authority deposited) is calculated as follows:

uint256 depositAmount = stockInfo.points.mulDiv(
preOfferInfo.points,
preOfferInfo.amount,
Math.Rounding.Floor
);

Let's express this as a standard formula:

It can be seen that the calculation above is incorrect. In reality, the stock was buying stockInfo.points points, where the price for preOfferInfo.points points was preOfferInfo.amount tokens.

This means that the price per point was equal to , and the stock should have deposited . This can be verified in the createTaker function of PreMarkets, which calculates depositAmount in lines 212-216.

uint256 depositAmount = _points.mulDiv(
offerInfo.amount,
offerInfo.points,
Math.Rounding.Ceil
);

So, we can now see that depositAmount is calculated incorrectly in abortBidTaker. The abortBidTaker function will then calculate transferAmount, which depends on depositAmount, add a token balance equal to transferAmount to the stock owner, and mark the stock as finished. Depending on the parameters of stock and offer, there could be significant losses either for the protocol (if the MakerRefund is larger than it should be) or for the stock owner (if the MakerRefund is smaller than it should be).

Impact

Depending on stockInfo.points, preOfferInfo.points, preOfferInfo.amount, it varies who will bear losses.

Let's consider hypothetical cases where both protocol and stock owner losses occur (the specific numbers are chosen for simplicity). This will serve as a PoC.

  1. Stock owner bears losses:
    preOfferInfo.points = 10,preOfferInfo.amount = 20,stockInfo.points = 5.
    The real depositAmount would be equal to .
    The depositAmount calculated in abortBidTaker would be equal to .
    As we can see, the depositAmount calculated in abortBidTaker is way smaller than it should be, so the stock owner bears losses.

  2. Protocol bears losses:
    preOfferInfo.points = 100,preOfferInfo.amount = 10,stockInfo.points = 80.
    The real depositAmount would be equal to .
    The depositAmount calculated in abortBidTaker would be equal to .
    As we can see, the depositAmount calculated in abortBidTaker is way bigger than it should be, so the protocol bears losses.

Tools Used

Manual Review

Recommendations

Fix calculation of depositAmount in abortBidTaker function.

-uint256 depositAmount = stockInfo.points.mulDiv(
- preOfferInfo.points,
- preOfferInfo.amount,
- Math.Rounding.Floor
-);
+uint256 depositAmount = stockInfo.points.mulDiv(
+preOfferInfo.amount,
+preOfferInfo.points,
+Math.Rounding.Floor
+);
Updates

Lead Judging Commences

0xnevi Lead Judge 12 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? Chat with us on Discord, Twitter or Linkedin.