From f7fb1794377b2b6b543d71b74faa2b62cd880550 Mon Sep 17 00:00:00 2001 From: "A.L." Date: Tue, 11 Jun 2024 14:02:45 +0200 Subject: [PATCH] wip: math --- foundry.toml | 6 +- .../large/ReservoirPriceOracleLarge.t.sol | 80 +++++++++++------- test/unit/ReservoirPriceOracle.t.sol | 83 ------------------- 3 files changed, 54 insertions(+), 115 deletions(-) rename test/{unit => }/large/ReservoirPriceOracleLarge.t.sol (50%) diff --git a/foundry.toml b/foundry.toml index ac4907c..2df2a55 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,6 +1,5 @@ [profile.default] solc = "0.8.26" -#via_ir = true bytecode_hash = "ipfs" optimizer_runs = 1_000_000 libs = ['lib'] @@ -14,10 +13,13 @@ fs_permissions = [ { access = "read", path = "./out" } ] ignored_error_codes = [] +skip = ["test/large/*.sol"] [profile.large-test] via_ir = true -match_path = "test/unit/large/*.sol" +match_path = "test/large/*.sol" +match_test = "testGetQuote_RandomizeAllParam_3HopRoute" +skip = [] [profile.integration] match_path = "test/integration/*.sol" diff --git a/test/unit/large/ReservoirPriceOracleLarge.t.sol b/test/large/ReservoirPriceOracleLarge.t.sol similarity index 50% rename from test/unit/large/ReservoirPriceOracleLarge.t.sol rename to test/large/ReservoirPriceOracleLarge.t.sol index 661c6b5..972d740 100644 --- a/test/unit/large/ReservoirPriceOracleLarge.t.sol +++ b/test/large/ReservoirPriceOracleLarge.t.sol @@ -1,7 +1,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; -import { ReservoirPriceOracleTest, EnumerableSetLib, MintableERC20, ReservoirPair, IERC20 } from "test/unit/ReservoirPriceOracle.t.sol"; +import { + ReservoirPriceOracleTest, + EnumerableSetLib, + MintableERC20, + ReservoirPair, + IERC20 +} from "test/unit/ReservoirPriceOracle.t.sol"; contract ReservoirPriceOracleLargeTest is ReservoirPriceOracleTest { using EnumerableSetLib for EnumerableSetLib.AddressSet; @@ -29,7 +35,7 @@ contract ReservoirPriceOracleLargeTest is ReservoirPriceOracleTest { _addressSet.add(aTokenAAddress) && _addressSet.add(aTokenBAddress) && _addressSet.add(aTokenCAddress) && _addressSet.add(aTokenDAddress) ); - uint256 lPrice1 = bound(aPrice1, 1e12, 1e24); // need to bound price within this range as a price below this will go to zero as during the mul and div of prices + uint256 lPrice1 = bound(aPrice1, 1e12, 1e24); uint256 lPrice2 = bound(aPrice2, 1e12, 1e24); uint256 lPrice3 = bound(aPrice3, 1e12, 1e24); uint256 lAmtIn = bound(aAmtIn, 0, 1_000_000_000); @@ -43,49 +49,63 @@ contract ReservoirPriceOracleLargeTest is ReservoirPriceOracleTest { MintableERC20 lTokenB = MintableERC20(aTokenBAddress); MintableERC20 lTokenC = MintableERC20(aTokenCAddress); MintableERC20 lTokenD = MintableERC20(aTokenDAddress); - deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenADecimal)), address(lTokenA)); - deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenBDecimal)), address(lTokenB)); - deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenCDecimal)), address(lTokenC)); - deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenDDecimal)), address(lTokenD)); + deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenADecimal)), aTokenAAddress); + deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenBDecimal)), aTokenBAddress); + deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenCDecimal)), aTokenCAddress); + deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenDDecimal)), aTokenDAddress); - ReservoirPair lPair1 = ReservoirPair(_factory.createPair(IERC20(address(lTokenA)), IERC20(address(lTokenB)), 0)); - ReservoirPair lPair2 = ReservoirPair(_factory.createPair(IERC20(address(lTokenB)), IERC20(address(lTokenC)), 0)); - ReservoirPair lPair3 = ReservoirPair(_factory.createPair(IERC20(address(lTokenC)), IERC20(address(lTokenD)), 0)); + ReservoirPair lPair1 = ReservoirPair(_factory.createPair(IERC20(aTokenAAddress), IERC20(aTokenBAddress), 0)); + ReservoirPair lPair2 = ReservoirPair(_factory.createPair(IERC20(aTokenBAddress), IERC20(aTokenCAddress), 0)); + ReservoirPair lPair3 = ReservoirPair(_factory.createPair(IERC20(aTokenCAddress), IERC20(aTokenDAddress), 0)); - _oracle.designatePair(address(lTokenA), address(lTokenB), lPair1); - _oracle.designatePair(address(lTokenB), address(lTokenC), lPair2); - _oracle.designatePair(address(lTokenC), address(lTokenD), lPair3); + _oracle.designatePair(aTokenAAddress, aTokenBAddress, lPair1); + _oracle.designatePair(aTokenBAddress, aTokenCAddress, lPair2); + _oracle.designatePair(aTokenCAddress, aTokenDAddress, lPair3); address[] memory lRoute = new address[](4); - (lRoute[0], lRoute[3]) = - lTokenA < lTokenD ? (address(lTokenA), address(lTokenD)) : (address(lTokenD), address(lTokenA)); - lRoute[1] = address(lTokenB); - lRoute[2] = address(lTokenC); + if (lTokenA < lTokenD) { + lRoute[0] = aTokenAAddress; + lRoute[1] = aTokenBAddress; + lRoute[2] = aTokenCAddress; + lRoute[3] = aTokenDAddress; + } else { + lRoute[0] = aTokenDAddress; + lRoute[1] = aTokenCAddress; + lRoute[2] = aTokenBAddress; + lRoute[3] = aTokenAAddress; + } - _oracle.setRoute(lRoute[0], lRoute[3], lRoute); + _oracle.setRoute(aTokenAAddress, aTokenDAddress, lRoute); _writePriceCache( - lRoute[0] < lRoute[1] ? lRoute[0] : lRoute[1], lRoute[0] < lRoute[1] ? lRoute[1] : lRoute[0], lPrice1 + lTokenA < lTokenB ? aTokenAAddress : aTokenBAddress, + lTokenA < lTokenB ? aTokenBAddress : aTokenAAddress, + lPrice1 ); _writePriceCache( - address(lTokenB) < address(lTokenC) ? address(lTokenB) : address(lTokenC), - address(lTokenB) < address(lTokenC) ? address(lTokenC) : address(lTokenB), + lTokenB < lTokenC ? aTokenBAddress : aTokenCAddress, + lTokenB < lTokenC ? aTokenCAddress : aTokenBAddress, lPrice2 ); _writePriceCache( - lRoute[2] < lRoute[3] ? lRoute[2] : lRoute[3], lRoute[2] < lRoute[3] ? lRoute[3] : lRoute[2], lPrice3 + lTokenC < lTokenD ? aTokenCAddress : aTokenDAddress, + lTokenC < lTokenD ? aTokenDAddress : aTokenCAddress, + lPrice3 ); // act - uint256 lAmtDOut = _oracle.getQuote(lAmtIn * 10 ** lTokenADecimal, address(lTokenA), address(lTokenD)); + uint256 lAmtDOut = _oracle.getQuote(lAmtIn * 10 ** lTokenADecimal, aTokenAAddress, aTokenDAddress); // assert -// uint256 lPriceStartEnd = (lRoute[0] < lRoute[1] ? lPrice1 : lPrice1.invertWad()) -// * (lRoute[1] < lRoute[2] ? lPrice2 : lPrice2.invertWad()) / WAD -// * (lRoute[2] < lRoute[3] ? lPrice3 : lPrice3.invertWad()) / WAD; -// assertEq( -// lAmtDOut, -// lAmtIn * (lRoute[0] == address(lTokenA) ? lPriceStartEnd : lPriceStartEnd.invertWad()) -// * (10 ** lTokenDDecimal) / WAD -// ); + uint256 lExpectedAmtBOut = lTokenA < lTokenB + ? lAmtIn * 10 ** lTokenADecimal * lPrice1 * 10 ** lTokenBDecimal / 10 ** lTokenADecimal / WAD + : lAmtIn * 10 ** lTokenADecimal * WAD * 10 ** lTokenBDecimal / lPrice1 / 10 ** lTokenADecimal; + uint256 lExpectedAmtCOut = lTokenB < lTokenC + ? lExpectedAmtBOut * lPrice2 * 10 ** lTokenCDecimal / 10 ** lTokenBDecimal / WAD + : lExpectedAmtBOut * WAD * 10 ** lTokenCDecimal / lPrice2 / 10 ** lTokenBDecimal; + uint256 lExpectedAmtDOut = lTokenC < lTokenD + ? lExpectedAmtCOut * lPrice2 * 10 ** lTokenDDecimal / 10 ** lTokenCDecimal / WAD + : lExpectedAmtCOut * WAD * 10 ** lTokenDDecimal / lPrice2 / 10 ** lTokenCDecimal; + + assertEq(lAmtDOut, lExpectedAmtDOut); } } diff --git a/test/unit/ReservoirPriceOracle.t.sol b/test/unit/ReservoirPriceOracle.t.sol index c18c0fd..111bdb4 100644 --- a/test/unit/ReservoirPriceOracle.t.sol +++ b/test/unit/ReservoirPriceOracle.t.sol @@ -356,89 +356,6 @@ contract ReservoirPriceOracleTest is BaseTest { assertEq(lAmtCOut, lExpectedAmtCOut); } - // function testGetQuote_RandomizeAllParam_3HopRoute( - // uint256 aPrice1, - // uint256 aPrice2, - // uint256 aPrice3, - // uint256 aAmtIn, - // address aTokenAAddress, - // address aTokenBAddress, - // address aTokenCAddress, - // address aTokenDAddress, - // uint8 aTokenADecimal, - // uint8 aTokenBDecimal, - // uint8 aTokenCDecimal, - // uint8 aTokenDDecimal - // ) external { - // // assume - // vm.assume( - // aTokenAAddress > ADDRESS_THRESHOLD && aTokenBAddress > ADDRESS_THRESHOLD - // && aTokenCAddress > ADDRESS_THRESHOLD && aTokenDAddress > ADDRESS_THRESHOLD - // ); - // vm.assume( - // _addressSet.add(aTokenAAddress) && _addressSet.add(aTokenBAddress) && _addressSet.add(aTokenCAddress) - // && _addressSet.add(aTokenDAddress) - // ); - // uint256 lPrice1 = bound(aPrice1, 1e12, 1e24); // need to bound price within this range as a price below this will go to zero as during the mul and div of prices - // uint256 lPrice2 = bound(aPrice2, 1e12, 1e24); - // uint256 lPrice3 = bound(aPrice3, 1e12, 1e24); - // uint256 lAmtIn = bound(aAmtIn, 0, 1_000_000_000); - // uint256 lTokenADecimal = bound(aTokenADecimal, 0, 18); - // uint256 lTokenBDecimal = bound(aTokenBDecimal, 0, 18); - // uint256 lTokenCDecimal = bound(aTokenCDecimal, 0, 18); - // uint256 lTokenDDecimal = bound(aTokenDDecimal, 0, 18); - // - // // arrange - // MintableERC20 lTokenA = MintableERC20(aTokenAAddress); - // MintableERC20 lTokenB = MintableERC20(aTokenBAddress); - // MintableERC20 lTokenC = MintableERC20(aTokenCAddress); - // MintableERC20 lTokenD = MintableERC20(aTokenDAddress); - // deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenADecimal)), address(lTokenA)); - // deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenBDecimal)), address(lTokenB)); - // deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenCDecimal)), address(lTokenC)); - // deployCodeTo("MintableERC20.sol", abi.encode("T", "T", uint8(lTokenDDecimal)), address(lTokenD)); - // - // ReservoirPair lPair1 = ReservoirPair(_factory.createPair(IERC20(address(lTokenA)), IERC20(address(lTokenB)), 0)); - // ReservoirPair lPair2 = ReservoirPair(_factory.createPair(IERC20(address(lTokenB)), IERC20(address(lTokenC)), 0)); - // ReservoirPair lPair3 = ReservoirPair(_factory.createPair(IERC20(address(lTokenC)), IERC20(address(lTokenD)), 0)); - // - // _oracle.designatePair(address(lTokenA), address(lTokenB), lPair1); - // _oracle.designatePair(address(lTokenB), address(lTokenC), lPair2); - // _oracle.designatePair(address(lTokenC), address(lTokenD), lPair3); - // - // address[] memory lRoute = new address[](4); - // (lRoute[0], lRoute[3]) = - // lTokenA < lTokenD ? (address(lTokenA), address(lTokenD)) : (address(lTokenD), address(lTokenA)); - // lRoute[1] = address(lTokenB); - // lRoute[2] = address(lTokenC); - // - // _oracle.setRoute(lRoute[0], lRoute[3], lRoute); - // _writePriceCache( - // lRoute[0] < lRoute[1] ? lRoute[0] : lRoute[1], lRoute[0] < lRoute[1] ? lRoute[1] : lRoute[0], lPrice1 - // ); - // _writePriceCache( - // address(lTokenB) < address(lTokenC) ? address(lTokenB) : address(lTokenC), - // address(lTokenB) < address(lTokenC) ? address(lTokenC) : address(lTokenB), - // lPrice2 - // ); - // _writePriceCache( - // lRoute[2] < lRoute[3] ? lRoute[2] : lRoute[3], lRoute[2] < lRoute[3] ? lRoute[3] : lRoute[2], lPrice3 - // ); - // - // // act - // uint256 lAmtDOut = _oracle.getQuote(lAmtIn * 10 ** lTokenADecimal, address(lTokenA), address(lTokenD)); - // - // // assert - // uint256 lPriceStartEnd = (lRoute[0] < lRoute[1] ? lPrice1 : lPrice1.invertWad()) - // * (lRoute[1] < lRoute[2] ? lPrice2 : lPrice2.invertWad()) / WAD - // * (lRoute[2] < lRoute[3] ? lPrice3 : lPrice3.invertWad()) / WAD; - // assertEq( - // lAmtDOut, - // lAmtIn * (lRoute[0] == address(lTokenA) ? lPriceStartEnd : lPriceStartEnd.invertWad()) - // * (10 ** lTokenDDecimal) / WAD - // ); - // } - function testGetQuotes(uint256 aPrice, uint256 aAmountIn) external { // assume uint256 lPrice = bound(aPrice, 1, 1e36);