From c5984f7e9062ba5b690ce288e1b8cc0eb8faf625 Mon Sep 17 00:00:00 2001 From: kinrezc Date: Mon, 15 Jul 2024 13:34:14 -0400 Subject: [PATCH] wip lower contract size --- src/LiquidityManager.sol | 22 +++++- src/RMM.sol | 112 ++++--------------------------- src/lib/BisectionLib.sol | 73 -------------------- src/lib/LiquidityLib.sol | 28 +------- src/lib/RmmErrors.sol | 6 +- src/lib/RmmLib.sol | 98 +++++++++++++++++++++++++-- test/unit/ApproxSpotPrice.t.sol | 20 ------ test/unit/Init.t.sol | 10 +-- test/unit/LiquidityManager.t.sol | 2 +- test/unit/SwapExactPtForSy.t.sol | 6 +- test/unit/SwapExactSyForPt.t.sol | 6 +- 11 files changed, 141 insertions(+), 242 deletions(-) delete mode 100644 src/lib/BisectionLib.sol delete mode 100644 test/unit/ApproxSpotPrice.t.sol diff --git a/src/LiquidityManager.sol b/src/LiquidityManager.sol index 90eed3a..7584d57 100644 --- a/src/LiquidityManager.sol +++ b/src/LiquidityManager.sol @@ -5,9 +5,8 @@ import {IStandardizedYield} from "pendle/interfaces/IStandardizedYield.sol"; import {PYIndexLib, PYIndex} from "pendle/core/StandardizedYield/PYIndex.sol"; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; import {SafeTransferLib, ERC20} from "solmate/utils/SafeTransferLib.sol"; -import {console} from "forge-std/console.sol"; -import {RMM, IPYieldToken} from "./RMM.sol"; +import {RMM, IPYieldToken, Gaussian, computeTradingFunction} from "./RMM.sol"; import {InvalidTokenIn, InsufficientSYMinted} from "./lib/RmmErrors.sol"; contract LiquidityManager { @@ -115,7 +114,6 @@ contract LiquidityManager { // swap ptToSwap for sy (uint256 syOut,) = rmm.swapExactPtForSy(ptToSwap, args.minOut, address(this)); - console.log("syOut", syOut); sy.approve(address(rmm), type(uint256).max); liquidity = rmm.allocate(false, pt.balanceOf(address(this)), args.minLiquidityDelta, msg.sender); @@ -180,4 +178,22 @@ contract LiquidityManager { function isAApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) { return b.mulWadDown(1 ether - eps) <= a && a <= b.mulWadDown(1 ether + eps); } + + function calcMaxPtOut( + uint256 reserveX_, + uint256 reserveY_, + uint256 totalLiquidity_, + uint256 strike_, + uint256 sigma_, + uint256 tau_ + ) internal pure returns (uint256) { + int256 currentTF = computeTradingFunction(reserveX_, reserveY_, totalLiquidity_, strike_, sigma_, tau_); + + uint256 maxProportion = uint256(int256(1e18) - currentTF) * 1e18 / (2 * 1e18); + + uint256 maxPtOut = reserveY_ * maxProportion / 1e18; + + return (maxPtOut * 999) / 1000; + } + } diff --git a/src/RMM.sol b/src/RMM.sol index 50d9485..80a1a31 100644 --- a/src/RMM.sol +++ b/src/RMM.sol @@ -6,7 +6,6 @@ import {PYIndexLib, PYIndex} from "pendle/core/StandardizedYield/PYIndex.sol"; import {IPPrincipalToken} from "pendle/interfaces/IPPrincipalToken.sol"; import {IStandardizedYield} from "pendle/interfaces/IStandardizedYield.sol"; import {IPYieldToken} from "pendle/interfaces/IPYieldToken.sol"; -import "forge-std/console2.sol"; import "./lib/RmmLib.sol"; import "./lib/RmmErrors.sol"; @@ -22,19 +21,16 @@ contract RMM is ERC20 { using SafeTransferLib for ERC20; - uint256 public constant IMPLIED_RATE_TIME = 365 * 86400; - uint256 public constant BURNT_LIQUIDITY = 1000; + IPPrincipalToken public PT; + IStandardizedYield public SY; + IPYieldToken public YT; - IPPrincipalToken public immutable PT; - IStandardizedYield public immutable SY; - IPYieldToken public immutable YT; + uint256 public SY_scalar; + uint256 public PT_scalar; - uint256 public immutable SY_scalar; - uint256 public immutable PT_scalar; - - uint256 public immutable sigma; - uint256 public immutable fee; - uint256 public immutable maturity; + uint256 public sigma; + uint256 public fee; + uint256 public maturity; uint256 public reserveX; uint256 public reserveY; @@ -93,14 +89,13 @@ contract RMM is ERC20 { lock returns (uint256 totalLiquidity_, uint256 amountY) { - if (strike != 0) revert AlreadyInitialized(); - if (strike_ <= 1e18) revert InvalidStrike(); + if (strike_ <= 1e18 || strike_ != 0) revert InvalidStrikeChange(); PYIndex index = YT.newIndex(); (totalLiquidity_, amountY) = prepareInit(priceX, amountX, strike_, sigma, index); - _mint(msg.sender, totalLiquidity_ - BURNT_LIQUIDITY); - _mint(address(0), BURNT_LIQUIDITY); + _mint(msg.sender, totalLiquidity_ - 1000); + _mint(address(0), 1000); _adjust(toInt(amountX), toInt(amountY), toInt(totalLiquidity_), strike_, index); _debit(address(SY), reserveX); _debit(address(PT), reserveY); @@ -392,7 +387,7 @@ contract RMM is ERC20 { int256 timeToExpiry = int256(maturity) - int256(block.timestamp); lastImpliedPrice = timeToExpiry > 0 - ? uint256(int256(approxSpotPrice(index.syToAsset(reserveX))).lnWad() * int256(IMPLIED_RATE_TIME) / timeToExpiry) + ? uint256(int256(computeSpotPrice(index.syToAsset(reserveX), totalLiquidity, strike, sigma, lastTau())).lnWad() * int256(365 * 86400) / timeToExpiry) : 1 ether; } @@ -437,19 +432,13 @@ contract RMM is ERC20 { return computeTradingFunction(totalAsset, reserveY, totalLiquidity, strike, sigma, lastTau()); } - /// @notice Uses state to approximate the spot price of the X token in terms of the Y token. - /// @dev Do not rely on this for onchain calculations. - function approxSpotPrice(uint256 totalAsset) public view returns (uint256) { - return computeSpotPrice(totalAsset, totalLiquidity, strike, sigma, lastTau()); - } - function computeKGivenLastPrice(uint256 reserveX_, uint256 liquidity, uint256 sigma_, uint256 tau_) public view returns (uint256) { int256 timeToExpiry = int256(maturity - block.timestamp); - int256 rt = int256(lastImpliedPrice) * int256(timeToExpiry) / int256(IMPLIED_RATE_TIME); + int256 rt = int256(lastImpliedPrice) * int256(timeToExpiry) / int256(365 * 86400); int256 lastPrice = rt.expWad(); uint256 a = sigma_.mulWadDown(sigma_).mulWadDown(tau_).mulWadDown(0.5 ether); @@ -502,77 +491,6 @@ contract RMM is ERC20 { } } - function calcMaxPtOut( - uint256 reserveX_, - uint256 reserveY_, - uint256 totalLiquidity_, - uint256 strike_, - uint256 sigma_, - uint256 tau_ - ) internal pure returns (uint256) { - int256 currentTF = computeTradingFunction(reserveX_, reserveY_, totalLiquidity_, strike_, sigma_, tau_); - - uint256 maxProportion = uint256(int256(1e18) - currentTF) * 1e18 / (2 * 1e18); - - uint256 maxPtOut = reserveY_ * maxProportion / 1e18; - - return (maxPtOut * 999) / 1000; - } - - function calcMaxPtIn( - uint256 reserveX_, - uint256 reserveY_, - uint256 totalLiquidity_, - uint256 strike_ - ) internal pure returns (uint256) { - uint256 low = 0; - uint256 high = reserveY_ - 1; - - while (low != high) { - uint256 mid = (low + high + 1) / 2; - if (calcSlope(reserveX_, reserveY_, totalLiquidity_, strike_, int256(mid)) < 0) { - high = mid - 1; - } else { - low = mid; - } - } - - return low; - } - - - - function calcSlope( - uint256 reserveX_, - uint256 reserveY_, - uint256 totalLiquidity_, - uint256 strike_, - int256 ptToMarket - ) internal pure returns (int256) { - uint256 newReserveY = reserveY_ + uint256(ptToMarket); - uint256 b_i = newReserveY * 1e36 / (strike_ * totalLiquidity_); - - if (b_i > 1e18) { - return -1; - } - - int256 b = Gaussian.ppf(toInt(b_i)); - int256 pdf_b = Gaussian.pdf(b); - - int256 slope = (int256(strike_ * totalLiquidity_) * pdf_b / 1e36); - - int256 dxdy = computedXdY(reserveX_, newReserveY); - - return slope + dxdy; - } - - function computedXdY( - uint256 reserveX_, - uint256 reserveY_ - ) internal pure returns (int256) { - return -int256(reserveX_) * 1e18 / int256(reserveY_); - } - //prepare calls function prepareInit(uint256 priceX, uint256 amountX, uint256 strike_, uint256 sigma_, PYIndex index) public @@ -749,10 +667,6 @@ contract RMM is ERC20 { } function redeemPy(uint256 amount, address to) internal returns (uint256 amountOut) { - console2.log("PT balance", PT.balanceOf(address(this))); - console2.log("YT balance", YT.balanceOf(address(this))); - console2.log("SY balance", SY.balanceOf(address(YT))); - console2.log("SY address", address(SY)); PT.transfer(address(YT), amount); YT.transfer(address(YT), amount); amountOut = YT.redeemPY(to); diff --git a/src/lib/BisectionLib.sol b/src/lib/BisectionLib.sol deleted file mode 100644 index 8ad9f34..0000000 --- a/src/lib/BisectionLib.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.13; - -/// @dev Thrown when the lower bound is greater than the upper bound. -error BisectionLib_InvalidBounds(uint256 lower, uint256 upper); -/// @dev Thrown when the result of the function `fx` for each input, `upper` and `lower`, is the same sign. -error BisectionLib_RootOutsideBounds(int256 lowerResult, int256 upperResult); - -/** - * @notice - * The function `fx` must be continuous and monotonic. - * - * @dev - * Bisection is a method of finding the root of a function. - * The root is the point where the function crosses the x-axis. - * - * @param args The arguments to pass to the function `fx`. - * @param lower The lower bound of the root to find. - * @param upper The upper bound of the root to find. - * @param epsilon The maximum distance between the lower and upper results. - * @param maxIterations The maximum amount of loop iterations to run. - * @param fx The function to find the root of. - * @return root The root of the function `fx`. - */ -function bisection( - bytes memory args, - uint256 lower, - uint256 upper, - uint256 epsilon, - uint256 maxIterations, - function (bytes memory,uint256) pure returns (int256) fx -) pure returns (uint256 root, uint256 upperInput, uint256 lowerInput) { - if (lower > upper) revert BisectionLib_InvalidBounds(lower, upper); - // Passes the lower and upper bounds to the optimized function. - // Reverts if the optimized function `fx` returns both negative or both positive values. - // This means that the root is not between the bounds. - // The root is between the bounds if the product of the two values is negative. - int256 lowerOutput = fx(args, lower); - int256 upperOutput = fx(args, upper); - if (lowerOutput * upperOutput > 0) { - revert BisectionLib_RootOutsideBounds(lowerOutput, upperOutput); - } - - // Distance is optimized to equal `epsilon`. - uint256 distance = upper - lower; - upperInput = upper; - lowerInput = lower; - - uint256 iterations; // Bounds the amount of loops to `maxIterations`. - do { - // Bisection uses the point between the lower and upper bounds. - // The `distance` is halved each iteration. - root = (lowerInput + upperInput) / 2; - - int256 output = fx(args, root); - - // If the product is negative, the root is between the lower and root. - // If the product is positive, the root is between the root and upper. - if (output * lowerOutput <= 0) { - upperInput = root; // Set the new upper bound to the root because we know its between the lower and root. - } else { - lowerInput = root; // Set the new lower bound to the root because we know its between the upper and root. - lowerOutput = output; // root function value becomes new lower output value - } - - // Update the distance with the new bounds. - distance = upper - lower; - - unchecked { - iterations++; // Increment the iterator. - } - } while (distance > epsilon && iterations < maxIterations); -} diff --git a/src/lib/LiquidityLib.sol b/src/lib/LiquidityLib.sol index 03be469..eafa85f 100644 --- a/src/lib/LiquidityLib.sol +++ b/src/lib/LiquidityLib.sol @@ -6,24 +6,6 @@ import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; using FixedPointMathLib for uint256; using FixedPointMathLib for int256; -function computeAllocationGivenX(bool add, uint256 amountX, uint256 rx, uint256 L) - pure - returns (uint256 nextRx, uint256 nextL) -{ - uint256 deltaL = amountX.mulDivDown(L, rx); - nextRx = add ? rx + amountX : rx - amountX; - nextL = add ? L + deltaL : L - deltaL; -} - -function computeAllocationGivenY(bool add, uint256 amountY, uint256 ry, uint256 L) - pure - returns (uint256 nextRy, uint256 nextL) -{ - uint256 deltaL = amountY.mulDivDown(L, ry); - nextRy = add ? ry + amountY : ry - amountY; - nextL = add ? L + deltaL : L - deltaL; -} - function computeDeltaLGivenDeltaX(uint256 deltaX, uint256 liquidity, uint256 reserveX) pure returns (uint256 deltaL) { return liquidity.mulDivDown(deltaX, reserveX); } @@ -62,12 +44,4 @@ function computeAllocationGivenDeltaY(uint256 deltaY, uint256 reserveX, uint256 { deltaX = computeDeltaXGivenDeltaY(deltaY, reserveX, reserveY); deltaL = computeDeltaLGivenDeltaY(deltaY, liquidity, reserveY); -} - -function computeAllocationGivenDeltaL(uint256 deltaL, uint256 reserveX, uint256 reserveY, uint256 liquidity) - pure - returns (uint256 deltaX, uint256 deltaY) -{ - deltaX = computeDeltaXGivenDeltaL(deltaL, reserveX, liquidity); - deltaY = computeDeltaYGivenDeltaL(deltaL, reserveY, liquidity); -} +} \ No newline at end of file diff --git a/src/lib/RmmErrors.sol b/src/lib/RmmErrors.sol index 1871088..95f375d 100644 --- a/src/lib/RmmErrors.sol +++ b/src/lib/RmmErrors.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.13; /// @dev Thrown if trying to initialize a pool with an invalid strike price (strike < 1e18). -error InvalidStrike(); +/// @dev Thrown if trying to change the strike price of an already initialized pool. +error InvalidStrikeChange(); /// @dev Thrown if trying to initialize an already initialized pool. error AlreadyInitialized(); /// @dev Thrown when a `balanceOf` call fails or returns unexpected data. @@ -31,3 +32,6 @@ error InvalidTokenIn(address tokenIn); error Reentrancy(); error MaturityReached(); + +error ToIntOverflow(); +error ToUintOverflow(); diff --git a/src/lib/RmmLib.sol b/src/lib/RmmLib.sol index 415c912..d059bf2 100644 --- a/src/lib/RmmLib.sol +++ b/src/lib/RmmLib.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.13; import {Gaussian} from "solstat/Gaussian.sol"; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; +import {ToUintOverflow, ToIntOverflow} from "./RmmErrors.sol"; using FixedPointMathLib for uint256; using FixedPointMathLib for int256; @@ -14,6 +15,7 @@ struct PoolPreCompute { uint256 tau_; } + function computeLnSDivK(uint256 S, uint256 strike_) pure returns (int256) { return int256(S.divWadDown(strike_)).lnWad(); } @@ -356,21 +358,101 @@ function computeTfDReserveY(bytes memory args, uint256 rY) pure returns (int256) return result; } +function calcMaxPtIn( + uint256 reserveX_, + uint256 reserveY_, + uint256 totalLiquidity_, + uint256 strike_ + ) pure returns (uint256) { + uint256 low = 0; + uint256 high = reserveY_ - 1; + + while (low != high) { + uint256 mid = (low + high + 1) / 2; + if (calcSlope(reserveX_, reserveY_, totalLiquidity_, strike_, int256(mid)) < 0) { + high = mid - 1; + } else { + low = mid; + } + } + + return low; + } + +function calcSlope( + uint256 reserveX_, + uint256 reserveY_, + uint256 totalLiquidity_, + uint256 strike_, + int256 ptToMarket +) pure returns (int256) { + uint256 newReserveY = reserveY_ + uint256(ptToMarket); + uint256 b_i = newReserveY * 1e36 / (strike_ * totalLiquidity_); + + if (b_i > 1e18) { + return -1; + } + + int256 b = Gaussian.ppf(toInt(b_i)); + int256 pdf_b = Gaussian.pdf(b); + + int256 slope = (int256(strike_ * totalLiquidity_) * pdf_b / 1e36); + + int256 dxdy = computedXdY(reserveX_, newReserveY); + + return slope + dxdy; +} + +function calcMaxPtOut( + uint256 reserveX_, + uint256 reserveY_, + uint256 totalLiquidity_, + uint256 strike_, + uint256 sigma_, + uint256 tau_ +) pure returns (uint256) { + int256 currentTF = computeTradingFunction(reserveX_, reserveY_, totalLiquidity_, strike_, sigma_, tau_); + + uint256 maxProportion = uint256(int256(1e18) - currentTF) * 1e18 / (2 * 1e18); + + uint256 maxPtOut = reserveY_ * maxProportion / 1e18; + + return (maxPtOut * 999) / 1000; +} + + +function computedXdY( + uint256 reserveX_, + uint256 reserveY_ +) pure returns (int256) { + return -int256(reserveX_) * 1e18 / int256(reserveY_); +} + + /// @dev Casts an unsigned integer to a signed integer, reverting if `x` is too large. function toInt(uint256 x) pure returns (int256) { // Safe cast below because `type(int256).max` is positive. - require(x <= uint256(type(int256).max), "toInt: overflow"); - return int256(x); + if (x <= uint256(type(int256).max)) { + return int256(x); + } else { + revert ToIntOverflow(); + } } /// @dev Sums an unsigned integer with a signed integer, reverting if the result overflows. function sum(uint256 a, int256 b) pure returns (uint256) { if (b < 0) { - require(a >= uint256(-b), "sum: underflow"); - return a - uint256(-b); + if (a >= uint256(-b)) { + return a - uint256(-b); + } else { + revert ToUintOverflow(); + } } else { - require(a + uint256(b) >= a, "sum: overflow"); - return a + uint256(b); + if (a + uint256(b) >= a) { + return a + uint256(b); + } else { + revert ToUintOverflow(); + } } } @@ -391,7 +473,9 @@ function downscaleUp(uint256 amount, uint256 scalar_) pure returns (uint256) { /// @dev Casts a positived signed integer to an unsigned integer, reverting if `x` is negative. function toUint(int256 x) pure returns (uint256) { - require(x >= 0, "toUint: negative"); + if (x < 0) { + revert ToUintOverflow(); + } return uint256(x); } diff --git a/test/unit/ApproxSpotPrice.t.sol b/test/unit/ApproxSpotPrice.t.sol deleted file mode 100644 index dacec5a..0000000 --- a/test/unit/ApproxSpotPrice.t.sol +++ /dev/null @@ -1,20 +0,0 @@ -/// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {SetUp} from "../SetUp.sol"; - -contract ApproxSpotPriceTest is SetUp { - function test_approxSpotPrice_IncreasesOverTime() public useDefaultPool { - uint256 preSpotPrice = rmm.approxSpotPrice(syToAsset(rmm.reserveX())); - rmm.setLastTimestamp(block.timestamp + 10 days); - uint256 postSpotPrice = rmm.approxSpotPrice(syToAsset(rmm.reserveX())); - assertGt(postSpotPrice, preSpotPrice); - } - - function test_approxSpotPrice_OneAtMaturity() public useDefaultPool { - vm.warp(rmm.maturity()); - rmm.swapExactSyForPt(1 ether, 0, address(this)); - uint256 maturityPrice = rmm.approxSpotPrice(syToAsset(rmm.reserveX())); - assertEq(maturityPrice, 1 ether); - } -} diff --git a/test/unit/Init.t.sol b/test/unit/Init.t.sol index 392a593..cd4449b 100644 --- a/test/unit/Init.t.sol +++ b/test/unit/Init.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.13; import {SetUp, RMM, InitParams, DEFAULT_EXPIRY} from "../SetUp.sol"; import {Init} from "../../src/lib/RmmEvents.sol"; -import {AlreadyInitialized, InvalidStrike} from "../../src/lib/RmmErrors.sol"; +import {InvalidStrikeChange} from "../../src/lib/RmmErrors.sol"; contract InitTest is SetUp { function test_init_MintsLiquidity() @@ -20,8 +20,8 @@ contract InitTest is SetUp { rmm.init(initParams.priceX, initParams.amountX, initParams.strike); assertEq(rmm.totalLiquidity(), totalLiquidity); - assertEq(rmm.balanceOf(address(this)), totalLiquidity - rmm.BURNT_LIQUIDITY()); - assertEq(rmm.balanceOf(address(0)), rmm.BURNT_LIQUIDITY()); + assertEq(rmm.balanceOf(address(this)), totalLiquidity - 1000); + assertEq(rmm.balanceOf(address(0)), 1000); } function test_init_AdjustsPool() public withSY(address(this), 2000000 ether) withPY(address(this), 1000000 ether) { @@ -99,7 +99,7 @@ contract InitTest is SetUp { { InitParams memory initParams = getDefaultParams(); - vm.expectRevert(AlreadyInitialized.selector); + vm.expectRevert(InvalidStrikeChange.selector); rmm.init(initParams.priceX, initParams.amountX, initParams.strike); } @@ -111,7 +111,7 @@ contract InitTest is SetUp { InitParams memory initParams = getDefaultParams(); setUpRMM(initParams); - vm.expectRevert(InvalidStrike.selector); + vm.expectRevert(InvalidStrikeChange.selector); rmm.init(initParams.priceX, initParams.amountX, 1 ether); } diff --git a/test/unit/LiquidityManager.t.sol b/test/unit/LiquidityManager.t.sol index 287074b..5683dd9 100644 --- a/test/unit/LiquidityManager.t.sol +++ b/test/unit/LiquidityManager.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.13; import {Test, console2} from "forge-std/Test.sol"; -import {RMM, toInt, toUint, upscale, downscaleDown, scalar, sum, abs, PoolPreCompute} from "../../src/RMM.sol"; +import {RMM, upscale, downscaleDown, scalar, sum, abs, PoolPreCompute} from "../../src/RMM.sol"; import {LiquidityManager, RMM} from "../../src/LiquidityManager.sol"; import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; import {IPMarket} from "pendle/interfaces/IPMarket.sol"; diff --git a/test/unit/SwapExactPtForSy.t.sol b/test/unit/SwapExactPtForSy.t.sol index 1ac50aa..95eb337 100644 --- a/test/unit/SwapExactPtForSy.t.sol +++ b/test/unit/SwapExactPtForSy.t.sol @@ -5,7 +5,7 @@ import {ERC20} from "solmate/tokens/ERC20.sol"; import {InsufficientOutput} from "../../src/lib/RmmErrors.sol"; import {Swap} from "../../src/lib/RmmEvents.sol"; import {SetUp} from "../SetUp.sol"; -import {abs} from "./../../src/lib/RmmLib.sol"; +import {abs, computeSpotPrice} from "./../../src/lib/RmmLib.sol"; contract SwapExactPtForSyTest is SetUp { function test_swapExactPtForSy_TransfersTokens() public useDefaultPool { @@ -49,9 +49,9 @@ contract SwapExactPtForSyTest is SetUp { function test_swapExactPtForSy_MaintainsPrice() public useDefaultPool { uint256 amountIn = 1 ether; - uint256 prevPrice = rmm.approxSpotPrice(syToAsset(rmm.reserveX())); + uint256 prevPrice = computeSpotPrice(syToAsset(rmm.reserveX()), rmm.totalLiquidity(), rmm.strike(), rmm.sigma(), rmm.lastTau()); rmm.swapExactPtForSy(amountIn, 0, address(this)); - assertTrue(rmm.approxSpotPrice(syToAsset(rmm.reserveX())) > prevPrice, "Price did not increase after buying Y."); + assertTrue(computeSpotPrice(syToAsset(rmm.reserveX()), rmm.totalLiquidity(), rmm.strike(), rmm.sigma(), rmm.lastTau()) > prevPrice, "Price did not increase after buying Y."); } function test_swapExactPtForSy_EmitsEvent() public useDefaultPool { diff --git a/test/unit/SwapExactSyForPt.t.sol b/test/unit/SwapExactSyForPt.t.sol index 4788de3..e9b160c 100644 --- a/test/unit/SwapExactSyForPt.t.sol +++ b/test/unit/SwapExactSyForPt.t.sol @@ -5,7 +5,7 @@ import {ERC20} from "solmate/tokens/ERC20.sol"; import {SetUp} from "../SetUp.sol"; import {Swap} from "../../src/lib/RmmEvents.sol"; import {InsufficientOutput} from "../../src/lib/RmmErrors.sol"; -import {abs} from "./../../src/lib/RmmLib.sol"; +import {abs, computeSpotPrice} from "./../../src/lib/RmmLib.sol"; contract SwapExactSyForPtTest is SetUp { function test_swapExactSyForPt_TransfersTokens() public useDefaultPool { @@ -52,9 +52,9 @@ contract SwapExactSyForPtTest is SetUp { function test_swapExactSyForPt_MaintainsPrice() public useDefaultPool { uint256 amountIn = 1 ether; - uint256 prevPrice = rmm.approxSpotPrice(syToAsset(rmm.reserveX())); + uint256 prevPrice = computeSpotPrice(syToAsset(rmm.reserveX()), rmm.totalLiquidity(), rmm.strike(), rmm.sigma(), rmm.lastTau()); rmm.swapExactSyForPt(amountIn, 0, address(this)); - assertTrue(rmm.approxSpotPrice(syToAsset(rmm.reserveX())) < prevPrice, "Price did not increase after buying Y."); + assertTrue(computeSpotPrice(syToAsset(rmm.reserveX()), rmm.totalLiquidity(), rmm.strike(), rmm.sigma(), rmm.lastTau()) < prevPrice, "Price did not increase after buying Y."); } function test_swapExactSyForPt_EmitsEvent() public useDefaultPool {