Pieces Protocol

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

Excess ETH received in `buyOrder` function has no withdrawal mechanism, leading to permanent loss of funds

Summary

Excess ETH sent during the buyOrder function is not refunded to the buyer, leading to permanent loss of funds.

Vulnerability Details

In the buyOrder function, the contract checks if the msg.value is greater than or equal to the required amount (order.price + sellerFee). However, if the buyer sends more ETH than required, the excess ETH remains stuck in the contract. There is no mechanism to refund the excess ETH to the buyer.

Impact

Users who send more ETH than necessary will lose their funds permanently or ETH sent accidentally (e.g., via selfdestruct or a direct transfer) cannot be recovered.
This can lead to significant financial losses, especially for high-value transactions.

The contract will accumulate unnecessary ETH over time, which could be exploited or cause operational issues.

Tools Used

  • Manual code review.

Recommendations

  1. Calculate the excess ETH (msg.value - totalRequired) and refund it to the buyer using transfer or call.

    if (msg.value > order.price + sellerFee) {
    uint256 excess = msg.value - (order.price + sellerFee);
    payable(msg.sender).call{value: excess}("");
    }
  2. Ensure the contract only accepts the exact amount of ETH required for the transaction, or explicitly handle excess ETH.

  3. Add a function to allow the owner to withdraw any accidentally locked ETH, ensuring transparency and control over the contract's balance.

    function withdraw() external onlyOwner {
    payable(owner).call{value: address(this).balance}("");
    }
Updates

Lead Judging Commences

fishy Lead Judge 5 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.