fix annoying forge warnings
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
5f4365a3a8
commit
b131a064db
@ -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;
|
||||
}
|
||||
|
||||
@ -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 {}
|
||||
|
||||
@ -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 {}
|
||||
|
||||
@ -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 {}
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user