pragma solidity 0.8.20; import {Test} from "forge-std/Test.sol"; import "@openzeppelin-contracts/token/ERC20/ERC20.sol"; abstract contract ERC20TransferTest is Test { ERC20 tokenTransfer; uint256 amountTransfer; uint256 totalSupplyTransfer; address aliceTransfer; address bobTransfer; function initializeTransfer( address alice, address bob, address token, uint256 amount, uint256 totalSupply ) public { tokenTransfer = ERC20(token); amountTransfer = amount; totalSupplyTransfer = totalSupply; aliceTransfer = alice; bobTransfer = bob; } function test_transfer_tokenTransfers() public { _mintTransferTokens(aliceTransfer, amountTransfer); assertEq(tokenTransfer.balanceOf(aliceTransfer), amountTransfer); assertEq(tokenTransfer.balanceOf(bobTransfer), 0); vm.prank(aliceTransfer); bool success = tokenTransfer.transfer(bobTransfer, amountTransfer); assertEq(success, true); assertEq(tokenTransfer.balanceOf(bobTransfer), amountTransfer); assertEq(tokenTransfer.balanceOf(aliceTransfer), 0); } function test_transfer_transferFuzzing(uint64 fuzzingTransferAmount) public { if (totalSupplyTransfer == 0) vm.assume(fuzzingTransferAmount > 0); else vm.assume(fuzzingTransferAmount > 0 && fuzzingTransferAmount < totalSupplyTransfer); _mintTransferTokens(aliceTransfer, fuzzingTransferAmount); assertEq(tokenTransfer.balanceOf(aliceTransfer), fuzzingTransferAmount); assertEq(tokenTransfer.balanceOf(bobTransfer), 0); vm.prank(aliceTransfer); bool success = tokenTransfer.transfer(bobTransfer, fuzzingTransferAmount); assertEq(success, true); assertEq(tokenTransfer.balanceOf(bobTransfer), fuzzingTransferAmount); assertEq(tokenTransfer.balanceOf(aliceTransfer), 0); } function test_transfer_couldNotTransferMoreThanAvailable() public { _mintTransferTokens(aliceTransfer, amountTransfer); vm.expectRevert(); vm.prank(aliceTransfer); tokenTransfer.transfer(bobTransfer, type(uint256).max); } function test_transfer_doesNotChangeTotalSupply() public { assertEq(tokenTransfer.totalSupply(), totalSupplyTransfer); _mintTransferTokens(aliceTransfer, amountTransfer); if (totalSupplyTransfer == 0) { assertEq(tokenTransfer.totalSupply(), amountTransfer); vm.prank(aliceTransfer); tokenTransfer.transfer(bobTransfer, amountTransfer); assertEq(tokenTransfer.totalSupply(), amountTransfer); } else { assertEq(tokenTransfer.totalSupply(), totalSupplyTransfer); vm.prank(aliceTransfer); tokenTransfer.transfer(bobTransfer, amountTransfer); assertEq(tokenTransfer.totalSupply(), totalSupplyTransfer); } } function _mintTransferTokens(address who, uint256 value) internal virtual; }