Tadle

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

Front-Running Vulnerability in `createOffer` Function

Summary

The createOffer function in the PreMarktes contract is susceptible to a front-running attack due to the delayed increment of the offerId. This vulnerability can allow an attacker to gain an unfair advantage in the marketplace by observing pending transactions and creating their own offer with a higher offerId.

Vulnerability Details

The createOffer function performs the following sequence of operations:

  1. It performs various checks and calculations.

  2. It generates addresses for the maker, offer, and stock using the current offerId.

  3. It transfers tokens to the capital pool.

  4. It updates the state variables makerInfoMap, offerInfoMap, and stockInfoMap.

  5. It increments the offerId.

The vulnerability lies in the fact that offerId is incremented only after generating addresses and transferring tokens. This creates a window of opportunity for an attacker to observe the pending transaction, extract the offerId used, and quickly submit their own transaction with a slightly higher offerId and a higher gas price.

Impact

the marketplace uses offerId to determine priority or order in auctions or queues, an attacker could consistently outbid or jump ahead of other users.

Tools Used

Manual review

Recommendations

Move the offerId increment to the beginning of the createOffer function, before any other operations. This ensures that the offerId used for address generation and subsequent actions is already the next available one, preventing front-running based on predictable IDs.

function createOffer(CreateOfferParams calldata params) external payable {
/**
* @dev points and amount must be greater than 0
* @dev eachTradeTax must be less than 100%, decimal scaler is 10000
* @dev collateralRate must be more than 100%, decimal scaler is 10000
*/
if (params.points == 0x0 || params.amount == 0x0) {
revert Errors.AmountIsZero();
}
if (params.eachTradeTax > Constants.EACH_TRADE_TAX_DECIMAL_SCALER) {
revert InvalidEachTradeTaxRate();
}
if (params.collateralRate < Constants.COLLATERAL_RATE_DECIMAL_SCALER) {
revert InvalidCollateralRate();
}
/// @dev market place must be online
ISystemConfig systemConfig = tadleFactory.getSystemConfig();
MarketPlaceInfo memory marketPlaceInfo = systemConfig
.getMarketPlaceInfo(params.marketPlace);
marketPlaceInfo.checkMarketPlaceStatus(
block.timestamp,
MarketPlaceStatus.Online
);
+ offerId = offerId + 1;
/// @dev generate address for maker, offer, stock.
address makerAddr = GenerateAddress.generateMakerAddress(offerId);
address offerAddr = GenerateAddress.generateOfferAddress(offerId);
address stockAddr = GenerateAddress.generateStockAddress(offerId);
if (makerInfoMap[makerAddr].authority != address(0x0)) {
revert MakerAlreadyExist();
}
if (offerInfoMap[offerAddr].authority != address(0x0)) {
revert OfferAlreadyExist();
}
if (stockInfoMap[stockAddr].authority != address(0x0)) {
revert StockAlreadyExist();
}
// ... (rest of the function) ...
}
Updates

Lead Judging Commences

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

Support

FAQs

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