Tadle

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

Incorrect authority cause dos in settleAskTaker()

Summary

In DeliverPlace::settleAskTaker(), the msg.sender should be the stock's authority, not the preOffer's authority. Incorrect authority will cause settleAskTaker() dos.

Vulnerability Details

In DeliverPlace::settleAskTaker(), the ask taker(seller) can settle the trade when the market place's status is AskSettling. The problem is that when we check access control for this function, we use _msgSender() != offerInfo.authority. This means that only the offer's authority has the permission to settle this ask taker. This is wrong, the actual msg.sender should be the ask taker(seller).

For example:

  • Alice creates one bid offer.

  • Bob matches Alice's offer via createTaker().

  • When the admin update market, and the market place's status is changed to AskSettling. Bob needs to settle ask taker via transferring point token into the capitalPool. But settleAskTaker() will be reverted, because Bob's stock's preOffer belongs to Alice. Bob does not have the permission to trigger settleAskTaker().

function settleAskTaker(address _stock, uint256 _settledPoints) external {
IPerMarkets perMarkets = tadleFactory.getPerMarkets();
StockInfo memory stockInfo = perMarkets.getStockInfo(_stock);
(
OfferInfo memory offerInfo,
MakerInfo memory makerInfo,
MarketPlaceInfo memory marketPlaceInfo,
MarketPlaceStatus status
) = getOfferInfo(stockInfo.preOffer);
...
if (status == MarketPlaceStatus.AskSettling) {
// @audit confirmed, this should be the taker' authority, is this correct ??? offer trigger this one ???
if (_msgSender() != offerInfo.authority) {
revert Errors.Unauthorized();
}
} else {
if (_msgSender() != owner()) {
revert Errors.Unauthorized();
}
if (_settledPoints > 0) {
revert InvalidPoints();
}
}
...
}

Poc

Add this function into PreMarkets.t.sol, and this function will be reverted because of Unauthorized().
user creates one bid offer.
user2 create one ask taker to match user's bid offer.
user2 call settleAskTaker and failed.

function test_create_bid_offer_turbo_usdc() public {
vm.startPrank(user);
preMarktes.createOffer(
CreateOfferParams(
marketPlace,
address(mockUSDCToken),
1000,
0.01 * 1e18,
12000,
300,
OfferType.Bid,
OfferSettleType.Turbo
)
);
vm.stopPrank();
vm.startPrank(user2);
address offerAddr = GenerateAddress.generateOfferAddress(0);
preMarktes.createTaker(offerAddr, 500);
address stock1Addr = GenerateAddress.generateStockAddress(1);
vm.stopPrank();
vm.prank(user1);
systemConfig.updateMarket(
"Backpack",
address(mockPointToken),
0.01 * 1e18,
block.timestamp - 1,
3600
);
vm.startPrank(user);
mockPointToken.approve(address(tokenManager), 10000 * 10 ** 18);
vm.stopPrank();
vm.startPrank(user2);
deliveryPlace.settleAskTaker(stock1Addr, 500);
vm.stopPrank();
vm.startPrank(user);
deliveryPlace.closeBidOffer(offerAddr);
vm.stopPrank();
}

Impact

The ask taker cannot settle the trade. The core function will be blocked.

Tools Used

Manual

Recommendations

Correct the authority to check msg.sender is the stockInfo.authority.

Updates

Lead Judging Commences

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

finding-PreMarkets-settleAskTaker-wrong-stock-authority

Valid high severity, when taker offers are created pointing to a `offer`, the relevant `stockInfoMap` offers are created with the owner of the offer aka `authority`, set as the creater of the offer, as seen [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L245). Because of the wrong check within settleAskTaker, it will permanently DoS the final settlement functionality for taker offers for the maker that listed the original offer, essentially bricking the whole functionality of the market i.e. maker will always get refunded the original collateral, and takers will never be able to transact the original points put up by the maker. This occurs regardless of market mode.

Support

FAQs

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