Pieces Protocol

First Flight #32
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: low
Valid

[H-2] Lack of Strict Price Validation in `sellErc20` and Incorrect Ether Amount Check in `buyOrder`

Summary

This contract contains two related vulnerabilities:

  1. Lack of Strict Price Validation in sellErc20
    The function sellErc20(address nftPegged, uint256 price, uint256 amount) does not validate whether price > 0. As a result, users can create sell orders priced at 0 or a nominal amount (e.g., 1 WEI), which prevents the protocol from collecting meaningful fees.

  2. Incorrect Ether Amount Check in buyOrder
    The function buyOrder(uint256 orderIndex, address seller) only checks if msg.value is at least order.price and an additional calculated fee, but does not enforce an exact match. This allows buyers to overpay, potentially causing loss of excess funds or inconsistencies in the protocol’s behavior.


Vulnerability Details

1. Lack of Strict Price Validation in sellErc20

In sellErc20, there is no check to ensure that the price parameter is greater than zero. When an order with price = 0 is created, the protocol collects no fees, as fees are calculated as a percentage of order.price. If price is 0 or extremely low (e.g., 1 WEI), the fee (fee = order.price / 100) remains 0 or negligible, leading to minimal or no revenue for the protocol.

// If order.price < 100, then fee = order.price / 100 = 0
uint256 fee = order.price / 100;
// sellerFee = fee / 2 = 0
uint256 sellerFee = fee / 2;

2. Incorrect Ether Amount Check in buyOrder

In buyOrder, the contract verifies msg.value via:

if (msg.value < order.price) revert TokenDivider__IncorrectEtherAmount();
if (msg.value < order.price + sellerFee) revert TokenDivider__InsuficientEtherForFees();

This check only enforces a minimum required amount and does not prevent overpayment. Consequently, users can accidentally send more Ether than necessary, risking loss of additional funds since no mechanism refunds the excess.


Impact

  1. Loss of Protocol Earnings

    • Sellers can set price = 0 or a nominal value, resulting in no fees being collected.

  2. Potential Buyer Losses

    • Buyers may inadvertently pay more Ether than required.

    • Any excess Ether remains in the contract, potentially lost or misdirected.

  3. Unpredictable Protocol Behavior

    • Overpayments and inadequate fee collection can lead to confusion among users and potential exploitation.


Recommendations

1. Add Strict Validation for price in sellErc20

Ensure price is sufficiently large to yield a non-zero fee. As a simple example:

if (price < 100) revert TokenDivider__InvalidAmount();

This guarantees that order.price / 100 is at least 1, enforcing a minimum fee.

2. Enforce Exact Ether Checks in buyOrder

Require msg.value to match the exact sum of the seller payout and protocol fee. For instance:

function buyOrder(uint256 orderIndex, address seller) external payable {
if (seller == address(0)) revert TokenDivider__InvalidSeller();
SellOrder memory order = s_userToSellOrders[seller][orderIndex];
// Calculate fees
uint256 protocolFee = order.price / 100;
uint256 sellerFee = protocolFee / 2;
uint256 sellerEtherTransferValue = order.price - sellerFee;
uint256 totalRequired = sellerEtherTransferValue + protocolFee;
// Enforce exact match of msg.value
if (msg.value != totalRequired) revert TokenDivider__InsuficientEtherForFees();
...
}

This approach prevents overpayment, ensuring predictable protocol behavior and correct fee collection.

Updates

Lead Judging Commences

fishy Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Appeal created

jayp Submitter
7 months ago
fishy Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Token misshandling

The extra eth sent by the user in the buy order will be locked in the contract forever

Support

FAQs

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