Tadle

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

Zero-Point Settlement in Ask Offers Enabling Market Manipulation and Liquidity Drain

Summary

The settleAskMaker function in the DeliveryPlace contract allows for settlements with zero points, enabling malicious actors to manipulate the market, drain liquidity, and cause financial harm to users and the protocol.

Vulnerability Detail

The vulnerability exists in the settleAskMaker function of the DeliveryPlace contract. The function allows the settlement of Ask offers with any number of points, including zero, as long as it doesn't exceed the used points of the offer.

function settleAskMaker(address _offer, uint256 _settledPoints) external {
(
OfferInfo memory offerInfo,
MakerInfo memory makerInfo,
MarketPlaceInfo memory marketPlaceInfo,
MarketPlaceStatus status
) = getOfferInfo(_offer);
if (_settledPoints > offerInfo.usedPoints) {
revert InvalidPoints();
}
// ... (other checks and logic)
if (_settledPoints == offerInfo.usedPoints) {
// ... (logic for full settlement)
}
// ... (rest of the function)
}

The function only checks if _settledPoints exceeds offerInfo.usedPoints, but doesn't enforce a minimum value greater than zero. This could allow a malicious actor to create a large Ask offer, let it be partially filled, and then settle with zero points, effectively cancelling the remaining offer without fulfilling their obligations.

POC

  1. Scenario Setup: Imagine a malicious actor, Alice, who wants to manipulate the market and profit from the ability to settle with zero points.

  2. Initial Actions:

    • Alice creates a large Ask offer for 1,000,000 points of a popular token at a slightly below-market price.

    • This large offer appears very attractive to buyers and could potentially influence the market price.

  3. Market Impact:

    • The presence of this large, attractive offer causes other sellers to lower their prices to compete.

    • Buyers, seeing the large offer, feel confident in the market liquidity and continue to trade normally.

  4. Partial Fills:

    • Various buyers start taking portions of Alice's offer. Let's say 50% of the offer gets filled.

    • At this point, Alice has received payment for 500,000 points worth of tokens.

  5. Market Manipulation:

    • Just as the market price is about to rise above Alice's offer price, making her offer unprofitable, she decides to act.

  6. Exploiting Zero Settlement:

    • Alice calls settleAskMaker with _settledPoints = 0.

    • If this is allowed, Alice effectively cancels her remaining offer without delivering any tokens.

  7. Consequences:

    • Buyers who thought they had secured tokens at a good price suddenly find their orders unfilled.

    • The market, which had adjusted to the presence of Alice's large offer, experiences a sudden liquidity shock.

    • This could trigger a rapid price increase as buyers scramble to fill their orders elsewhere.

  8. Profit for Alice:

    • Alice has received payment for 500,000 points worth of tokens.

    • She never had these tokens in the first place and has no obligation to deliver them due to the zero settlement.

    • She can now buy the necessary tokens at the new, higher market price and still profit from the difference.

Impact

If exploited, this vulnerability could lead to:

  1. Market Manipulation: Attackers could create large, attractive offers to influence market prices, then cancel them through zero-point settlements.

  2. Liquidity Drain: Sudden cancellation of large offers could cause a liquidity shock in the market.

  3. Financial Losses: Users who believed they had secured tokens at a certain price might find their orders unfilled, forcing them to buy at potentially higher prices.

Tool used

Manual Review

Recommendation

  1. Enforce Minimum Settlement: Modify the settleAskMaker function to require a minimum settlement amount greater than zero:

function settleAskMaker(address _offer, uint256 _settledPoints) external {
// ... (existing checks)
if (_settledPoints == 0 || _settledPoints > offerInfo.usedPoints) {
revert InvalidPoints();
}
// ... (rest of the function)
}
  1. Implement Partial Settlement Locks: Introduce a time lock for partial settlements to prevent rapid manipulations:

mapping(address => uint256) private lastPartialSettlementTime;
function settleAskMaker(address _offer, uint256 _settledPoints) external {
// ... (existing checks)
if (_settledPoints < offerInfo.usedPoints) {
require(block.timestamp >= lastPartialSettlementTime[_offer] + PARTIAL_SETTLEMENT_LOCKTIME, "Partial settlement too soon");
lastPartialSettlementTime[_offer] = block.timestamp;
}
// ... (rest of the function)
}
Updates

Lead Judging Commences

0xnevi Lead Judge
12 months ago
0xnevi Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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