fix annoying forge warnings

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2026-10-23 12:38:29 +03:00
parent 5f4365a3a8
commit b131a064db
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
22 changed files with 229 additions and 152 deletions

View File

@ -3,7 +3,7 @@ pragma solidity ^0.8.20;
import {Script} from "forge-std/Script.sol";
import {stdJson} from "forge-std/StdJson.sol";
import "@openzeppelin-contracts/utils/Strings.sol";
import {Strings} from "@openzeppelin-contracts/utils/Strings.sol";
contract AddressFileRWScript is Script {
using stdJson for string;
@ -18,6 +18,7 @@ contract AddressFileRWScript is Script {
Strings.toString(block.chainid),
"/run-latest.json"
);
// forge-lint: disable-next-line(unsafe-cheatcode)
string memory json = vm.readFile(path);
bytes memory contractAddress = stdJson.parseRaw(
json,
@ -42,6 +43,7 @@ contract AddressFileRWScript is Script {
uint256 k = length;
j = _i;
while (j != 0) {
// forge-lint: disable-next-line(unsafe-typecast)
bstr[--k] = bytes1(uint8(48 + j % 10));
j /= 10;
}

View File

@ -2,9 +2,7 @@
pragma solidity ^0.8.20;
import {Script,console} from "forge-std/Script.sol";
import "../src/UniswapV2Factory.sol";
import "./AddressFileRW.sol";
import {UniswapV2Factory} from "../src/UniswapV2Factory.sol";
contract UniswapV2FactoryScript is Script {
function setUp() public {}

View File

@ -2,9 +2,9 @@
pragma solidity ^0.8.20;
import {console} from "forge-std/Script.sol";
import "../src/UniswapV2Router.sol";
import {UniswapV2Router} from "../src/UniswapV2Router.sol";
import "./AddressFileRW.sol";
import {AddressFileRWScript} from "./AddressFileRW.sol";
contract UniswapV2RouterScript is AddressFileRWScript {
function setUp() public {}

View File

@ -2,7 +2,7 @@
pragma solidity ^0.8.20;
import {Script,console} from "forge-std/Script.sol";
import "../src/WETH9.sol";
import {WETH9} from "../src/WETH9.sol";
contract WETH9Script is Script {
function setUp() public {}

View File

@ -1,18 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.20;
import "./interfaces/IUniswapV2ERC20.sol";
import {IUniswapV2ERC20} from "./interfaces/IUniswapV2ERC20.sol";
contract UniswapV2ERC20 is IUniswapV2ERC20 {
string public constant override name = "Uniswap V2";
string public constant override symbol = "UNI-V2";
uint8 public constant override decimals = 18;
string private constant NAME = "Uniswap V2";
string private constant SYMBOL = "UNI-V2";
uint8 private constant DECIMALS = 18;
uint256 public override totalSupply;
mapping(address => uint256) public override balanceOf;
mapping(address => mapping(address => uint256)) public override allowance;
// forge-lint: disable-next-line(mixed-case-variable)
bytes32 public override DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
// forge-lint: disable-next-line(mixed-case-variable)
bytes32 public constant override PERMIT_TYPEHASH =
0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint256) public override nonces;
@ -21,7 +24,7 @@ contract UniswapV2ERC20 is IUniswapV2ERC20 {
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256(bytes(NAME)),
keccak256(bytes("1")),
block.chainid,
address(this)
@ -29,6 +32,18 @@ contract UniswapV2ERC20 is IUniswapV2ERC20 {
);
}
function name() public override pure returns (string memory) {
return NAME;
}
function symbol() public override pure returns (string memory) {
return SYMBOL;
}
function decimals() public override pure returns (uint8) {
return DECIMALS;
}
function _mint(address to, uint256 value) internal {
totalSupply += value;
balanceOf[to] += value;
@ -90,6 +105,7 @@ contract UniswapV2ERC20 is IUniswapV2ERC20 {
bytes32 s
) external override {
if (deadline < block.timestamp) revert("UniswapV2: EXPIRED");
// forge-lint: disable-next-item(asm-keccak256)
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",

View File

@ -1,9 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.20;
import "./interfaces/IUniswapV2Factory.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./UniswapV2Pair.sol";
import {IUniswapV2Factory} from "./interfaces/IUniswapV2Factory.sol";
import {IUniswapV2Pair} from "./interfaces/IUniswapV2Pair.sol";
import {UniswapV2Pair} from "./UniswapV2Pair.sol";
contract UniswapV2Factory is IUniswapV2Factory {
bytes32 public constant PAIR_HASH = keccak256(type(UniswapV2Pair).creationCode);
@ -32,6 +32,7 @@ contract UniswapV2Factory is IUniswapV2Factory {
if (getPair[token0][token1] != address(0)) revert("UniswapV2: PAIR_EXISTS");
bytes memory bytecode = type(UniswapV2Pair).creationCode;
// forge-lint: disable-next-line(asm-keccak256)
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
assembly {
pair := create2(0, add(bytecode, 32), mload(bytecode), salt)

View File

@ -1,16 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.20;
import "./UniswapV2ERC20.sol";
import {UniswapV2ERC20} from "./UniswapV2ERC20.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IUniswapV2Factory.sol";
import "./interfaces/IUniswapV2Callee.sol";
import "./interfaces/IERC20.sol";
import {IUniswapV2Pair} from "./interfaces/IUniswapV2Pair.sol";
import {IUniswapV2Factory} from "./interfaces/IUniswapV2Factory.sol";
import {IUniswapV2Callee} from "./interfaces/IUniswapV2Callee.sol";
import {IERC20} from "./interfaces/IERC20.sol";
import "./libraries/Math.sol";
import "./libraries/UQ112x112.sol";
import "./libraries/TransferHelper.sol";
import {UniswapV2Math} from "./libraries/Math.sol";
import {UQ112x112} from "./libraries/UQ112x112.sol";
import {TransferHelper} from "./libraries/TransferHelper.sol";
contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
using UQ112x112 for uint224;
@ -31,10 +31,9 @@ contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
uint256 private unlocked = 1;
modifier lock() {
if (unlocked == 0) revert("UniswapV2: LOCKED");
unlocked = 0;
_lockBefore();
_;
unlocked = 1;
_lockAfter();
}
function getReserves()
@ -72,8 +71,8 @@ contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
price1CumulativeLast += uint256(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
}
}
reserve0 = uint112(balance0);
reserve1 = uint112(balance1);
reserve0 = uint112(balance0); // forge-lint: disable-line(unsafe-typecast)
reserve1 = uint112(balance1); // forge-lint: disable-line(unsafe-typecast)
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
@ -192,4 +191,13 @@ contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
function sync() external override lock {
_update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
}
function _lockBefore() internal {
if (unlocked == 0) revert("UniswapV2: LOCKED");
unlocked = 0;
}
function _lockAfter() internal {
unlocked = 1;
}
}

View File

@ -1,28 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.20;
import "./interfaces/IUniswapV2Factory.sol";
import "./interfaces/IUniswapV2Router.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IWETH.sol";
import "./interfaces/IERC20.sol";
import {IUniswapV2Factory} from "./interfaces/IUniswapV2Factory.sol";
import {IUniswapV2Router} from "./interfaces/IUniswapV2Router.sol";
import {IUniswapV2Pair} from "./interfaces/IUniswapV2Pair.sol";
import {IWETH} from "./interfaces/IWETH.sol";
import {IERC20} from "./interfaces/IERC20.sol";
import {TransferHelper} from "./libraries/TransferHelper.sol";
import {UniswapV2Library} from "./libraries/UniswapV2Library.sol";
contract UniswapV2Router is IUniswapV2Router {
//solhint-disable-next-line immutable-vars-naming
// forge-lint: disable-next-line(screaming-snake-case-immutable)
address public immutable override factory;
address public immutable override WETH;
modifier ensure(uint256 deadline) {
if (deadline < block.timestamp) revert("UniswapV2Router: EXPIRED");
_ensure(deadline);
_;
}
constructor(address _factory, address _WETH) {
constructor(address _factory, address _weth) {
factory = _factory;
WETH = _WETH;
WETH = _weth;
}
receive() external payable {
@ -82,10 +82,12 @@ contract UniswapV2Router is IUniswapV2Router {
liquidity = IUniswapV2Pair(pair).mint(to);
}
// forge-lint: disable-next-line(mixed-case-function)
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline
@ -95,6 +97,7 @@ contract UniswapV2Router is IUniswapV2Router {
virtual
override
ensure(deadline)
// forge-lint: disable-next-line(mixed-case-variable)
returns (uint256 amountToken, uint256 amountETH, uint256 liquidity)
{
(amountToken, amountETH) = _addLiquidity(
@ -133,7 +136,7 @@ contract UniswapV2Router is IUniswapV2Router {
returns (uint256 amountA, uint256 amountB)
{
address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
require(IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity)); // send liquidity to pair
(uint256 amount0, uint256 amount1) = IUniswapV2Pair(pair).burn(to);
(address token0, ) = UniswapV2Library.sortTokens(tokenA, tokenB);
(amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0);
@ -141,10 +144,12 @@ contract UniswapV2Router is IUniswapV2Router {
if (amountB < amountBMin) revert("UniswapV2Router: INSUFFICIENT_B_AMOUNT");
}
// forge-lint: disable-next-line(mixed-case-function)
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline
@ -153,6 +158,7 @@ contract UniswapV2Router is IUniswapV2Router {
virtual
override
ensure(deadline)
// forge-lint: disable-next-line(mixed-case-variable)
returns (uint256 amountToken, uint256 amountETH)
{
(amountToken, amountETH) = removeLiquidity(
@ -204,10 +210,12 @@ contract UniswapV2Router is IUniswapV2Router {
);
}
// forge-lint: disable-next-line(mixed-case-function)
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline,
@ -219,6 +227,7 @@ contract UniswapV2Router is IUniswapV2Router {
external
virtual
override
// forge-lint: disable-next-line(mixed-case-variable)
returns (uint256 amountToken, uint256 amountETH)
{
address pair = UniswapV2Library.pairFor(factory, token, WETH);
@ -242,14 +251,16 @@ contract UniswapV2Router is IUniswapV2Router {
);
}
// **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) ****
// forge-lint: disable-next-line(mixed-case-function)
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline
// forge-lint: disable-next-line(mixed-case-variable)
) public virtual override ensure(deadline) returns (uint256 amountETH) {
(, amountETH) = removeLiquidity(
token,
@ -265,10 +276,12 @@ contract UniswapV2Router is IUniswapV2Router {
TransferHelper.safeTransferETH(to, amountETH);
}
// forge-lint: disable-next-line(mixed-case-function)
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline,
@ -276,6 +289,7 @@ contract UniswapV2Router is IUniswapV2Router {
uint8 v,
bytes32 r,
bytes32 s
// forge-lint: disable-next-line(mixed-case-variable)
) external virtual override returns (uint256 amountETH) {
address pair = UniswapV2Library.pairFor(factory, token, WETH);
uint256 value = approveMax ? type(uint256).max : liquidity;
@ -370,6 +384,7 @@ contract UniswapV2Router is IUniswapV2Router {
_swap(amounts, path, to);
}
// forge-lint: disable-next-line(mixed-case-function)
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
@ -391,6 +406,7 @@ contract UniswapV2Router is IUniswapV2Router {
_swap(amounts, path, to);
}
// forge-lint: disable-next-line(mixed-case-function)
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
@ -418,6 +434,7 @@ contract UniswapV2Router is IUniswapV2Router {
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
// forge-lint: disable-next-line(mixed-case-function)
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
@ -445,6 +462,7 @@ contract UniswapV2Router is IUniswapV2Router {
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
// forge-lint: disable-next-line(mixed-case-function)
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
@ -525,6 +543,7 @@ contract UniswapV2Router is IUniswapV2Router {
}
}
// forge-lint: disable-next-line(mixed-case-function)
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
@ -542,6 +561,7 @@ contract UniswapV2Router is IUniswapV2Router {
}
}
// forge-lint: disable-next-line(mixed-case-function)
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
@ -601,4 +621,8 @@ contract UniswapV2Router is IUniswapV2Router {
) public view virtual override returns (uint256[] memory amounts) {
return UniswapV2Library.getAmountsIn(factory, amountOut, path);
}
function _ensure(uint256 deadline) internal view {
if (deadline < block.timestamp) revert("UniswapV2Router: EXPIRED");
}
}

View File

@ -21,7 +21,9 @@ interface IUniswapV2ERC20 {
uint256 value
) external returns (bool);
// forge-lint: disable-next-line(mixed-case-function)
function DOMAIN_SEPARATOR() external view returns (bytes32);
// forge-lint: disable-next-line(mixed-case-function)
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint256);

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.20;
import "./IUniswapV2ERC20.sol";
import {IUniswapV2ERC20} from "./IUniswapV2ERC20.sol";
interface IUniswapV2Pair is IUniswapV2ERC20 {
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
@ -16,6 +16,7 @@ interface IUniswapV2Pair is IUniswapV2ERC20 {
);
event Sync(uint112 reserve0, uint112 reserve1);
// forge-lint: disable-next-line(mixed-case-function)
function MINIMUM_LIQUIDITY() external pure returns (uint256);
function factory() external view returns (address);
function token0() external view returns (address);

View File

@ -4,19 +4,24 @@ pragma solidity =0.8.20;
import {IUniswapV2Router01} from "./IUniswapV2Router01.sol";
interface IUniswapV2Router is IUniswapV2Router01 {
// forge-lint: disable-next-line(mixed-case-function)
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline
// forge-lint: disable-next-line(mixed-case-variable)
) external returns (uint256 amountETH);
// forge-lint: disable-next-line(mixed-case-function)
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline,
@ -24,6 +29,7 @@ interface IUniswapV2Router is IUniswapV2Router01 {
uint8 v,
bytes32 r,
bytes32 s
// forge-lint: disable-next-line(mixed-case-variable)
) external returns (uint256 amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
@ -34,6 +40,7 @@ interface IUniswapV2Router is IUniswapV2Router01 {
uint256 deadline
) external;
// forge-lint: disable-next-line(mixed-case-function)
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
@ -41,6 +48,7 @@ interface IUniswapV2Router is IUniswapV2Router01 {
uint256 deadline
) external payable;
// forge-lint: disable-next-line(mixed-case-function)
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,

View File

@ -17,16 +17,19 @@ interface IUniswapV2Router01 {
uint256 deadline
) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
// forge-lint: disable-next-line(mixed-case-function)
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
// forge-lint: disable-next-line(mixed-case-variable)
returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
function removeLiquidity(
@ -39,13 +42,16 @@ interface IUniswapV2Router01 {
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
// forge-lint: disable-next-line(mixed-case-function)
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline
// forge-lint: disable-next-line(mixed-case-variable)
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
@ -62,10 +68,12 @@ interface IUniswapV2Router01 {
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
// forge-lint: disable-next-line(mixed-case-function)
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
// forge-lint: disable-next-line(mixed-case-variable)
uint256 amountETHMin,
address to,
uint256 deadline,
@ -73,6 +81,7 @@ interface IUniswapV2Router01 {
uint8 v,
bytes32 r,
bytes32 s
// forge-lint: disable-next-line(mixed-case-variable)
) external returns (uint256 amountToken, uint256 amountETH);
function swapExactTokensForTokens(
@ -91,6 +100,7 @@ interface IUniswapV2Router01 {
uint256 deadline
) external returns (uint256[] memory amounts);
// forge-lint: disable-next-line(mixed-case-function)
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
@ -98,6 +108,7 @@ interface IUniswapV2Router01 {
uint256 deadline
) external payable returns (uint256[] memory amounts);
// forge-lint: disable-next-line(mixed-case-function)
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
@ -106,6 +117,7 @@ interface IUniswapV2Router01 {
uint256 deadline
) external returns (uint256[] memory amounts);
// forge-lint: disable-next-line(mixed-case-function)
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
@ -114,6 +126,7 @@ interface IUniswapV2Router01 {
uint256 deadline
) external returns (uint256[] memory amounts);
// forge-lint: disable-next-line(mixed-case-function)
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,

View File

@ -37,6 +37,7 @@ library TransferHelper {
}
}
// forge-lint: disable-next-line(mixed-case-function)
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
if (!success) revert("TransferHelper::safeTransferETH: ETH transfer failed");

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.20;
import "../interfaces/IUniswapV2Pair.sol";
import {IUniswapV2Pair} from "../interfaces/IUniswapV2Pair.sol";
import {UniswapV2Pair} from "../UniswapV2Pair.sol";
library UniswapV2Library {
// returns sorted token addresses, used to handle return values from pairs sorted in this order
@ -31,7 +32,7 @@ library UniswapV2Library {
bytes1(0xff),
factory,
keccak256(abi.encodePacked(token0, token1)),
hex"430c098d71e70091b6b419a06af9259b7847ea60cfa63fb719a0c9473f6cbb49" // init code hash
keccak256(type(UniswapV2Pair).creationCode) // init code hash
)
)
)

View File

@ -2,13 +2,14 @@
pragma solidity =0.8.20;
contract SigUtils {
bytes32 internal DOMAIN_SEPARATOR;
bytes32 internal immutable DOMAIN_SEPARATOR;
constructor(bytes32 _DOMAIN_SEPARATOR) {
DOMAIN_SEPARATOR = _DOMAIN_SEPARATOR;
constructor(bytes32 domainSeparator) {
DOMAIN_SEPARATOR = domainSeparator;
}
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
// forge-lint: disable-next-line(mixed-case-function)
bytes32 public constant PERMIT_TYPEHASH =
0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
@ -26,6 +27,7 @@ contract SigUtils {
pure
returns (bytes32)
{
// forge-lint: disable-next-item(asm-keccak256)
return
keccak256(
abi.encode(
@ -45,6 +47,7 @@ contract SigUtils {
view
returns (bytes32)
{
// forge-lint: disable-next-item(asm-keccak256)
return
keccak256(
abi.encodePacked(

View File

@ -3,11 +3,11 @@ pragma solidity =0.8.20;
import {Test} from "forge-std/Test.sol";
import "../src/UniswapV2ERC20.sol";
import {UniswapV2ERC20} from "../src/UniswapV2ERC20.sol";
import "./tokens/Permit.t.sol";
import "./tokens/Allowance.t.sol";
import "./tokens/Transfer.t.sol";
import {ERC20PermitTest} from "./tokens/Permit.t.sol";
import {ERC20AllowanceTest} from "./tokens/Allowance.t.sol";
import {ERC20TransferTest} from "./tokens/Transfer.t.sol";
contract UniswapV2ERC20Mintable is UniswapV2ERC20 {
function mint(address to, uint256 value) public {
@ -18,16 +18,16 @@ contract UniswapV2ERC20Mintable is UniswapV2ERC20 {
contract UniswapV2ERC20Test is Test, ERC20PermitTest, ERC20AllowanceTest, ERC20TransferTest {
UniswapV2ERC20Mintable uni;
address constant alice = 0x0000000000000000000000000000000000000001;
address constant bob = 0x0000000000000000000000000000000000000002;
uint256 constant amount = 1e23;
uint256 constant maxAmount = type(uint256).max;
address constant ALICE = 0x0000000000000000000000000000000000000001;
address constant BOB = 0x0000000000000000000000000000000000000002;
uint256 constant AMOUNT = 1e23;
uint256 constant MAX_AMOUTN = type(uint256).max;
function setUp() public {
uni = new UniswapV2ERC20Mintable();
initializePermit(address(uni), amount, maxAmount);
initializeAllowance(alice, bob, address(uni), amount, maxAmount, amount);
initializeTransfer(alice, bob, address(uni), amount, 0);
initializePermit(address(uni), AMOUNT, MAX_AMOUTN);
initializeAllowance(ALICE, BOB, address(uni), AMOUNT, MAX_AMOUTN, AMOUNT);
initializeTransfer(ALICE, BOB, address(uni), AMOUNT, 0);
}
function testNameIsCorrect() public view {

View File

@ -3,11 +3,11 @@ pragma solidity =0.8.20;
import {Test} from "forge-std/Test.sol";
import "../src/UniswapV2Factory.sol";
import "../src/UniswapV2Pair.sol";
import "../src/mock/MockERC20.sol";
import {UniswapV2Factory} from "../src/UniswapV2Factory.sol";
import {UniswapV2Pair} from "../src/UniswapV2Pair.sol";
import {MockERC20} from "../src/mock/MockERC20.sol";
import "../src/libraries/UniswapV2Library.sol";
import {UniswapV2Library} from "../src/libraries/UniswapV2Library.sol";
contract UniswapV2FactoryTest is Test {
UniswapV2Factory public factory;

View File

@ -3,10 +3,10 @@ pragma solidity =0.8.20;
import {Test} from "forge-std/Test.sol";
import "../src/mock/MockERC20.sol";
import "../src/UniswapV2Pair.sol";
import "../src/UniswapV2Factory.sol";
import "../src/libraries/UQ112x112.sol";
import {MockERC20} from "../src/mock/MockERC20.sol";
import {UniswapV2Pair} from "../src/UniswapV2Pair.sol";
import {UniswapV2Factory} from "../src/UniswapV2Factory.sol";
import {UQ112x112} from "../src/libraries/UQ112x112.sol";
contract MockUser {
function addLiquidity(
@ -16,8 +16,9 @@ contract MockUser {
uint256 _amount0,
uint256 _amount1
) public returns (uint256) {
MockERC20(_token0).transfer(pair, _amount0);
MockERC20(_token1).transfer(pair, _amount1);
bool success1 = MockERC20(_token0).transfer(pair, _amount0);
bool success2 = MockERC20(_token1).transfer(pair, _amount1);
require(success1 && success2);
return UniswapV2Pair(pair).mint(address(this));
}
@ -25,7 +26,8 @@ contract MockUser {
public
returns (uint256, uint256)
{
UniswapV2Pair(pair).transfer(pair, liquidity);
bool success = UniswapV2Pair(pair).transfer(pair, liquidity);
require(success);
return UniswapV2Pair(pair).burn(address(this));
}
@ -97,14 +99,13 @@ contract TestUniswapV2Pair is Test {
function assertPairReserves(uint256 _reserve0, uint256 _reserve1) public view {
(uint256 reserve0, uint256 reserve1,) = pair.getReserves();
// (reserve0, reserve1) = sortAmountsByTokens(reserve0, reserve1);
assertEq(reserve0, _reserve0);
assertEq(reserve1, _reserve1);
}
function testMintNewPair() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 liquidity = pair.mint(address(this));
@ -115,12 +116,12 @@ contract TestUniswapV2Pair is Test {
}
function testMintWithReserve() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 l1 = pair.mint(address(this));
token0.transfer(address(pair), 2 ether);
token1.transfer(address(pair), 2 ether);
assertTrue(token0.transfer(address(pair), 2 ether));
assertTrue(token1.transfer(address(pair), 2 ether));
uint256 l2 = pair.mint(address(this));
assertPairReserves(3 ether, 3 ether);
@ -129,12 +130,12 @@ contract TestUniswapV2Pair is Test {
}
function testMintUnequalBalance() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 l1 = pair.mint(address(this));
token0.transfer(address(pair), 4 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 4 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 l2 = pair.mint(address(this));
assertPairReserves(2 ether, 5 ether);
@ -149,16 +150,16 @@ contract TestUniswapV2Pair is Test {
}
function testMintInsufficientLiquidity() public {
token0.transfer(address(pair), 1000);
token1.transfer(address(pair), 1000);
assertTrue(token0.transfer(address(pair), 1000));
assertTrue(token1.transfer(address(pair), 1000));
vm.expectRevert();
pair.mint(address(this));
}
function testMintMultipleUsers() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 l1 = pair.mint(address(this));
uint256 l2 = user.addLiquidity(
@ -176,11 +177,11 @@ contract TestUniswapV2Pair is Test {
}
function testBurn() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 liquidity = pair.mint(address(this));
pair.transfer(address(pair), liquidity);
assertTrue(pair.transfer(address(pair), liquidity));
pair.burn(address(this));
assertEq(pair.balanceOf(address(this)), 0);
@ -197,15 +198,15 @@ contract TestUniswapV2Pair is Test {
}
function testBurnUnequal() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 l0 = pair.mint(address(this));
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 2 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 2 ether));
uint256 l1 = pair.mint(address(this));
pair.transfer(address(pair), l0 + l1);
assertTrue(pair.transfer(address(pair), l0 + l1));
(uint256 amount0, uint256 amount1) = pair.burn(address(this));
(amount0, amount1) = sortAmountsByTokens(amount0, amount1);
@ -222,8 +223,8 @@ contract TestUniswapV2Pair is Test {
}
function testBurnInsufficientLiquidityBurned() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
pair.mint(address(this));
vm.expectRevert();
@ -231,8 +232,8 @@ contract TestUniswapV2Pair is Test {
}
function testBurnMultipleUsers() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 l1 = pair.mint(address(this));
uint256 l2 = user.addLiquidity(
@ -243,7 +244,7 @@ contract TestUniswapV2Pair is Test {
3 ether
);
pair.transfer(address(pair), l1);
assertTrue(pair.transfer(address(pair), l1));
(uint256 amount0, uint256 amount1) = pair.burn(address(this));
(amount0, amount1) = sortAmountsByTokens(amount0, amount1);
@ -256,8 +257,8 @@ contract TestUniswapV2Pair is Test {
}
function testBurnUnbalancedMultipleUsers() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
uint256 l1 = pair.mint(address(this));
uint256 l2 = user.addLiquidity(
@ -271,7 +272,7 @@ contract TestUniswapV2Pair is Test {
(uint256 a00, uint256 a01) = user.removeLiquidity(address(pair), l2);
(a00, a01) = sortAmountsByTokens(a00, a01);
pair.transfer(address(pair), l1);
assertTrue(pair.transfer(address(pair), l1));
(uint256 a10, uint256 a11) = pair.burn(address(this));
(a10, a11) = sortAmountsByTokens(a10, a11);
@ -291,12 +292,12 @@ contract TestUniswapV2Pair is Test {
}
function testSwap() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
pair.mint(address(this));
// transfer to maintain K
token1.transfer(address(pair), 1 ether);
assertTrue(token1.transfer(address(pair), 1 ether));
pair.swap(0.5 ether, 0 ether, address(user), "");
assertPairReserves(1.5 ether, 1 ether);
@ -304,8 +305,8 @@ contract TestUniswapV2Pair is Test {
}
function testSwapMultipleUserLiquidity() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
pair.mint(address(this));
user.addLiquidity(
@ -317,18 +318,18 @@ contract TestUniswapV2Pair is Test {
);
// transfer to maintain K
token0.transfer(address(pair), 2 ether);
assertTrue(token0.transfer(address(pair), 2 ether));
pair.swap(0 ether, 1 ether, address(user), "");
assertPairReserves(4 ether, 4 ether);
}
function testSwapUnderpriced() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
pair.mint(address(this));
// transfer to maintain K
token1.transfer(address(pair), 1 ether);
assertTrue(token1.transfer(address(pair), 1 ether));
pair.swap(0, 0.4 ether, address(user), "");
assertPairReserves(2 ether, 0.6 ether);
}
@ -339,8 +340,8 @@ contract TestUniswapV2Pair is Test {
}
function testSwapInsufficientLiquidity() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
pair.mint(address(this));
vm.expectRevert();
@ -351,8 +352,8 @@ contract TestUniswapV2Pair is Test {
}
function testSwapSwapToSelf() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
pair.mint(address(this));
vm.expectRevert();
@ -363,8 +364,8 @@ contract TestUniswapV2Pair is Test {
}
function testSwapInvalidConstantProductFormula() public {
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
pair.mint(address(this));
vm.expectRevert();
@ -376,8 +377,8 @@ contract TestUniswapV2Pair is Test {
function testCumulativePrices() public {
vm.warp(0);
token0.transfer(address(pair), 1 ether);
token1.transfer(address(pair), 1 ether);
assertTrue(token0.transfer(address(pair), 1 ether));
assertTrue(token1.transfer(address(pair), 1 ether));
pair.mint(address(this));
pair.sync();

View File

@ -3,15 +3,15 @@ pragma solidity =0.8.20;
import {Test} from "forge-std/Test.sol";
import "../src/mock/MockERC20.sol";
import "../src/interfaces/IERC20.sol";
import {MockERC20} from "../src/mock/MockERC20.sol";
import {IERC20} from "../src/interfaces/IERC20.sol";
import "../src/UniswapV2Factory.sol";
import "../src/UniswapV2Router.sol";
import "../src/UniswapV2Pair.sol";
import "../src/WETH9.sol";
import {UniswapV2Factory} from "../src/UniswapV2Factory.sol";
import {UniswapV2Router} from "../src/UniswapV2Router.sol";
import {UniswapV2Pair} from "../src/UniswapV2Pair.sol";
import {WETH9} from "../src/WETH9.sol";
import "../src/libraries/UniswapV2Library.sol";
import {UniswapV2Library} from "../src/libraries/UniswapV2Library.sol";
contract TestUniswapV2Router is Test {
UniswapV2Factory public factory;

View File

@ -2,7 +2,7 @@
pragma solidity =0.8.20;
import {Test} from "forge-std/Test.sol";
import "@openzeppelin-contracts/token/ERC20/ERC20.sol";
import {ERC20} from "@openzeppelin-contracts/token/ERC20/ERC20.sol";
abstract contract ERC20AllowanceTest is Test {
ERC20 tokenAllowance;
@ -61,7 +61,7 @@ abstract contract ERC20AllowanceTest is Test {
assertEq(tokenAllowance.allowance(aliceAllowance, bobAllowance), maxAmountAllowance);
vm.expectRevert();
vm.prank(bobAllowance);
tokenAllowance.transferFrom(aliceAllowance, bobAllowance, maxAmountAllowance);
assertFalse(tokenAllowance.transferFrom(aliceAllowance, bobAllowance, maxAmountAllowance));
}
function test_allowance_couldNotTransferFromIfNotEnoughAllowance() public {
@ -73,7 +73,7 @@ abstract contract ERC20AllowanceTest is Test {
assertEq(tokenAllowance.allowance(aliceAllowance, bobAllowance), amountAllowance);
vm.expectRevert();
vm.prank(bobAllowance);
tokenAllowance.transferFrom(aliceAllowance, bobAllowance, maxAmountAllowance);
assertFalse(tokenAllowance.transferFrom(aliceAllowance, bobAllowance, maxAmountAllowance));
}
function _mintAllowanceTokens(address who, uint256 value) internal virtual;

View File

@ -2,8 +2,8 @@
pragma solidity =0.8.20;
import {Test} from "forge-std/Test.sol";
import "../../src/mock/SigUtils.sol";
import "@openzeppelin-contracts/token/ERC20/extensions/ERC20Permit.sol";
import {SigUtils} from "../../src/mock/SigUtils.sol";
import {ERC20Permit} from "@openzeppelin-contracts/token/ERC20/extensions/ERC20Permit.sol";
abstract contract ERC20PermitTest is Test {
SigUtils sigUtils;
@ -14,8 +14,8 @@ abstract contract ERC20PermitTest is Test {
uint256 permitAmount;
uint256 maxPermitAmount;
uint256 constant ownerPrivateKey = 0xA11CE;
uint256 constant spenderPrivateKey = 0xB0B;
uint256 constant OWNER_PRIVATE_KEY = 0xA11CE;
uint256 constant SPENDER_PRIVATE_KEY = 0xB0B;
function initializePermit(
address token,
@ -27,8 +27,8 @@ abstract contract ERC20PermitTest is Test {
permitToken = ERC20Permit(token);
sigUtils = new SigUtils(permitToken.DOMAIN_SEPARATOR());
owner = vm.addr(ownerPrivateKey);
spender = vm.addr(spenderPrivateKey);
owner = vm.addr(OWNER_PRIVATE_KEY);
spender = vm.addr(SPENDER_PRIVATE_KEY);
}
function test_permit_initialNonceIsZero() public view {
@ -48,7 +48,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(OWNER_PRIVATE_KEY, digest);
permitToken.permit(
permit.owner,
@ -76,7 +76,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(OWNER_PRIVATE_KEY, digest);
vm.warp(1 days + 1 seconds); // fast forward one second past the deadline
@ -104,7 +104,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(spenderPrivateKey, digest); // spender signs owner's approval
(uint8 v, bytes32 r, bytes32 s) = vm.sign(SPENDER_PRIVATE_KEY, digest); // spender signs owner's approval
vm.expectRevert();
permitToken.permit(
@ -130,7 +130,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(OWNER_PRIVATE_KEY, digest);
vm.expectRevert();
permitToken.permit(
@ -156,7 +156,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(OWNER_PRIVATE_KEY, digest);
permitToken.permit(
permit.owner,
@ -192,7 +192,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(OWNER_PRIVATE_KEY, digest);
permitToken.permit(
permit.owner,
@ -205,7 +205,7 @@ abstract contract ERC20PermitTest is Test {
);
vm.prank(spender);
permitToken.transferFrom(owner, spender, permitAmount);
assertTrue(permitToken.transferFrom(owner, spender, permitAmount));
assertEq(permitToken.balanceOf(owner), 0);
assertEq(permitToken.balanceOf(spender), permitAmount);
@ -224,7 +224,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(OWNER_PRIVATE_KEY, digest);
permitToken.permit(
permit.owner,
@ -237,7 +237,7 @@ abstract contract ERC20PermitTest is Test {
);
vm.prank(spender);
permitToken.transferFrom(owner, spender, permitAmount);
assertTrue(permitToken.transferFrom(owner, spender, permitAmount));
assertEq(permitToken.balanceOf(owner), 0);
assertEq(permitToken.balanceOf(spender), permitAmount);
@ -256,7 +256,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(OWNER_PRIVATE_KEY, digest);
permitToken.permit(
permit.owner,
@ -270,7 +270,7 @@ abstract contract ERC20PermitTest is Test {
vm.expectRevert();
vm.prank(spender);
permitToken.transferFrom(owner, spender, permitAmount);
assertFalse(permitToken.transferFrom(owner, spender, permitAmount));
}
function test_permit_ivnalidBalance() public {
@ -285,7 +285,7 @@ abstract contract ERC20PermitTest is Test {
bytes32 digest = sigUtils.getTypedDataHash(permit);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(OWNER_PRIVATE_KEY, digest);
permitToken.permit(
permit.owner,
@ -299,7 +299,7 @@ abstract contract ERC20PermitTest is Test {
vm.expectRevert();
vm.prank(spender);
permitToken.transferFrom(owner, spender, permitAmount);
assertFalse(permitToken.transferFrom(owner, spender, permitAmount));
}
function _mintPermitTokens(address who, uint256 permitAmount) internal virtual;

View File

@ -2,7 +2,7 @@
pragma solidity =0.8.20;
import {Test} from "forge-std/Test.sol";
import "@openzeppelin-contracts/token/ERC20/ERC20.sol";
import {ERC20} from "@openzeppelin-contracts/token/ERC20/ERC20.sol";
abstract contract ERC20TransferTest is Test {
ERC20 tokenTransfer;
@ -31,8 +31,7 @@ abstract contract ERC20TransferTest is Test {
assertEq(tokenTransfer.balanceOf(aliceTransfer), amountTransfer);
assertEq(tokenTransfer.balanceOf(bobTransfer), 0);
vm.prank(aliceTransfer);
bool success = tokenTransfer.transfer(bobTransfer, amountTransfer);
assertEq(success, true);
assertTrue(tokenTransfer.transfer(bobTransfer, amountTransfer));
assertEq(tokenTransfer.balanceOf(bobTransfer), amountTransfer);
assertEq(tokenTransfer.balanceOf(aliceTransfer), 0);
}
@ -44,8 +43,7 @@ abstract contract ERC20TransferTest is Test {
assertEq(tokenTransfer.balanceOf(aliceTransfer), fuzzingTransferAmount);
assertEq(tokenTransfer.balanceOf(bobTransfer), 0);
vm.prank(aliceTransfer);
bool success = tokenTransfer.transfer(bobTransfer, fuzzingTransferAmount);
assertEq(success, true);
assertTrue(tokenTransfer.transfer(bobTransfer, fuzzingTransferAmount));
assertEq(tokenTransfer.balanceOf(bobTransfer), fuzzingTransferAmount);
assertEq(tokenTransfer.balanceOf(aliceTransfer), 0);
}
@ -54,7 +52,7 @@ abstract contract ERC20TransferTest is Test {
_mintTransferTokens(aliceTransfer, amountTransfer);
vm.expectRevert();
vm.prank(aliceTransfer);
tokenTransfer.transfer(bobTransfer, type(uint256).max);
assertFalse(tokenTransfer.transfer(bobTransfer, type(uint256).max));
}
function test_transfer_doesNotChangeTotalSupply() public {
@ -63,12 +61,12 @@ abstract contract ERC20TransferTest is Test {
if (totalSupplyTransfer == 0) {
assertEq(tokenTransfer.totalSupply(), amountTransfer);
vm.prank(aliceTransfer);
tokenTransfer.transfer(bobTransfer, amountTransfer);
assertTrue(tokenTransfer.transfer(bobTransfer, amountTransfer));
assertEq(tokenTransfer.totalSupply(), amountTransfer);
} else {
assertEq(tokenTransfer.totalSupply(), totalSupplyTransfer);
vm.prank(aliceTransfer);
tokenTransfer.transfer(bobTransfer, amountTransfer);
assertTrue(tokenTransfer.transfer(bobTransfer, amountTransfer));
assertEq(tokenTransfer.totalSupply(), totalSupplyTransfer);
}