Tadle

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

Inability to Close Bid Taker for Directly Created Offers

Summary

The DeliveryPlace contract's closeBidTaker function will always to fail for all stocks created directly from offers due to an incorrect assumption about the preOffer field. This renders the function unusable for a significant portion of potential use cases, effectively locking users out of closing their bid positions. When a user attempts to close a bid taker position using closeBidTaker, the function first retrieves the stock information. For directly created offers, the stockInfo.preOffer is address(0x0). The function immediately reverts due to the InvalidStock check, preventing any further execution. This occurs regardless of the offer's validity or the user's authorization to close the position.

Vulnerability Details

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

In the offer creation process, stocks are created with their preOffer field set to address(0x0).

/// @dev update stock info
stockInfoMap[stockAddr] = StockInfo({
id: offerId,
stockStatus: StockStatus.Initialized,
stockType: params.offerType == OfferType.Ask
? StockType.Bid
: StockType.Ask,
authority: _msgSender(),
maker: makerAddr,
:142 preOffer: address(0x0), //@notice
offer: offerAddr,
points: params.points,
amount: params.amount
});

  • The closeBidTaker function in the DeliveryPlace contract contains the following check:

if (stockInfo.preOffer == address(0x0)) {
revert InvalidStock();
}

This check assumes that all valid stocks must have a non-zero preOffer address, which contradicts how stocks are initially created.

Proof Of Code

//PreMarkets.t.sol
function test_ask_offer_turbo_usdc() public {
vm.startPrank(user);
preMarktes.createOffer(
CreateOfferParams(
marketPlace,
address(mockUSDCToken),
1000,
0.01 * 1e18,
12000,
300,
OfferType.Ask,
OfferSettleType.Turbo
)
);
address offerAddr = GenerateAddress.generateOfferAddress(0);
preMarktes.createTaker(offerAddr, 500);
StockInfo memory _info = preMarktes.getStockInfo(GenerateAddress.generateStockAddress(0)); // This is the first one
emit log_named_uint(" This is the amount",_info.amount);
emit log_named_address(" This is the authority",_info.authority);
emit log_named_address(" This is the preOffer address",_info.preOffer);
emit log_named_address(" This is the Offer address",_info.offer);
deliveryPlace.closeBidTaker(GenerateAddress.generateStockAddress(0)); // This will always revert
vm.stopPrank();
}

Run

forge test --match-test test_ask_offer_turbo_usdc
[⠊] Compiling...
[⠢] Compiling 1 files with Solc 0.8.26
[⠆] Solc 0.8.26 finished in 6.13s
Compiler run successful!
Ran 1 test for test/PreMarkets.t.sol:PreMarketsTest
[FAIL. Reason: InvalidStock()] test_ask_offer_turbo_usdc() (gas: 1281339)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 13.29ms (3.55ms CPU time)
Ran 1 test suite in 22.83ms (13.29ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/PreMarkets.t.sol:PreMarketsTest
[FAIL. Reason: InvalidStock()] test_ask_offer_turbo_usdc() (gas: 1281339)@audit always revert
Encountered a total of 1 failing tests, 0 tests succeeded

Impact

  • Users are unable to close bid taker positions for directly created offers.

  • It could lead to an accumulation of "zombie" offers that can't be closed or settled.

Tools Used

Manual code review

Recommendations

  • Modify the closeBidTaker function to handle stocks with preOffer set to address(0x0)

Updates

Lead Judging Commences

0xnevi Lead Judge
9 months ago
0xnevi Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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