diff --git a/.gas-snapshot b/.gas-snapshot index 62c5d5b..956d878 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,56 +1,57 @@ -QuoterTest:testGetAmountOutConstantProduct(uint256,uint256,uint256,uint256) (runs: 256, μ: 16973, ~: 17007) -QuoterTest:testGetAmountOutStable(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 46155, ~: 46746) -QuoterTest:testGetAmountsIn(uint256) (runs: 256, μ: 4790024, ~: 4790318) -QuoterTest:testGetAmountsOut(uint256,uint256,uint256) (runs: 256, μ: 4786181, ~: 4784679) -QuoterTest:testQuoteAddLiquidity_ConstantProduct_Balanced(uint256,uint256) (runs: 256, μ: 119386, ~: 119421) -QuoterTest:testQuoteAddLiquidity_ConstantProduct_Unbalanced(uint256,uint256,uint256,uint256) (runs: 256, μ: 4751352, ~: 4751305) -QuoterTest:testQuoteAddLiquidity_PairDoesNotExistYet(uint256,uint256,uint256) (runs: 256, μ: 40499, ~: 45595) -QuoterTest:testQuoteAddLiquidity_Stable_Balanced(uint256,uint256) (runs: 256, μ: 136744, ~: 136785) -QuoterTest:testQuoteAddLiquidity_Stable_Unbalanced(uint256,uint256,uint256,uint256) (runs: 256, μ: 9704840, ~: 9705547) -QuoterTest:testQuoteRemoveLiquidity(uint256) (runs: 256, μ: 149170, ~: 149145) -ReservoirLibraryTest:testGetAmountInConstantProduct(uint256) (runs: 256, μ: 82307, ~: 82225) -ReservoirLibraryTest:testGetAmountInStable(uint256) (runs: 256, μ: 104143, ~: 104440) -ReservoirLibraryTest:testGetAmountIn_InsufficientLiquidity(uint256) (runs: 256, μ: 7651, ~: 7409) +QuoterTest:testGetAmountOutConstantProduct(uint256,uint256,uint256,uint256) (runs: 256, μ: 17056, ~: 17131) +QuoterTest:testGetAmountOutStable(uint256,uint256,uint256,uint256,uint256) (runs: 256, μ: 45934, ~: 46746) +QuoterTest:testGetAmountsIn(uint256) (runs: 256, μ: 4727472, ~: 4727774) +QuoterTest:testGetAmountsOut(uint256,uint256,uint256) (runs: 256, μ: 4723651, ~: 4722138) +QuoterTest:testQuoteAddLiquidity_ConstantProduct_Balanced(uint256,uint256) (runs: 256, μ: 123667, ~: 123693) +QuoterTest:testQuoteAddLiquidity_ConstantProduct_Unbalanced(uint256,uint256,uint256,uint256) (runs: 256, μ: 4688921, ~: 4688926) +QuoterTest:testQuoteAddLiquidity_PairDoesNotExistYet(uint256,uint256,uint256) (runs: 256, μ: 40039, ~: 33807) +QuoterTest:testQuoteAddLiquidity_Stable_Balanced(uint256,uint256) (runs: 256, μ: 143380, ~: 143486) +QuoterTest:testQuoteAddLiquidity_Stable_Unbalanced(uint256,uint256,uint256,uint256) (runs: 256, μ: 5089005, ~: 5089835) +QuoterTest:testQuoteRemoveLiquidity(uint256) (runs: 256, μ: 153798, ~: 153763) +ReservoirLibraryTest:testGetAmountInConstantProduct(uint256) (runs: 256, μ: 86851, ~: 87043) +ReservoirLibraryTest:testGetAmountInStable(uint256) (runs: 256, μ: 111001, ~: 111314) +ReservoirLibraryTest:testGetAmountIn_InsufficientLiquidity(uint256) (runs: 256, μ: 7664, ~: 7409) ReservoirLibraryTest:testGetAmountIn_InsufficientOutputAmount() (gas: 3313) -ReservoirLibraryTest:testGetAmountOutConstantProduct(uint256) (runs: 256, μ: 80071, ~: 81699) -ReservoirLibraryTest:testGetAmountOutStable(uint256) (runs: 256, μ: 100030, ~: 104280) +ReservoirLibraryTest:testGetAmountOutConstantProduct(uint256) (runs: 256, μ: 84614, ~: 86229) +ReservoirLibraryTest:testGetAmountOutStable(uint256) (runs: 256, μ: 106751, ~: 105562) ReservoirLibraryTest:testGetAmountOut_InsufficientInputAmount() (gas: 3471) -ReservoirLibraryTest:testGetAmountOut_InsufficientLiquidity(uint256) (runs: 256, μ: 7691, ~: 7449) -ReservoirLibraryTest:testGetAmountsIn_CP() (gas: 4732027) -ReservoirLibraryTest:testGetAmountsIn_MixedCurves() (gas: 4773478) -ReservoirLibraryTest:testGetAmountsIn_SP(uint256) (runs: 256, μ: 9688771, ~: 9689096) -ReservoirLibraryTest:testGetAmountsOut_CP() (gas: 4731578) -ReservoirLibraryTest:testGetAmountsOut_MixedCurves() (gas: 4747780) -ReservoirLibraryTest:testGetAmountsOut_SP() (gas: 9687224) +ReservoirLibraryTest:testGetAmountOut_InsufficientLiquidity(uint256) (runs: 256, μ: 7704, ~: 7449) +ReservoirLibraryTest:testGetAmountsIn_CP() (gas: 4669483) +ReservoirLibraryTest:testGetAmountsIn_MixedCurves() (gas: 4710934) +ReservoirLibraryTest:testGetAmountsIn_SP(uint256) (runs: 256, μ: 5072618, ~: 5072943) +ReservoirLibraryTest:testGetAmountsOut_CP() (gas: 4669034) +ReservoirLibraryTest:testGetAmountsOut_MixedCurves() (gas: 4685236) +ReservoirLibraryTest:testGetAmountsOut_SP() (gas: 5071071) ReservoirLibraryTest:testGetPrecisionMultiplier() (gas: 760899) ReservoirLibraryTest:testGetPrecisionMultiplier_MoreThan18Decimals() (gas: 14181) ReservoirLibraryTest:testGetSwapFee() (gas: 17704) ReservoirLibraryTest:testGetSwapFee_PairDoesNotExist() (gas: 23540) ReservoirLibraryTest:testQuote_AmountZero() (gas: 3359) -ReservoirLibraryTest:testQuote_Balanced(uint256,uint256) (runs: 256, μ: 6382, ~: 6462) +ReservoirLibraryTest:testQuote_Balanced(uint256,uint256) (runs: 256, μ: 6417, ~: 6462) ReservoirLibraryTest:testQuote_ReserveZero() (gas: 3398) -ReservoirLibraryTest:testQuote_Unbalanced(uint256,uint256,uint256) (runs: 256, μ: 8098, ~: 8114) -ReservoirRouterTest:testAddLiquidity_CP(uint256,uint256) (runs: 256, μ: 451430, ~: 442630) -ReservoirRouterTest:testAddLiquidity_CreatePair_CP() (gas: 4796225) -ReservoirRouterTest:testAddLiquidity_CreatePair_CP_Native() (gas: 5066571) +ReservoirLibraryTest:testQuote_Unbalanced(uint256,uint256,uint256) (runs: 256, μ: 8188, ~: 8114) +ReservoirRouterTest:testAddLiquidity_CP(uint256,uint256) (runs: 256, μ: 456794, ~: 466170) +ReservoirRouterTest:testAddLiquidity_CreatePair_CP() (gas: 4733681) +ReservoirRouterTest:testAddLiquidity_CreatePair_CP_Native() (gas: 5004027) ReservoirRouterTest:testAddLiquidity_OptimalLessThanMin() (gas: 44571) -ReservoirRouterTest:testAddLiquidity_SP_Balanced(uint256,uint256) (runs: 256, μ: 473597, ~: 473566) -ReservoirRouterTest:testAddLiquidity_SP_Unbalanced(uint256,uint256,uint256,uint256) (runs: 256, μ: 10054191, ~: 10054407) -ReservoirRouterTest:testCheckDeadline(uint256) (runs: 256, μ: 108165, ~: 108032) -ReservoirRouterTest:testCheckDeadline_PastDeadline(uint256) (runs: 256, μ: 108161, ~: 107670) -ReservoirRouterTest:testRemoveLiquidity(uint256) (runs: 256, μ: 369770, ~: 360934) -ReservoirRouterTest:testRemoveLiquidity_Native() (gas: 5313670) -ReservoirRouterTest:testRemoveLiquidity_ReceivedLessThanMin() (gas: 266436) -ReservoirRouterTest:testSwapExactForVariable(uint256,uint256,uint256) (runs: 256, μ: 4840193, ~: 4844032) -ReservoirRouterTest:testSwapExactForVariable_MixedCurves(uint256) (runs: 256, μ: 5265247, ~: 5267999) -ReservoirRouterTest:testSwapExactForVariable_NativeIn() (gas: 5256145) -ReservoirRouterTest:testSwapExactForVariable_NativeOut() (gas: 5349060) -ReservoirRouterTest:testSwapExactForVariable_Slippage() (gas: 4881716) -ReservoirRouterTest:testSwapVariableForExact(uint256) (runs: 256, μ: 9846638, ~: 9848265) -ReservoirRouterTest:testSwapVariableForExact_MixedCurves() (gas: 5331087) -ReservoirRouterTest:testSwapVariableForExact_NativeIn() (gas: 5273674) -ReservoirRouterTest:testSwapVariableForExact_NativeIn_RefundETH() (gas: 5280059) -ReservoirRouterTest:testSwapVariableForExact_NativeOut() (gas: 5337868) +ReservoirRouterTest:testAddLiquidity_SP_Balanced(uint256,uint256) (runs: 256, μ: 480182, ~: 480612) +ReservoirRouterTest:testAddLiquidity_SP_Unbalanced(uint256,uint256,uint256,uint256) (runs: 256, μ: 5438520, ~: 5438797) +ReservoirRouterTest:testCheckDeadline(uint256) (runs: 256, μ: 107954, ~: 108032) +ReservoirRouterTest:testCheckDeadline_PastDeadline(uint256) (runs: 256, μ: 108152, ~: 108232) +ReservoirRouterTest:testRemoveLiquidity(uint256) (runs: 256, μ: 375090, ~: 365530) +ReservoirRouterTest:testRemoveLiquidity_Native() (gas: 5251744) +ReservoirRouterTest:testRemoveLiquidity_PairDoesNotExist() (gas: 17493) +ReservoirRouterTest:testRemoveLiquidity_ReceivedLessThanMin() (gas: 277254) +ReservoirRouterTest:testSwapExactForVariable(uint256,uint256,uint256) (runs: 256, μ: 4782426, ~: 4786538) +ReservoirRouterTest:testSwapExactForVariable_MixedCurves(uint256) (runs: 256, μ: 5209794, ~: 5212641) +ReservoirRouterTest:testSwapExactForVariable_NativeIn() (gas: 5198649) +ReservoirRouterTest:testSwapExactForVariable_NativeOut() (gas: 5291564) +ReservoirRouterTest:testSwapExactForVariable_Slippage() (gas: 4824750) +ReservoirRouterTest:testSwapVariableForExact(uint256) (runs: 256, μ: 5237566, ~: 5235917) +ReservoirRouterTest:testSwapVariableForExact_MixedCurves() (gas: 5275735) +ReservoirRouterTest:testSwapVariableForExact_NativeIn() (gas: 5216202) +ReservoirRouterTest:testSwapVariableForExact_NativeIn_RefundETH() (gas: 5222587) +ReservoirRouterTest:testSwapVariableForExact_NativeOut() (gas: 5280374) SelfPermitTest:testPermit(uint256) (runs: 256, μ: 92124, ~: 91453) SelfPermitTest:testSelfPermit(uint256) (runs: 256, μ: 77961, ~: 77946) SelfPermitTest:testSelfPermitAllowed() (gas: 75028) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b43ca6e..0e58b34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,25 +61,25 @@ jobs: env: FOUNDRY_PROFILE: default - coverage: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - run: forge coverage --report lcov - env: - FOUNDRY_PROFILE: coverage - - run: sudo apt install -y lcov - - run: lcov -r lcov.info "src/libraries/*" -o lcov.info - - run: lcov -r lcov.info "test/*" -o lcov.info - - run: | - ! lcov --summary lcov.info | grep -q 0.0% - - uses: codecov/codecov-action@v3 - with: - fail_ci_if_error: true - files: ./lcov.info +# coverage: +# runs-on: ubuntu-latest +# +# steps: +# - uses: actions/checkout@v3 +# with: +# submodules: recursive +# - uses: foundry-rs/foundry-toolchain@v1 +# with: +# version: nightly +# - run: forge coverage --report lcov +# env: +# FOUNDRY_PROFILE: coverage +# - run: sudo apt install -y lcov +# - run: lcov -r lcov.info "src/libraries/*" -o lcov.info +# - run: lcov -r lcov.info "test/*" -o lcov.info +# - run: | +# ! lcov --summary lcov.info | grep -q 0.0% +# - uses: codecov/codecov-action@v3 +# with: +# fail_ci_if_error: true +# files: ./lcov.info diff --git a/.gitignore b/.gitignore index 85251ca..bb8d701 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /cache /out /node_modules +/broadcast # slither /slither-report.md diff --git a/README.md b/README.md index 160882c..43d2a98 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,15 @@ To run unit tests: forge test ``` +## Deploying + +To deploy this onto a testnet / mainnet, run: + +```bash +forge script scripts/setup_scaffold.s.sol --target-contract SetupScaffold +--sig "run()" --rpc-url "http://127.0.0.1:8545" -vv +``` + ## Contributing Are you interested in helping us build the future of Vexchange with our V3? diff --git a/foundry.toml b/foundry.toml index 27155f0..1a0eefc 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,14 +1,16 @@ [profile.default] solc = "0.8.17" -#via-ir = true bytecode_hash = "none" optimizer_runs = 1_000_000 remappings = ["@openzeppelin/=lib/openzeppelin-contracts/contracts/", "v3-core/=lib/v3-core"] match_path = "test/unit/*.sol" verbosity = 3 + fs_permissions = [ { access = "write", path = "./scripts/optimized-stable-mint-burn-key" }, { access = "write", path = "./scripts/unoptimized-stable-mint-burn-key" }, + { access = "read", path = "./out" }, + { access = "read", path = "./lib" }, ] [profile.ci.fuzz] diff --git a/lib/v3-core b/lib/v3-core index de1cc47..b899003 160000 --- a/lib/v3-core +++ b/lib/v3-core @@ -1 +1 @@ -Subproject commit de1cc47575afed8b707bb9e0fdc9cc3b40462417 +Subproject commit b899003e8f3ce1ba0f592df4bfa9a9890441419f diff --git a/scripts/deploy_stablepair.s.sol b/scripts/deploy_stablepair.s.sol new file mode 100644 index 0000000..6752844 --- /dev/null +++ b/scripts/deploy_stablepair.s.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import "v3-core/scripts/BaseScript.sol"; + +import { FactoryStoreLib } from "v3-core/src/libraries/FactoryStore.sol"; +import { ConstantsLib } from "v3-core/src/libraries/Constants.sol"; +import { StablePair } from "v3-core/src/curve/stable/StablePair.sol"; +import { StableMintBurn } from "v3-core/src/curve/stable/StableMintBurn.sol"; +import { MintableERC20 } from "v3-core/test/__fixtures/MintableERC20.sol"; + +uint256 constant DEFAULT_SWAP_FEE_SP = 100; // 0.01% +uint256 constant DEFAULT_AMP_COEFF = 1000; + +contract DeployStablePair is BaseScript { + using FactoryStoreLib for GenericFactory; + + // default private key from anvil + uint256 private _defaultPrivateKey = vm.envUint("PRIVATE_KEY"); + address private _walletAddress; + + address private _deployedUSDC = 0x5D60473C5Cb323032d6fdFf42380B50E2AE4d245; + address private _deployedUSDT = 0x6e9FDaE1Fe20b0A5a605C879Ae14030a0aE99cF9; + address private _router = 0x7F05c63dC7CA3F99f2d3409f0017C28058C42B27; + + StablePair internal _sp1; + + function _createStablePair() private { + vm.startBroadcast(_defaultPrivateKey); + // add stable curve + _factory.addCurve(type(StablePair).creationCode); + _factory.write("SP::swapFee", DEFAULT_SWAP_FEE_SP); + _factory.write("SP::amplificationCoefficient", DEFAULT_AMP_COEFF); + + _factory.addBytecode(type(StableMintBurn).creationCode); + address lStableMintBurn = _factory.deploySharedContract(ConstantsLib.MINT_BURN_KEY, _deployedUSDC, _deployedUSDT); + _factory.write("SP::STABLE_MINT_BURN", lStableMintBurn); + + _sp1 = StablePair(_factory.createPair(_deployedUSDC, _deployedUSDT, 1)); + MintableERC20(_deployedUSDC).mint(address(_sp1), 948_192_492_581); + MintableERC20(_deployedUSDT).mint(address(_sp1), 1_140_591_501_001); + _sp1.mint(_walletAddress); + require(_sp1.balanceOf(_walletAddress) > 0, "INSUFFICIENT LIQ"); + + _sp1.approve(_router, type(uint256).max); + + // _factory.createPair(WAVAX_AVAX_MAINNET, USDC_AVAX_MAINNET, 1); + vm.stopBroadcast(); + } + + function run() external { + _walletAddress = vm.rememberKey(_defaultPrivateKey); + _setup(_defaultPrivateKey); + _createStablePair(); + } +} diff --git a/scripts/optimized-stable-mint-burn-key b/scripts/optimized-stable-mint-burn-key index d65a545..0fdb748 100644 --- a/scripts/optimized-stable-mint-burn-key +++ b/scripts/optimized-stable-mint-burn-key @@ -1 +1 @@ -0xfca7c68f711102d77ab0a2765cee66cea90b7f07334352820e7ebf31c0ef3acf \ No newline at end of file +0xf629f8de34ecb99dffcf69ea812ed1fdbba96bee14757da972c41f5b986fc74d \ No newline at end of file diff --git a/scripts/setup_scaffold.s.sol b/scripts/setup_scaffold.s.sol new file mode 100644 index 0000000..a9bc9fe --- /dev/null +++ b/scripts/setup_scaffold.s.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { WETH } from "solmate/tokens/WETH.sol"; + +import "v3-core/scripts/BaseScript.sol"; +import { ConstantProductPair } from "v3-core/src/curve/constant-product/ConstantProductPair.sol"; +import { FactoryStoreLib } from "v3-core/src/libraries/FactoryStore.sol"; +import { MintableERC20 } from "v3-core/test/__fixtures/MintableERC20.sol"; + +import { ReservoirRouter } from "src/ReservoirRouter.sol"; +import { Quoter } from "src/Quoter.sol"; + +uint256 constant INITIAL_MINT_AMOUNT = 100e18; +uint256 constant DEFAULT_SWAP_FEE_CP = 3000; // 0.3% +uint256 constant DEFAULT_PLATFORM_FEE = 250_000; // 25% +uint256 constant DEFAULT_MAX_CHANGE_RATE = 0.0005e18; + +contract SetupScaffold is BaseScript { + using FactoryStoreLib for GenericFactory; + + address payable private constant AVAX_MAINNET_WAVAX = payable(0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7); + + ReservoirRouter private _router; + Quoter private _quoter; + + MintableERC20 internal _usdc; + MintableERC20 internal _usdt; + WETH internal _wavax = WETH(AVAX_MAINNET_WAVAX); + ConstantProductPair internal _cp1; + ConstantProductPair internal _cp2; + + // default private key from anvil + uint256 private _defaultPrivateKey = vm.envUint("PRIVATE_KEY"); + address private _walletAddress; + + function _deployInfra() private { + vm.startBroadcast(_defaultPrivateKey); + _usdc = new MintableERC20("USD Circle", "USDC", 6); + _usdt = new MintableERC20("USD Tether", "USDT", 6); + // _wavax = new WETH(); + vm.stopBroadcast(); + } + + function _deployCore() private { + _setup(_defaultPrivateKey); + + vm.startBroadcast(_defaultPrivateKey); + // set shared variables + _factory.write("Shared::platformFee", DEFAULT_PLATFORM_FEE); + // _factory.write("Shared::platformFeeTo", _platformFeeTo); + // _factory.write("Shared::defaultRecoverer", _recoverer); + _factory.write("Shared::maxChangeRate", DEFAULT_MAX_CHANGE_RATE); + + // add constant product curve + _factory.addCurve(type(ConstantProductPair).creationCode); + _factory.write("CP::swapFee", DEFAULT_SWAP_FEE_CP); + + vm.stopBroadcast(); + } + + function _deployPeriphery() private { + + _router = ReservoirRouter( + payable( + Create2Lib.computeAddress( + CREATE2_FACTORY, + abi.encodePacked(type(ReservoirRouter).creationCode, abi.encode(address(_factory), address(_wavax))), + bytes32(uint256(0)) + ) + ) + ); + if (address(_router).code.length == 0) { + vm.broadcast(_defaultPrivateKey); + ReservoirRouter lRouter = new ReservoirRouter{salt: bytes32(uint256(0))}(address(_factory), address(_wavax)); + + require(lRouter == _router, "Create2 Address Mismatch for ReservoirRouter"); + } + + _quoter = Quoter( + Create2Lib.computeAddress( + CREATE2_FACTORY, + abi.encodePacked(type(Quoter).creationCode, abi.encode(address(_factory), address(_wavax))), + bytes32(uint256(0)) + ) + ); + if (address(_quoter).code.length == 0) { + vm.broadcast(_defaultPrivateKey); + Quoter lQuoter = new Quoter{salt: bytes32(uint256(0))}(address(_factory), address(_wavax)); + + require(lQuoter == _quoter, "Create2 Address mismatch for Quoter"); + } + } + + function _getRich() private { + uint256 lAmtToWrap = 1 ether; + vm.startBroadcast(_defaultPrivateKey); + _usdc.mint(_walletAddress, 1_000_000e6); + _usdt.mint(_walletAddress, 1_000_000e6); + _wavax.deposit{value: lAmtToWrap}(); + require(_wavax.balanceOf(_walletAddress) == lAmtToWrap, "WAVAX AMT WRONG"); + vm.stopBroadcast(); + } + + function _deployPairs() private { + vm.startBroadcast(_defaultPrivateKey); + _cp1 = ConstantProductPair(_factory.createPair(address(_usdt), address(_usdc), 0)); + _usdc.mint(address(_cp1), 1_000_000e6); + _usdt.mint(address(_cp1), 950_000e6); + _cp1.mint(_walletAddress); + + _cp2 = ConstantProductPair(_factory.createPair(address(_wavax), address(_usdc), 0)); + _usdc.mint(address(_cp2), 103_392_049_192); + _wavax.transfer(address(_cp2), 302_291_291_321_201_392); + _cp2.mint(_walletAddress); + + require(_cp1.balanceOf(_walletAddress) > 0, "INSUFFICIENT LIQ"); + require(_cp2.balanceOf(_walletAddress) > 0, "INSUFFICIENT LIQ"); + vm.stopBroadcast(); + } + + function _approveRouter() private { + vm.startBroadcast(_defaultPrivateKey); + _usdc.approve(address(_router), type(uint256).max); + _usdt.approve(address(_router), type(uint256).max); + _wavax.approve(address(_router), type(uint256).max); + _cp1.approve(address(_router), type(uint256).max); + _cp2.approve(address(_router), type(uint256).max); + vm.stopBroadcast(); + } + + function run() external { + _walletAddress = vm.rememberKey(_defaultPrivateKey); + _deployInfra(); + _deployCore(); + _deployPeriphery(); + _getRich(); + _deployPairs(); + _approveRouter(); + } +} diff --git a/test/unit/ReservoirRouter.t.sol b/test/unit/ReservoirRouter.t.sol index 2dedf10..be1baab 100644 --- a/test/unit/ReservoirRouter.t.sol +++ b/test/unit/ReservoirRouter.t.sol @@ -321,6 +321,12 @@ contract ReservoirRouterTest is BaseTest { ); } + function testRemoveLiquidity_PairDoesNotExist() external { + // act & assert + vm.expectRevert(); + _router.removeLiquidity(address(0), address(0), 1, 123, 0, 0, address(this)); + } + function testCheckDeadline(uint256 aDeadline) public { // assume uint256 lDeadline = bound(aDeadline, 1, type(uint64).max);