Pieces Protocol

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

Documentation Discrepancy, the documentation does not mention a 2% fee; however, the contract logic deducts a 1% fee from both the buyer and the seller, which contradicts the protocol's stated terms.

Description:

In function buyOrder, buyer is require to send 1% more ETH than the order price, and the seller will receive 99% of the order price, the protocol doc never states this 2% charge.

function buyOrder(uint256 orderIndex, address seller) external payable {
...
@> uint256 fee = order.price / 100;
@> uint256 sellerFee = fee / 2;
@> if(msg.value < order.price + sellerFee) {
@> revert TokenDivider__InsuficientEtherForFees();
@> }
...
}

Impact:

Users will pay more/earn less, resulting in financial harm.

Proof of Concept:

add the following in test/unit/TokenDividerTest.t.sol

modifier nftSell(uint256 price, uint256 sellAmount) {
ERC20Mock erc20Mock = ERC20Mock(tokenDivider.getErc20InfoFromNft(address(erc721Mock)).erc20Address);
vm.startPrank(USER);
erc20Mock.approve(address(tokenDivider), sellAmount);
tokenDivider.sellErc20(address(erc721Mock), price, sellAmount);
vm.stopPrank();
_;
}
...
function testBuyErc20WithFee() public nftDivided nftSell(1e18, AMOUNT/2) {
ERC20Mock erc20Mock = ERC20Mock(tokenDivider.getErc20InfoFromNft(address(erc721Mock)).erc20Address);
uint256 amountToSell = AMOUNT / 2;
uint256 price = tokenDivider.getOrderPrice(USER, 0);
uint256 fee = price / 100;
uint256 sellerFee = fee / 2;
assertEq(erc20Mock.balanceOf(USER2), 0);
assertEq(tokenDivider.getBalanceOf(USER2, address(erc20Mock)), 0);
assertEq(erc20Mock.balanceOf(address(tokenDivider)), amountToSell);
// check eth
uint256 ownerInitialBalance = tokenDivider.owner().balance;
uint256 userInitialBalance = USER.balance;
uint256 user2InitialBalance = USER2.balance;
assertEq(address(tokenDivider).balance, 0);
assertEq(USER.balance, 0);
assertEq(USER2.balance, STARTING_USER_BALANCE);
vm.prank(USER2);
tokenDivider.buyOrder{value: price + sellerFee}(0, USER);
assertEq(erc20Mock.balanceOf(USER2), amountToSell);
assertEq(tokenDivider.getBalanceOf(USER2, address(erc20Mock)), amountToSell);
assertEq(erc20Mock.balanceOf(address(tokenDivider)), 0);
// check eth
uint256 ownerBalanceAfter = tokenDivider.owner().balance;
uint256 userBalanceAfter = USER.balance;
uint256 user2BalanceAfter = USER2.balance;
assertEq(ownerBalanceAfter, ownerInitialBalance + fee);
assertEq(userBalanceAfter, userInitialBalance + price - sellerFee);
assertEq(user2BalanceAfter, user2InitialBalance - price - sellerFee);
}

and run the test forge test --mt testBuyErc20WithFee

Recommended Mitigation:

Update the documentation to reflect the 2% fee charged to the buyer and seller.

Updates

Lead Judging Commences

fishy Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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