282 lines
6.4 KiB
Solidity
282 lines
6.4 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.18;
|
|
|
|
|
|
import {Test, console} 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';
|
|
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
|
|
|
|
|
|
contract TokenDiverTest 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); // @auditor: user has the NFT
|
|
vm.deal(USER2, STARTING_USER_BALANCE); // @auditor: user2 got 10 ether
|
|
}
|
|
|
|
function test_assertSetUp() public view {
|
|
// USER has the ERC721 NFT of TOKEN_ID
|
|
assertTrue(address(erc721Mock.ownerOf(TOKEN_ID)) == address(USER));
|
|
|
|
// USER2 has no ERC721 NFT of TOKEN_ID
|
|
assertTrue(address(erc721Mock.ownerOf(TOKEN_ID)) != address(USER2));
|
|
}
|
|
|
|
function test_divideNftSuccessfully() public {
|
|
vm.startPrank(USER);
|
|
|
|
// approve the NFT to receive the NFT in USER
|
|
erc721Mock.approve(address(tokenDivider), TOKEN_ID);
|
|
|
|
tokenDivider.divideNft(
|
|
address(erc721Mock),
|
|
TOKEN_ID,
|
|
AMOUNT
|
|
);
|
|
vm.stopPrank();
|
|
|
|
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_failIf_sendNFTDuringDivide() public {
|
|
vm.startPrank(USER);
|
|
|
|
// approve the NFT to receive the NFT in USER
|
|
erc721Mock.approve(address(tokenDivider), TOKEN_ID);
|
|
|
|
// send the NFT to USER2
|
|
erc721Mock.safeTransferFrom(
|
|
address(USER),
|
|
address(USER2),
|
|
TOKEN_ID
|
|
);
|
|
|
|
vm.expectRevert(
|
|
TokenDivider.TokenDivider__NotFromNftOwner.selector
|
|
);
|
|
tokenDivider.divideNft(
|
|
address(erc721Mock),
|
|
TOKEN_ID,
|
|
AMOUNT
|
|
);
|
|
|
|
vm.stopPrank();
|
|
}
|
|
|
|
function test_sendNFTBeforeDivide() public {
|
|
vm.startPrank(USER);
|
|
|
|
// send the NFT to USER2
|
|
erc721Mock.safeTransferFrom(
|
|
address(USER),
|
|
address(USER2),
|
|
TOKEN_ID
|
|
);
|
|
|
|
vm.stopPrank();
|
|
|
|
vm.startPrank(USER2);
|
|
|
|
// approve the NFT to receive the NFT in USER
|
|
erc721Mock.approve(address(tokenDivider), TOKEN_ID);
|
|
|
|
tokenDivider.divideNft(
|
|
address(erc721Mock),
|
|
TOKEN_ID,
|
|
AMOUNT
|
|
);
|
|
|
|
vm.stopPrank();
|
|
|
|
ERC20Mock erc20Mock = ERC20Mock(
|
|
tokenDivider.getErc20InfoFromNft(address(erc721Mock)).erc20Address
|
|
);
|
|
|
|
// assert if USER2 has the ERC20 token
|
|
assertEq(
|
|
tokenDivider.getBalanceOf(USER2, address(erc20Mock)),
|
|
AMOUNT
|
|
);
|
|
}
|
|
|
|
function test_failIf_nonExistenceNftTokenId() public {
|
|
vm.startPrank(USER);
|
|
|
|
// approve the NFT to receive the NFT in USER
|
|
erc721Mock.approve(address(tokenDivider), TOKEN_ID);
|
|
|
|
vm.expectRevert();
|
|
tokenDivider.divideNft(
|
|
address(erc721Mock),
|
|
404,
|
|
AMOUNT
|
|
);
|
|
vm.stopPrank();
|
|
}
|
|
|
|
function test_failWhen_reMintTheDividedERC20Token() public {
|
|
vm.startPrank(USER);
|
|
|
|
// approve the NFT to receive the NFT in USER
|
|
erc721Mock.approve(address(tokenDivider), TOKEN_ID);
|
|
|
|
tokenDivider.divideNft(
|
|
address(erc721Mock),
|
|
TOKEN_ID,
|
|
AMOUNT
|
|
);
|
|
vm.stopPrank();
|
|
|
|
ERC20Mock erc20Mock = ERC20Mock(
|
|
tokenDivider.getErc20InfoFromNft(address(erc721Mock)).erc20Address
|
|
);
|
|
|
|
// assert if USER has the ERC20 token
|
|
assertEq(
|
|
tokenDivider.getBalanceOf(USER, address(erc20Mock)),
|
|
AMOUNT
|
|
);
|
|
|
|
vm.startPrank(USER2);
|
|
erc20Mock.mint(address(USER2), AMOUNT);
|
|
vm.stopPrank();
|
|
|
|
assertEq(
|
|
tokenDivider.getBalanceOf(
|
|
USER,
|
|
address(erc20Mock)
|
|
),
|
|
AMOUNT
|
|
);
|
|
assertEq(
|
|
tokenDivider.getBalanceOf(
|
|
USER2,
|
|
address(erc20Mock)
|
|
),
|
|
erc20Mock.balanceOf(address(USER2))
|
|
);
|
|
assertEq(
|
|
erc20Mock.totalSupply(),
|
|
AMOUNT
|
|
);
|
|
}
|
|
|
|
function test_divideSameNFTAddressWithDifferentTokenId() public {
|
|
vm.startPrank(USER);
|
|
|
|
// approve the NFT to receive the NFT in USER
|
|
erc721Mock.approve(address(tokenDivider), TOKEN_ID);
|
|
|
|
tokenDivider.divideNft(
|
|
address(erc721Mock),
|
|
TOKEN_ID,
|
|
AMOUNT
|
|
);
|
|
vm.stopPrank();
|
|
|
|
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
|
|
);
|
|
|
|
uint256 counterfeitTokenId = TOKEN_ID + 1;
|
|
erc721Mock.mint(USER2);
|
|
assertEq(
|
|
erc721Mock.ownerOf(counterfeitTokenId),
|
|
address(USER2)
|
|
);
|
|
|
|
// USER2 divide the counterfeit
|
|
vm.startPrank(USER2);
|
|
|
|
// approve the NFT to receive the NFT in USER2
|
|
erc721Mock.approve(
|
|
address(tokenDivider),
|
|
counterfeitTokenId
|
|
);
|
|
|
|
tokenDivider.divideNft(
|
|
address(erc721Mock),
|
|
counterfeitTokenId,
|
|
AMOUNT
|
|
);
|
|
vm.stopPrank();
|
|
|
|
// now both of users (USER and USER2) has the same amount of registered ERC20 tokens despite it refer to different NFT Token Id
|
|
|
|
ERC20Mock erc20MockCounterfeit = ERC20Mock(
|
|
tokenDivider.getErc20InfoFromNft(address(erc721Mock)).erc20Address
|
|
);
|
|
// assert if NFT already moved to tokenDivider
|
|
|
|
assertEq(
|
|
erc721Mock.ownerOf(counterfeitTokenId),
|
|
address(tokenDivider)
|
|
);
|
|
|
|
// assert if previous NFT is still being hold by contract
|
|
assertEq(
|
|
erc721Mock.ownerOf(TOKEN_ID),
|
|
address(tokenDivider)
|
|
);
|
|
|
|
// assert if USER2 has the ERC20 token
|
|
assertEq(
|
|
tokenDivider.getBalanceOf(
|
|
USER2,
|
|
address(erc20MockCounterfeit)
|
|
),
|
|
AMOUNT
|
|
);
|
|
// assert if USER has the ERC20 token
|
|
assertEq(
|
|
tokenDivider.getBalanceOf(
|
|
USER,
|
|
address(erc20MockCounterfeit)
|
|
),
|
|
AMOUNT
|
|
);
|
|
}
|
|
|
|
}
|