Pieces Protocol

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

[H-01] The balance of the contract is not updated in the sell order.

Description:

When the user publishes the order, he sends the tokens to the contract. But the the contract balance is not updated accordingly.

function sellErc20(
address nftPegged,
uint256 price,
uint256 amount
) external {
if (nftPegged == address(0)) {
revert TokenDivider__NftAddressIsZero();
}
if (amount == 0) {
revert TokenDivider__AmountCantBeZero();
}
ERC20Info memory tokenInfo = nftToErc20Info[nftPegged];
if (balances[msg.sender][tokenInfo.erc20Address] < amount) {
revert TokenDivider__InsuficientBalance();
}
balances[msg.sender][tokenInfo.erc20Address] -= amount;
s_userToSellOrders[msg.sender].push(
SellOrder({
seller: msg.sender,
erc20Address: tokenInfo.erc20Address,
price: price,
amount: amount
})
);
emit OrderPublished(amount, msg.sender, nftPegged);
@>
IERC20(tokenInfo.erc20Address).transferFrom(
msg.sender,
address(this),
amount
);
}

Impact:

High. The contract balance is incorrect.

Proof of Concept:
The last assertion fails. The contract balance should have increased.

function testMySell() public {
vm.startPrank(USER);
erc721Mock.approve(address(tokenDivider), TOKEN_ID);
tokenDivider.divideNft(address(erc721Mock), TOKEN_ID, AMOUNT);
ERC20Mock erc20Mock = ERC20Mock(
tokenDivider.getErc20InfoFromNft(address(erc721Mock)).erc20Address
);
erc20Mock.approve(address(tokenDivider), AMOUNT);
tokenDivider.sellErc20(address(erc721Mock), 1e18, AMOUNT);
vm.stopPrank();
//1. user has the balance decreased from is account
assertEq(tokenDivider.getBalanceOf(USER, address(erc20Mock)), 0);
//2. order is created
assertEq(tokenDivider.getOrderPrice(USER, 0), 1e18);
//3. contract has the balance increased
assertEq(
tokenDivider.getBalanceOf(address(tokenDivider), address(erc20Mock)),
1e18
);
}

Recommended Mitigation:

Update the balance:

function sellErc20(address nftPegged, uint256 price,uint256 amount) external {
if(nftPegged == address(0)) {
revert TokenDivider__NftAddressIsZero();
}
if( amount == 0) {
revert TokenDivider__AmountCantBeZero();
}
ERC20Info memory tokenInfo = nftToErc20Info[nftPegged];
if(balances[msg.sender][tokenInfo.erc20Address] < amount) {
revert TokenDivider__InsuficientBalance();
}
balances[msg.sender][tokenInfo.erc20Address] -= amount;
s_userToSellOrders[msg.sender].push(
SellOrder({
seller: msg.sender,
erc20Address: tokenInfo.erc20Address,
price: price,
amount: amount
})
);
emit OrderPublished(amount,msg.sender, nftPegged);
+ balances[address(this)][tokanInfo.erc20Address] += amount;
IERC20(tokenInfo.erc20Address).transferFrom(msg.sender,address(this), amount);
}
Updates

Lead Judging Commences

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

Support

FAQs

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