Tadle

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

Malicious actors can cause address collisions leading to DOS (`PreMarktes::createOffer` and `PreMarktes::createTaker`)

Summary

Vulnerability Detail

The PreMarktes contract implements a marketplace system where users can create offers and take existing offers. Two key functions, createOffer() and createTaker(), are responsible for these operations. Both functions utilize a shared offerId variable to generate unique addresses for offers, makers, and stocks.

The core issue lies in the incrementation of offerId in both functions.

offerId = offerId + 1;

In createOffer(), offerId is used to generate addresses for the maker, offer, and stock, and then incremented. Similarly, in createTaker(), offerId is used to generate a stock address and then incremented again. This dual incrementation creates a race condition where the same offerId could be used to generate addresses in both functions, potentially leading to address collisions.

The GenerateAddress library uses offerId to deterministically generate addresses:

address makerAddr = GenerateAddress.generateMakerAddress(offerId);
address offerAddr = GenerateAddress.generateOfferAddress(offerId);
address stockAddr = GenerateAddress.generateStockAddress(offerId);

If these generated addresses collide with existing entries in makerInfoMap, offerInfoMap, or stockInfoMap, the transaction will revert with errors such as MakerAlreadyExist, OfferAlreadyExist, or StockAlreadyExist.

This issue allows malicious actors to manipulate the timing of their transactions to cause intentional address collisions, effectively denying service to legitimate users.

Impact

The impact of this vulnerability is severe. It can lead to a denial of service for legitimate users trying to create offers or take existing ones. Malicious actors can exploit this issue to disrupt the normal functioning of the marketplace, potentially causing financial losses and eroding user trust in the platform.

Proof of Concept

  1. User A calls createOffer:

    • offerId is used to generate addresses for the maker, offer, and stock.

    • offerId is incremented.

  2. User B calls createTaker:

    • The same offerId is used to generate a stock address.

    • offerId is incremented again.

  3. If the generated addresses collide with existing entries in makerInfoMap, offerInfoMap, or stockInfoMap, the transaction will revert with errors such as MakerAlreadyExist, OfferAlreadyExist, or StockAlreadyExist.

Tools Used

Manual review

Recommendation

To fix this issue, ensure that offerId is incremented only in createOffer. Remove the incrementation of offerId in createTaker to prevent address collisions and logical errors.

function createOffer(CreateOfferParams calldata params) external payable {
// ... existing code ...
address makerAddr = GenerateAddress.generateMakerAddress(offerId);
address offerAddr = GenerateAddress.generateOfferAddress(offerId);
address stockAddr = GenerateAddress.generateStockAddress(offerId);
offerId = offerId + 1; // Increment offerId only in createOffer
// ... existing code ...
}
function createTaker(address _offer, uint256 _points) external payable {
// ... existing code ...
address stockAddr = GenerateAddress.generateStockAddress(offerId);
// Do not increment offerId here
- offerId = offerId + 1;
// ... existing code ...
}
Updates

Lead Judging Commences

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

finding-PreMarkets-createOffer-offerId-increment-after

I believe this is valid low severity, although there is inconsistency here when using the correct `offerId` for assigning offerIds and generating the unique addresses as seen [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L67-L69), this is purely an accounting error for offerIds. If we generate the offerId using current `offerId - 1`, the appropriate listing/taker orders can still be created against those offers.

Support

FAQs

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