Tadle

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

Due to the incorrect use of collateralRate, users could steal funds from the protocol.

Summary

Due to the incorrect use of collateralRate, users could steal funds from the protocol.

Vulnerability Details

The collateralRate used by the user when depositing the collateral in listOffer comes from offerInfo which is stockInfo.preOffer.

https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/PreMarkets.sol#L345-L353

OfferInfo storage offerInfo = offerInfoMap[stockInfo.preOffer];
...
/// @dev transfer collateral when offer settle type is protected
if (makerInfo.offerSettleType == OfferSettleType.Protected) {
uint256 transferAmount = OfferLibraries.getDepositAmount(
offerInfo.offerType,
offerInfo.collateralRate,
_amount,
true,
Math.Rounding.Ceil
);

However, when generating new offer data later, the _collateralRate in the parameters is used directly.

https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/PreMarkets.sol#L369-L379

/// @dev update offer info
offerInfoMap[offerAddr] = OfferInfo({
id: stockInfo.id,
authority: _msgSender(),
maker: offerInfo.maker,
offerStatus: OfferStatus.Virgin,
offerType: offerInfo.offerType,
abortOfferStatus: AbortOfferStatus.Initialized,
points: stockInfo.points,
amount: _amount,
collateralRate: _collateralRate, //@audit param, not offerInfo.collateralRate

In Protected mode, it is not required that these two values are equal, it merely limits the minimum value of _collateralRate.

https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/PreMarkets.sol#L304-L306

if (_collateralRate < Constants.COLLATERAL_RATE_DECIMAL_SCALER) {
revert InvalidCollateralRate();
}

In closeOffer, the amount of refund is calculated based on the offer data generated in listOffer, which means that the offerInfo.collateralRate in closeOffer is the _collateralRate in listOffer, not the collateralRate used during deposit.

https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/PreMarkets.sol#L441-L447

uint256 refundAmount = OfferLibraries.getRefundAmount(
offerInfo.offerType,
offerInfo.amount,
offerInfo.points,
offerInfo.usedPoints,
offerInfo.collateralRate
);

Therefore, since the collateralRate used when depositing and withdrawing collateral is different, if the rate is lower when depositing and higher when withdrawing, users could steal protocol funds.

For example:

  1. Alice performs listOffer, where the _collateralRate parameter is 110%, and the amount is 100.

  2. When depositing collateral, the offerInfo.collateralRate used is 100%, so Alice deposits 100 tokens as collateral.

  3. In the newly generated offer from listOffer, the collateralRate is set to the _collateralRate of 110%.

  4. Alice performs closeOffer to close the newly generated offer. In closeOffer, the offerInfo.collateralRate obtained is 110%, so the refund amount is 110.

  5. Finally, Alice steals 110-100=10 tokens from the protocol through the two steps of listOffer + closeOffer.

Impact

Users could steal funds from the protocol.

Tools Used

vscode

Recommendations

Ensure that the collateralRate during deposit and the collateralRate when generating a new offer in listOffer are consistent.

Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-PreMarkets-listOffer-collateralRate-manipulate

Valid high severity, because the collateral rate utilized when creating an offer is stale and retrieved from a previously set collateral rate, it allows possible manipilation of refund amounts using an inflated collateral rate to drain funds from the CapitalPool contract

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!