// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {Test} from 'forge-std/Test.sol'; import {DeployTokenDivider} from 'script/DeployTokenDivider.s.sol'; import {TokenDivider} from 'src/TokenDivider.sol'; import {ERC721Mock} from '../mocks/ERC721Mock.sol'; import {ERC20Mock} from '@openzeppelin/contracts/mocks/token/ERC20Mock.sol'; contract TokenDividerSellTest is Test { DeployTokenDivider deployer; TokenDivider tokenDivider; ERC721Mock erc721Mock; address public USER = makeAddr("user"); address public USER2 = makeAddr("user2"); uint256 constant public STARTING_USER_BALANCE = 10e18; uint256 constant public AMOUNT = 2e18; uint256 constant public TOKEN_ID = 0; function setUp() public { deployer = new DeployTokenDivider(); tokenDivider = deployer.run(); erc721Mock = new ERC721Mock(); erc721Mock.mint(USER); // divide the ERC721 and mint ERC20 vm.startPrank(USER); erc721Mock.approve(address(tokenDivider), TOKEN_ID); tokenDivider.divideNft( address(erc721Mock), TOKEN_ID, AMOUNT ); vm.stopPrank(); } function test_assertSetUp() public { erc721Mock.mint(USER); ERC20Mock erc20Mock = ERC20Mock( tokenDivider.getErc20InfoFromNft( address(erc721Mock) ).erc20Address ); // assert if NFT already moved to tokenDivider assertEq( erc721Mock.ownerOf(TOKEN_ID), address(tokenDivider) ); // assert if USER has the ERC20 token assertEq( tokenDivider.getBalanceOf(USER, address(erc20Mock)), AMOUNT ); } function test_sellErc20() public { ERC20Mock erc20Mock = ERC20Mock( tokenDivider.getErc20InfoFromNft( address(erc721Mock) ).erc20Address ); uint256 sellAmount = 1; vm.startPrank(USER); erc20Mock.approve(address(tokenDivider), sellAmount); tokenDivider.sellErc20( address(erc721Mock), 1, sellAmount ); vm.stopPrank(); assertEq( tokenDivider.getBalanceOf(USER, address(erc20Mock)), AMOUNT - 1 ); } function test_sellErc20WithZeroPrice() public { ERC20Mock erc20Mock = ERC20Mock( tokenDivider.getErc20InfoFromNft( address(erc721Mock) ).erc20Address ); uint256 sellAmount = 1e17; uint256 sellPrice = 0; vm.startPrank(USER); erc20Mock.approve(address(tokenDivider), sellAmount); tokenDivider.sellErc20( address(erc721Mock), sellPrice, sellAmount ); vm.stopPrank(); assertEq( tokenDivider.getBalanceOf(USER, address(erc20Mock)), AMOUNT - sellAmount ); assertEq( sellPrice, tokenDivider.getOrderPrice( address(USER), 0 // index of order price ) ); } function test_sellAndBuyErc20() public { ERC20Mock erc20Mock = ERC20Mock( tokenDivider.getErc20InfoFromNft( address(erc721Mock) ).erc20Address ); uint256 sellAmount = 1e17; uint256 sellPrice = 1 ether; vm.startPrank(USER); erc20Mock.approve(address(tokenDivider), sellAmount); tokenDivider.sellErc20( address(erc721Mock), sellPrice, sellAmount ); vm.stopPrank(); assertEq( tokenDivider.getBalanceOf(USER, address(erc20Mock)), AMOUNT - sellAmount ); uint256 buyPrice = sellPrice + ((sellPrice / 100) / 2); vm.deal( address(USER2), buyPrice ); uint256 contractInitialBalance = address( tokenDivider.owner() ).balance; assertEq( address(USER).balance, 0 ); vm.startPrank(USER2); tokenDivider.buyOrder{value: buyPrice}( 0, address(USER) ); vm.stopPrank(); assertEq( erc20Mock.balanceOf(address(USER2)), sellAmount ); uint256 sellerFee = buyPrice - sellPrice; assertEq( address( tokenDivider.owner() ).balance - contractInitialBalance, sellerFee * 2 ); assertEq( address(USER).balance, sellPrice - sellerFee ); } function test_sellAndBuyErc20With0Price() public { ERC20Mock erc20Mock = ERC20Mock( tokenDivider.getErc20InfoFromNft( address(erc721Mock) ).erc20Address ); uint256 sellAmount = 1e17; uint256 sellPrice = 0 ether; vm.startPrank(USER); erc20Mock.approve(address(tokenDivider), sellAmount); tokenDivider.sellErc20( address(erc721Mock), sellPrice, sellAmount ); vm.stopPrank(); assertEq( tokenDivider.getBalanceOf(USER, address(erc20Mock)), AMOUNT - sellAmount ); uint256 buyPrice = sellPrice + ((sellPrice / 100) / 2); vm.deal( address(USER2), buyPrice ); uint256 contractInitialBalance = address( tokenDivider.owner() ).balance; assertEq( address(USER).balance, 0 ); vm.startPrank(USER2); tokenDivider.buyOrder{value: buyPrice}( 0, address(USER) ); vm.stopPrank(); assertEq( erc20Mock.balanceOf(address(USER2)), sellAmount ); uint256 sellerFee = buyPrice - sellPrice; assertEq( address( tokenDivider.owner() ).balance - contractInitialBalance, sellerFee * 2 ); assertEq( address(USER).balance, sellPrice - sellerFee ); } }