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();
assertEq(tokenDivider.getBalanceOf(USER, address(erc20Mock)), 0);
assertEq(tokenDivider.getOrderPrice(USER, 0), 1e18);
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);
}