Tadle

Tadle
DeFiFoundry
27,750 USDC
View results
Submission Details
Severity: medium
Invalid

The `listOffe`r function is vulnerable to front-running attacks.

Summary

The listOffer function in the contract is vulnerable to front-running attacks. An attacker can exploit this vulnerability by observing pending transactions in the mempool and submitting their own transaction with higher gas fees to manipulate the order of execution, potentially causing financial losses for users by taking advantage of changes in market conditions or the behavior of other users' transactions.

Vulnerability Details

The listOffer function allows users to list their offers in the marketplace. However, due to the lack of mechanisms to prevent front-running, an attacker can monitor the mempool for listOffer transactions and submit their own competing transaction with a higher gas price. This allows the attacker to have their transaction mined before the victim's transaction, potentially manipulating the market or capturing arbitrage opportunities at the expense of the original user.

Impact

The front-running vulnerability can lead to the following impacts:

  • Financial Loss for Users: Users may lose out on favorable market conditions or arbitrage opportunities due to front-running.

  • Market Manipulation: Attackers can manipulate the order of transactions, affecting the integrity and fairness of the marketplace.

  • User Trust: The presence of such vulnerabilities could erode user trust in the platform, leading to decreased usage and reputation damage.

Tools Used

Manual Code Review

Recommendations

Introduce a commit-reveal scheme for the listOffer function to prevent attackers from knowing the offer details in advance. Here's an example implementation:

Commit Phase:

function commitOffer(bytes32 _commitment) external {
// Store the commitment hash in a mapping
commitments[msg.sender] = _commitment;
emit OfferCommitted(msg.sender, _commitment);
}
function revealOffer(uint256 _amount, uint256 _collateralRate, uint256 _nonce, bytes32 _secret) external {
bytes32 commitment = keccak256(abi.encodePacked(_amount, _collateralRate, _nonce, _secret));
require(commitments[msg.sender] == commitment, "Invalid commitment");
// Proceed with offer listing
_listOffer(_amount, _collateralRate);
delete commitments[msg.sender];
}

Private Function _listOffer:

function _listOffer(uint256 _amount, uint256 _collateralRate) private {
// Existing implementation of listOffer
}

Add a delay mechanism to prevent immediate listing:

mapping(address => uint256) public offerListingTimes;
function listOffer(
address _stock,
uint256 _amount,
uint256 _collateralRate
) external payable {
// Check time delay
require(block.timestamp >= offerListingTimes[msg.sender] + DELAY_PERIOD, "Delay period not passed");
// Update listing time
offerListingTimes[msg.sender] = block.timestamp;
// Existing implementation of listOffer
}

Encourage users to use randomized gas prices by providing a utility function:

function getRandomGasPrice() internal view returns (uint256) {
// Example function to get a randomized gas price
return block.timestamp % 1000000 + 1; // Replace with more complex logic if needed
}
Updates

Lead Judging Commences

0xnevi Lead Judge
about 1 year ago
0xnevi Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

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