Pieces Protocol

First Flight #32
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Invalid

Buyer is forced to pay more than price while buying tokens

Description

Buyer sends the money to the `TokenDivider::buyOrder` function for buying the tokens for desired nft. For that they are forced to pay more then the actual price set by seller.
```javascript
function buyOrder(uint256 orderIndex, address seller) external payable {
if(seller == address(0)) {
revert TokenDivider__InvalidSeller();
}
SellOrder memory order = s_userToSellOrders[seller][orderIndex];
if(msg.value < order.price) {
revert TokenDivider__IncorrectEtherAmount();
}
uint256 fee = order.price / 100;
uint256 sellerFee = fee / 2;
@> if(msg.value < order.price + sellerFee) {
revert TokenDivider__InsuficientEtherForFees();
}
```
As function describe it will first check the `amount` sent by the buyer weather it is less then of price or not. But after that check the function perform some fees calculations then after it is again checking the amount sent by buyer with additional charges of fees.
```javascript
@> if(msg.value < order.price + sellerFee) {
```
This will force buyer to pay extra money to the seller. if user sent exact amount of money then it will revert.

Impact

Force buyer to pay or send extra money to the function or contract.

Proof of Concept

Add this code in the `TokenDividerTest` contract
Code:
```javascript
function testBuyerForceToPayExtraMoney() public nftDivided {
ERC20Mock erc20Mock = ERC20Mock(tokenDivider.getErc20InfoFromNft(address(erc721Mock)).erc20Address);
vm.startPrank(USER);
erc20Mock.approve(address(tokenDivider), AMOUNT);
tokenDivider.sellErc20(address(erc721Mock), 200, AMOUNT);
vm.stopPrank();
address user1 = makeAddr("user1");
vm.deal(user1, 200);
vm.prank(user1);
vm.expectRevert(TokenDivider.TokenDivider__InsuficientEtherForFees.selector);
tokenDivider.buyOrder{value: 200}(0, USER);
}
```
As code explains, If a seller set price `200` for their specific amount of token, And the buyer sent exact amount of money which is `200` then it will revert due to incorrect condition checking.
1. USER -> sell token -> price = 200
2. user1 -> buy token -> sent money = 200
1. fee = 200 / 2 = 2.
2. sellerFee = fee / 2 = 2 / 2 = 1.
3. Amount sent by user1 (200) < 200 + 1 ---> Rvert.

Recommended Mitigation

Remove the Additional check for additional fees on price.
Recommended function:
```diff
function buyOrder(uint256 orderIndex, address seller) external payable {
if(seller == address(0)) {
revert TokenDivider__InvalidSeller();
}
SellOrder memory order = s_userToSellOrders[seller][orderIndex];
if(msg.value < order.price) {
revert TokenDivider__IncorrectEtherAmount();
}
uint256 fee = order.price / 100;
uint256 sellerFee = fee / 2;
- if(msg.value < order.price + sellerFee) {
- revert TokenDivider__InsuficientEtherForFees();
- }
```
Updates

Lead Judging Commences

fishy Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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