From ad95d229b91b1bd5901b12c750b479673aa1ddd3 Mon Sep 17 00:00:00 2001 From: kinrezc Date: Fri, 23 Feb 2024 13:13:57 -0500 Subject: [PATCH 01/37] feat: logging on atomic arb contract --- src/LogNormal/LogNormalSolver.sol | 2 +- src/test/helpers/AtomicV2.sol | 74 +++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 7997ddac..482c8370 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: GPL-3.0-or-latersolver pragma solidity ^0.8.13; import "./LogNormalExtendedLib.sol"; diff --git a/src/test/helpers/AtomicV2.sol b/src/test/helpers/AtomicV2.sol index 549463e9..b8dd4f58 100644 --- a/src/test/helpers/AtomicV2.sol +++ b/src/test/helpers/AtomicV2.sol @@ -6,13 +6,24 @@ import "solmate/utils/FixedPointMathLib.sol"; import "src/lib/BisectionLib.sol"; import "forge-std/console2.sol"; +struct LogNormalParams { + uint256 strike; + uint256 sigma; + uint256 tau; + uint256 swapFee; + address controller; +} + interface LiquidExchange { function swap(address token, uint256 amount) external; function price() external returns (uint256); } -interface StrategyLike { +interface DfmmLike { function swap(uint256 poolId, bytes calldata data) external; +} + +interface SolverLike { function simulateSwap( uint256 poolId, bool swapXIn, @@ -31,8 +42,18 @@ interface StrategyLike { external view returns (uint256, uint256, uint256); + function strategy() external view returns (address); } +interface LogNormalStrategyLike { + function fetchPoolParams(uint256 poolId) external view returns (LogNormalParams memory); +} + +interface StrategyLike { + function name() external view returns (string memory); +} + + interface TokenLike { function transferFrom(address, address, uint256) external; function transfer(address, uint256) external; @@ -69,6 +90,9 @@ contract AtomicV2 { address public solver; address public asset; address public quote; + address public strategy; + + string public strategyName; /// @dev Since token x is transferred inside the arbitrage loop, this stores that value in the last arb loop. uint256 public intermediateTokenXBalance; @@ -90,16 +114,36 @@ contract AtomicV2 { liquidExchange = liquidExchangeAddress; asset = assetAddress; quote = quoteAddress; + strategy = SolverLike(solver).strategy(); + strategyName = StrategyLike(strategy).name(); } bool public XTOY = true; bool public YTOX = false; error AttemptedProfit(int256 profit); + event LogDfmmData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry, uint256 liq, uint256 strike, uint256 sigma, uint256 tau); + event LogLexData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry); + event LogArbData(uint256 xBalance, uint256 yBalance, uint256 timestamp); function lower_exchange_price(uint256 poolId, uint256 input) external { - uint256 price = StrategyLike(solver).internalPrice(poolId); - emit Price(price, block.timestamp); + uint256 price = SolverLike(solver).internalPrice(poolId); + + if (keccak256(abi.encode(strategyName)) == keccak256(abi.encode("LogNormal"))) { + (uint256 rx, uint256 ry, uint256 L) = SolverLike(solver).getReservesAndLiquidity(poolId); + LogNormalParams memory params = LogNormalStrategyLike(solver).fetchPoolParams(poolId); + emit LogDfmmData(price, block.timestamp, rx, ry, L, params.strike, params.sigma, params.tau); + } + + uint256 lexPrice = LiquidExchange(liquidExchange).price(); + uint256 lexBalanceX = TokenLike(asset).balanceOf(liquidExchange); + uint256 lexBalanceY = TokenLike(quote).balanceOf(liquidExchange); + emit LogLexData(lexPrice, block.timestamp, lexBalanceX, lexBalanceY); + + uint256 arbBalanceX = TokenLike(asset).balanceOf(msg.sender); + uint256 arbBalanceY = TokenLike(quote).balanceOf(msg.sender); + emit LogArbData(arbBalanceX, arbBalanceY, block.timestamp); + // Arbitrageur Y -> AtomicV2 _invoice(input); @@ -114,8 +158,22 @@ contract AtomicV2 { } function raise_exchange_price(uint256 poolId, uint256 input) external { - uint256 price = StrategyLike(solver).internalPrice(poolId); - emit Price(price, block.timestamp); + uint256 price = SolverLike(solver).internalPrice(poolId); + if (keccak256(abi.encode(strategyName)) == keccak256(abi.encode("LogNormal"))) { + (uint256 rx, uint256 ry, uint256 L) = SolverLike(solver).getReservesAndLiquidity(poolId); + LogNormalParams memory params = LogNormalStrategyLike(solver).fetchPoolParams(poolId); + emit LogDfmmData(price, block.timestamp, rx, ry, L, params.strike, params.sigma, params.tau); + } + + uint256 lexPrice = LiquidExchange(liquidExchange).price(); + uint256 lexBalanceX = TokenLike(asset).balanceOf(liquidExchange); + uint256 lexBalanceY = TokenLike(quote).balanceOf(liquidExchange); + emit LogLexData(lexPrice, block.timestamp, lexBalanceX, lexBalanceY); + + uint256 arbBalanceX = TokenLike(asset).balanceOf(msg.sender); + uint256 arbBalanceY = TokenLike(quote).balanceOf(msg.sender); + emit LogArbData(arbBalanceX, arbBalanceY, block.timestamp); + // Arbitrageur Y -> AtomicV2 _invoice(input); @@ -194,7 +252,7 @@ contract AtomicV2 { uint256 estimatedOut, uint256 estimatedPrice, bytes memory payload - ) = StrategyLike(solver).simulateSwap(poolId, swapXIn, amountIn); + ) = SolverLike(solver).simulateSwap(poolId, swapXIn, amountIn); if (!valid) { revert SimulatedSwapFailure( @@ -203,7 +261,7 @@ contract AtomicV2 { } // Execute the swap. - try StrategyLike(exchange).swap(poolId, payload) { + try DfmmLike(exchange).swap(poolId, payload) { // Swap succeeded, do nothing other than store the intermediary balance. if (swapXIn) { // If X -> Y @@ -262,7 +320,7 @@ contract AtomicV2 { bytes memory payload ) { - return StrategyLike(solver).simulateSwap(poolId, swapXIn, amountIn); + return SolverLike(solver).simulateSwap(poolId, swapXIn, amountIn); } function cdf(int256 input) public pure returns (int256 output) { From 0a0a6de434573ff90fa0a009955f0828113a8700 Mon Sep 17 00:00:00 2001 From: kinrezc Date: Fri, 23 Feb 2024 14:54:21 -0500 Subject: [PATCH 02/37] fix: logData function in atomic: --- src/test/LogNormal/LogNormalTest.t.sol | 87 +++----------------------- src/test/helpers/AtomicV2.sol | 21 ++----- 2 files changed, 12 insertions(+), 96 deletions(-) diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index 16bc02e5..92c28531 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -6,6 +6,7 @@ import "solmate/test/utils/mocks/MockERC20.sol"; import "src/DFMM.sol"; import "src/LogNormal/LogNormal.sol"; import "src/LogNormal/LogNormalSolver.sol"; +import "../helpers/AtomicV2.sol"; import "../helpers/Lex.sol"; contract LogNormalTest is Test { @@ -17,6 +18,7 @@ contract LogNormalTest is Test { address tokenX; address tokenY; Lex lex; + AtomicV2 atomic; uint256 public constant TEST_SWAP_FEE = 0.003 ether; @@ -30,8 +32,11 @@ contract LogNormalTest is Test { dfmm = new DFMM(address(0)); logNormal = new LogNormal(address(dfmm)); solver = new LogNormalSolver(address(logNormal)); + atomic = new AtomicV2(address(solver), address(dfmm), address(lex), tokenX, tokenY); MockERC20(tokenX).approve(address(dfmm), type(uint256).max); MockERC20(tokenY).approve(address(dfmm), type(uint256).max); + MockERC20(tokenX).approve(address(atomic), type(uint256).max); + MockERC20(tokenY).approve(address(atomic), type(uint256).max); } modifier realisticEth() { @@ -180,83 +185,7 @@ contract LogNormalTest is Test { console2.log(optimalRaise); } - // function test_internal_price() public basic { - // uint256 internalPrice = solver.internalPrice(); - - // console2.log(internalPrice); - // } - - // function test_internal_price_post_y_in() public basic { - // uint256 internalPrice = solver.internalPrice(); - // uint256 amountIn = 0.1 ether; - // bool swapXIn = false; - - // // Try doing simulate swap to see if we get a similar result. - // (bool valid,,, bytes memory payload) = - // solver.simulateSwap(swapXIn, amountIn); - - // assertEq(valid, true); - - // dfmm.swap(payload); - - // uint256 postSwapInternalPrice = solver.internalPrice(); - - // assertGt(postSwapInternalPrice, internalPrice); - // } - - // function test_internal_price_post_x_in() public basic { - // uint256 internalPrice = solver.internalPrice(); - // uint256 amountIn = 0.1 ether; - // bool swapXIn = true; - - // // Try doing simulate swap to see if we get a similar result. - // (bool valid,,, bytes memory payload) = - // solver.simulateSwap(swapXIn, amountIn); - - // assertEq(valid, true); - - // dfmm.swap(payload); - - // uint256 postSwapInternalPrice = solver.internalPrice(); - - // assertLt(postSwapInternalPrice, internalPrice); - // } - - // function test_swap_eth_backtest() public realisticEth { - // uint256 amountIn = 0.1 ether; - // bool swapXIn = true; - - // // Try doing simulate swap to see if we get a similar result. - // (bool valid,,, bytes memory payload) = - // solver.simulateSwap(swapXIn, amountIn); - - // assertEq(valid, true); - - // dfmm.swap(payload); - // } - - // function test_allocate_multiple_times() public basic { - // uint256 amountX = 0.1 ether; - // (uint256 rx, uint256 ry, uint256 L) = solver.allocateGivenX(amountX); - - // uint256 preBalance = dfmm.balanceOf(address(this)); - // uint256 deltaLiquidity = L - dfmm.totalLiquidity(); - // bytes memory data = abi.encode(rx, ry, L); - // dfmm.allocate(data); - // assertEq(preBalance + deltaLiquidity, dfmm.balanceOf(address(this))); - - // (rx, ry, L) = solver.allocateGivenX(amountX * 2); - // deltaLiquidity = L - dfmm.totalLiquidity(); - // data = abi.encode(rx, ry, L); - - // MockERC20(tokenX).mint(address(0xbeef), rx); - // MockERC20(tokenY).mint(address(0xbeef), ry); - - // vm.startPrank(address(0xbeef)); - // MockERC20(tokenX).approve(address(dfmm), type(uint256).max); - // MockERC20(tokenY).approve(address(dfmm), type(uint256).max); - // dfmm.allocate(data); - // assertEq(deltaLiquidity, dfmm.balanceOf(address(0xbeef))); - // vm.stopPrank(); - // } + function test_atomic_events() public basic { + atomic.lower_exchange_price(dfmm.nonce() - 1, 0.01 ether); + } } diff --git a/src/test/helpers/AtomicV2.sol b/src/test/helpers/AtomicV2.sol index b8dd4f58..7c114e99 100644 --- a/src/test/helpers/AtomicV2.sol +++ b/src/test/helpers/AtomicV2.sol @@ -126,7 +126,7 @@ contract AtomicV2 { event LogLexData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry); event LogArbData(uint256 xBalance, uint256 yBalance, uint256 timestamp); - function lower_exchange_price(uint256 poolId, uint256 input) external { + function logData(uint256 poolId) external { uint256 price = SolverLike(solver).internalPrice(poolId); if (keccak256(abi.encode(strategyName)) == keccak256(abi.encode("LogNormal"))) { @@ -144,6 +144,9 @@ contract AtomicV2 { uint256 arbBalanceY = TokenLike(quote).balanceOf(msg.sender); emit LogArbData(arbBalanceX, arbBalanceY, block.timestamp); + } + + function lower_exchange_price(uint256 poolId, uint256 input) external { // Arbitrageur Y -> AtomicV2 _invoice(input); @@ -158,22 +161,6 @@ contract AtomicV2 { } function raise_exchange_price(uint256 poolId, uint256 input) external { - uint256 price = SolverLike(solver).internalPrice(poolId); - if (keccak256(abi.encode(strategyName)) == keccak256(abi.encode("LogNormal"))) { - (uint256 rx, uint256 ry, uint256 L) = SolverLike(solver).getReservesAndLiquidity(poolId); - LogNormalParams memory params = LogNormalStrategyLike(solver).fetchPoolParams(poolId); - emit LogDfmmData(price, block.timestamp, rx, ry, L, params.strike, params.sigma, params.tau); - } - - uint256 lexPrice = LiquidExchange(liquidExchange).price(); - uint256 lexBalanceX = TokenLike(asset).balanceOf(liquidExchange); - uint256 lexBalanceY = TokenLike(quote).balanceOf(liquidExchange); - emit LogLexData(lexPrice, block.timestamp, lexBalanceX, lexBalanceY); - - uint256 arbBalanceX = TokenLike(asset).balanceOf(msg.sender); - uint256 arbBalanceY = TokenLike(quote).balanceOf(msg.sender); - emit LogArbData(arbBalanceX, arbBalanceY, block.timestamp); - // Arbitrageur Y -> AtomicV2 _invoice(input); From 728ce2b27a8bbe27665f435aa5f7d3119e3052c5 Mon Sep 17 00:00:00 2001 From: kinrezc Date: Fri, 23 Feb 2024 16:03:09 -0500 Subject: [PATCH 03/37] testing arbiter bug --- src/test/LogNormal/LogNormalTest.t.sol | 2 +- src/test/helpers/AtomicV2.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index 92c28531..d9394234 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -186,6 +186,6 @@ contract LogNormalTest is Test { } function test_atomic_events() public basic { - atomic.lower_exchange_price(dfmm.nonce() - 1, 0.01 ether); + atomic.logData(dfmm.nonce() - 1); } } diff --git a/src/test/helpers/AtomicV2.sol b/src/test/helpers/AtomicV2.sol index 7c114e99..8d160ec9 100644 --- a/src/test/helpers/AtomicV2.sol +++ b/src/test/helpers/AtomicV2.sol @@ -124,7 +124,7 @@ contract AtomicV2 { error AttemptedProfit(int256 profit); event LogDfmmData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry, uint256 liq, uint256 strike, uint256 sigma, uint256 tau); event LogLexData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry); - event LogArbData(uint256 xBalance, uint256 yBalance, uint256 timestamp); + event LogTraderData(uint256 xBalance, uint256 yBalance, uint256 timestamp); function logData(uint256 poolId) external { uint256 price = SolverLike(solver).internalPrice(poolId); @@ -142,7 +142,7 @@ contract AtomicV2 { uint256 arbBalanceX = TokenLike(asset).balanceOf(msg.sender); uint256 arbBalanceY = TokenLike(quote).balanceOf(msg.sender); - emit LogArbData(arbBalanceX, arbBalanceY, block.timestamp); + emit LogTraderData(arbBalanceX, arbBalanceY, block.timestamp); } From a6e8653b2734fe2a2b86ce82314a14061928294e Mon Sep 17 00:00:00 2001 From: kinrezc Date: Fri, 23 Feb 2024 16:09:51 -0500 Subject: [PATCH 04/37] rename events --- src/test/helpers/AtomicV2.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/helpers/AtomicV2.sol b/src/test/helpers/AtomicV2.sol index 8d160ec9..f5460cdc 100644 --- a/src/test/helpers/AtomicV2.sol +++ b/src/test/helpers/AtomicV2.sol @@ -123,8 +123,8 @@ contract AtomicV2 { error AttemptedProfit(int256 profit); event LogDfmmData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry, uint256 liq, uint256 strike, uint256 sigma, uint256 tau); - event LogLexData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry); - event LogTraderData(uint256 xBalance, uint256 yBalance, uint256 timestamp); + event LogLiquidData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry); + event LogArbData(uint256 xBalance, uint256 yBalance, uint256 timestamp); function logData(uint256 poolId) external { uint256 price = SolverLike(solver).internalPrice(poolId); @@ -138,11 +138,11 @@ contract AtomicV2 { uint256 lexPrice = LiquidExchange(liquidExchange).price(); uint256 lexBalanceX = TokenLike(asset).balanceOf(liquidExchange); uint256 lexBalanceY = TokenLike(quote).balanceOf(liquidExchange); - emit LogLexData(lexPrice, block.timestamp, lexBalanceX, lexBalanceY); + emit LogLiquidData(lexPrice, block.timestamp, lexBalanceX, lexBalanceY); uint256 arbBalanceX = TokenLike(asset).balanceOf(msg.sender); uint256 arbBalanceY = TokenLike(quote).balanceOf(msg.sender); - emit LogTraderData(arbBalanceX, arbBalanceY, block.timestamp); + emit LogArbData(arbBalanceX, arbBalanceY, block.timestamp); } From c4f271aa9de53e0d5abd09e2c08b0b0bfea35fda Mon Sep 17 00:00:00 2001 From: kinrezc Date: Fri, 23 Feb 2024 16:31:43 -0500 Subject: [PATCH 05/37] rename event --- src/test/helpers/AtomicV2.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/helpers/AtomicV2.sol b/src/test/helpers/AtomicV2.sol index f5460cdc..7b81ee2e 100644 --- a/src/test/helpers/AtomicV2.sol +++ b/src/test/helpers/AtomicV2.sol @@ -123,7 +123,7 @@ contract AtomicV2 { error AttemptedProfit(int256 profit); event LogDfmmData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry, uint256 liq, uint256 strike, uint256 sigma, uint256 tau); - event LogLiquidData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry); + event LogAssetData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry); event LogArbData(uint256 xBalance, uint256 yBalance, uint256 timestamp); function logData(uint256 poolId) external { From 55c15f69fa9577ec5d90a1384dce0d0c0eebb5ea Mon Sep 17 00:00:00 2001 From: kinrezc Date: Fri, 23 Feb 2024 16:32:35 -0500 Subject: [PATCH 06/37] fix --- src/test/helpers/AtomicV2.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/helpers/AtomicV2.sol b/src/test/helpers/AtomicV2.sol index 7b81ee2e..505f7cdf 100644 --- a/src/test/helpers/AtomicV2.sol +++ b/src/test/helpers/AtomicV2.sol @@ -138,7 +138,7 @@ contract AtomicV2 { uint256 lexPrice = LiquidExchange(liquidExchange).price(); uint256 lexBalanceX = TokenLike(asset).balanceOf(liquidExchange); uint256 lexBalanceY = TokenLike(quote).balanceOf(liquidExchange); - emit LogLiquidData(lexPrice, block.timestamp, lexBalanceX, lexBalanceY); + emit LogAssetData(lexPrice, block.timestamp, lexBalanceX, lexBalanceY); uint256 arbBalanceX = TokenLike(asset).balanceOf(msg.sender); uint256 arbBalanceY = TokenLike(quote).balanceOf(msg.sender); From 5c4779df8bba28ff4973d8db9b154adc798e2dee Mon Sep 17 00:00:00 2001 From: kinrezc Date: Fri, 23 Feb 2024 16:48:40 -0500 Subject: [PATCH 07/37] event changes --- src/test/helpers/AtomicV2.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/helpers/AtomicV2.sol b/src/test/helpers/AtomicV2.sol index 505f7cdf..4a820c10 100644 --- a/src/test/helpers/AtomicV2.sol +++ b/src/test/helpers/AtomicV2.sol @@ -123,14 +123,14 @@ contract AtomicV2 { error AttemptedProfit(int256 profit); event LogDfmmData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry, uint256 liq, uint256 strike, uint256 sigma, uint256 tau); - event LogAssetData(uint256 price, uint256 timestamp, uint256 rx, uint256 ry); + event LogAssetData(uint256 lexPrice, uint256 timestamp, uint256 rx, uint256 ry); event LogArbData(uint256 xBalance, uint256 yBalance, uint256 timestamp); function logData(uint256 poolId) external { - uint256 price = SolverLike(solver).internalPrice(poolId); if (keccak256(abi.encode(strategyName)) == keccak256(abi.encode("LogNormal"))) { (uint256 rx, uint256 ry, uint256 L) = SolverLike(solver).getReservesAndLiquidity(poolId); + uint256 price = SolverLike(solver).internalPrice(poolId); LogNormalParams memory params = LogNormalStrategyLike(solver).fetchPoolParams(poolId); emit LogDfmmData(price, block.timestamp, rx, ry, L, params.strike, params.sigma, params.tau); } From 87e630b20ec2d06d02c9530716b49af8f2fff4eb Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Mon, 4 Mar 2024 13:56:57 -0500 Subject: [PATCH 08/37] hacking matts computer --- foundry.toml | 2 +- src/GeometricMean/G3MExtendedLib.sol | 239 ++++++++++----- src/GeometricMean/GeometricMean.sol | 2 + src/GeometricMean/GeometricMeanSolver.sol | 2 +- src/LogNormal/LogNormalExtendedLib.sol | 353 +++++++++++++--------- src/LogNormal/LogNormalSolver.sol | 18 +- src/lib/BisectionLib.sol | 4 +- src/test/LogNormal/LogNormalTest.t.sol | 36 ++- 8 files changed, 418 insertions(+), 238 deletions(-) diff --git a/foundry.toml b/foundry.toml index 11cd564e..745c98f3 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,7 +9,7 @@ solc_version = "0.8.22" # these are defaults. explicitly setting them here for clarity. libs = ["lib"] out = "out/" -via-ir = true +via-ir = false [fmt] bracket_spacing = true diff --git a/src/GeometricMean/G3MExtendedLib.sol b/src/GeometricMean/G3MExtendedLib.sol index 5c7ae879..416a9b78 100644 --- a/src/GeometricMean/G3MExtendedLib.sol +++ b/src/GeometricMean/G3MExtendedLib.sol @@ -17,7 +17,7 @@ function computeLGivenX( uint256 x, uint256 S, GeometricMeanParams memory params -) pure returns (uint256) { +) view returns (uint256) { int256 a = int256(params.wY.divWadUp(params.wX).mulWadUp(S)); int256 b = a.powWad(int256(params.wY)); return x.mulWadUp(uint256(b)); @@ -27,7 +27,7 @@ function computeLGivenY( uint256 y, uint256 S, GeometricMeanParams memory params -) pure returns (uint256) { +) view returns (uint256) { return y.mulWadUp(params.wX).divWadUp(params.wY.mulWadUp(S)); } @@ -35,7 +35,7 @@ function computeXGivenL( uint256 L, uint256 S, GeometricMeanParams memory params -) pure returns (uint256) { +) view returns (uint256) { return params.wX.mulWadUp(L).divWadUp(params.wY.mulWadUp(S)); } @@ -43,7 +43,7 @@ function computeYGivenL( uint256 L, uint256 S, GeometricMeanParams memory params -) pure returns (uint256) { +) view returns (uint256) { return params.wY.mulWadUp(L).divWadUp(params.wX.mulWadUp(S)); } @@ -51,7 +51,7 @@ function computeY( uint256 x, uint256 S, GeometricMeanParams memory params -) pure returns (uint256) { +) view returns (uint256) { return params.wY.divWadDown(params.wX).mulWadDown(S).mulWadDown(x); } @@ -59,7 +59,7 @@ function computeX( uint256 y, uint256 S, GeometricMeanParams memory params -) pure returns (uint256) { +) view returns (uint256) { return params.wX.divWadDown(params.wY.mulWadDown(S)).mulWadDown(y); } @@ -67,7 +67,7 @@ function computeL( uint256 x, uint256 y, GeometricMeanParams memory params -) pure returns (uint256) { +) view returns (uint256) { uint256 a = uint256(int256(x).powWad(int256(params.wX))); uint256 b = uint256(int256(y).powWad(int256(params.wY))); @@ -78,7 +78,7 @@ function computeInitialPoolData( uint256 amountX, uint256 initialPrice, GeometricMeanParams memory params -) pure returns (bytes memory) { +) view returns (bytes memory) { uint256 rY = computeY(amountX, initialPrice, params); uint256 L = computeL(amountX, rY, params); @@ -100,7 +100,7 @@ function computeNextRy( uint256 rX, uint256 liquidity, GeometricMeanParams memory params -) pure returns (uint256 rY) { +) view returns (uint256 rY) { rY = uint256( int256( liquidity.divWadUp(uint256(int256(rX).powWad(int256(params.wX)))) @@ -113,7 +113,7 @@ function computeNextRx( uint256 rY, uint256 liquidity, GeometricMeanParams memory params -) pure returns (uint256 rX) { +) view returns (uint256 rX) { rX = uint256( int256( liquidity.divWadUp(uint256(int256(rY).powWad(int256(params.wY)))) @@ -126,19 +126,19 @@ function computePrice( uint256 rX, uint256 rY, GeometricMeanParams memory params -) pure returns (uint256 price) { +) view returns (uint256 price) { uint256 n = rY.divWadDown(params.wY); uint256 d = rX.divWadDown(params.wX); price = n.divWadDown(d); } -/// @dev This is a pure anonymous function defined at the file level, which allows +/// @dev This is a view anonymous function defined at the file level, which allows /// it to be passed as an argument to another function. BisectionLib.sol takes this /// function as an argument to find the root of the trading function given the liquidity. function findRootLiquidity( bytes memory data, uint256 L -) pure returns (int256) { +) view returns (int256) { (uint256 rX, uint256 rY,, GeometricMeanParams memory params) = abi.decode(data, (uint256, uint256, int256, GeometricMeanParams)); return GeometricMeanLib.tradingFunction({ @@ -149,7 +149,7 @@ function findRootLiquidity( }); } -function findRootLower(bytes memory data, uint256 v) pure returns (int256) { +function findRootLower(bytes memory data, uint256 v) view returns (int256) { ( uint256 S, uint256 rX, @@ -162,7 +162,7 @@ function findRootLower(bytes memory data, uint256 v) pure returns (int256) { return diffLower({ S: S, rX: rX, rY: rY, L: L, v: v, params: params }); } -function findRootRaise(bytes memory data, uint256 v) pure returns (int256) { +function findRootRaise(bytes memory data, uint256 v) view returns (int256) { ( uint256 S, uint256 rX, @@ -175,6 +175,80 @@ function findRootRaise(bytes memory data, uint256 v) pure returns (int256) { return diffRaise({ S: S, rX: rX, rY: rY, L: L, v: v, params: params }); } +struct DiffLowerStruct { + uint256 wX; + uint256 rX; + uint256 rY; + uint256 L; + uint256 v; + uint256 yOverXPowWx; + uint256 yOverXPowWy; + uint256 gamma; +} + +function computeDiffLowerNumerator(DiffLowerStruct memory params) + view + returns (uint256) +{ + uint256 first = params.L.mulWadDown(params.wX).mulWadDown(params.rX) + .mulWadDown(params.yOverXPowWx); + uint256 second = (params.v - params.v.mulWadDown(params.wX) + params.rX) + .mulWadDown(params.rY).mulWadDown(ONE - params.gamma); + uint256 third = + uint256(int256(params.v + params.rX).powWad(-int256(params.wX))); + uint256 fourth = params.L + + params.v.mulWadDown(params.yOverXPowWy).mulWadDown(ONE - params.gamma); + return (first - second).mulWadDown( + uint256( + int256(third.mulWadDown(fourth)).powWad( + int256(ONE.divWadDown(ONE - params.wX)) + ) + ) + ); +} + +function computeDiffLowerDenominator(DiffLowerStruct memory params) + view + returns (uint256) +{ + uint256 dFirst = ONE - params.wX; + uint256 dSecond = params.v + params.rX; + uint256 dThird = + params.L.mulWadDown(params.rX).mulWadDown(uint256(params.yOverXPowWx)); + uint256 dFourth = + params.v.mulWadDown(params.rY).mulWadDown(ONE - params.gamma); + return dFirst.mulWadDown(dSecond).mulWadDown(dThird + dFourth); +} + +function computeDiffLowerResult( + uint256 wX, + uint256 wY, + uint256 rX, + uint256 rY, + uint256 S, + uint256 L, + uint256 v, + uint256 gamma +) view returns (int256) { + int256 yOverX = int256(rY.divWadDown(rX)); + + DiffLowerStruct memory params = DiffLowerStruct({ + wX: wX, + rX: rX, + rY: rY, + L: L, + v: v, + yOverXPowWx: uint256(yOverX.powWad(int256(wX))), + yOverXPowWy: uint256(yOverX.powWad(int256(wY))), + gamma: gamma + }); + + uint256 numerator = computeDiffLowerNumerator(params); + uint256 denominator = computeDiffLowerDenominator(params); + + return -int256(S) + int256(numerator.divWadDown(denominator)); +} + // todo(matt): refactor this to only use int256 function diffLower( uint256 S, @@ -183,41 +257,68 @@ function diffLower( uint256 L, uint256 v, GeometricMeanParams memory params -) pure returns (int256) { - (int256 wx, int256 wy) = (int256(params.wX), int256(params.wY)); +) view returns (int256) { uint256 gamma = ONE - params.swapFee; - int256 yOverX = int256(rY.divWadDown(rX)); - uint256 yOverXPowWx = uint256(yOverX.powWad(wx)); - uint256 yOverXPowWy = uint256(yOverX.powWad(wy)); + return computeDiffLowerResult(params.wX, params.wY, rX, rY, S, L, v, gamma); +} - uint256 numerator; - { - uint256 first = - L.mulWadDown(params.wX).mulWadDown(rX).mulWadDown(yOverXPowWx); - uint256 second = (v - v.mulWadDown(params.wX) + rX).mulWadDown(rY) - .mulWadDown(ONE - gamma); - uint256 third = uint256(int256(v + rX).powWad(-wx)); - uint256 fourth = L + v.mulWadDown(yOverXPowWy).mulWadDown(ONE - gamma); - numerator = (first - second).mulWadDown( - uint256( - int256(third.mulWadDown(fourth)).powWad( - int256(ONE.divWadDown(ONE - params.wX)) - ) - ) - ); - } +function computeDiffRaiseNumerator(DiffRaiseStruct memory params) + view + returns (int256) +{ + int256 first = + int256(params.wX).wadMul(int256(params.v) + int256(params.rY)); + int256 third = (params.vPlusYPow.wadMul(params.lMinusVTimesXOverYPowWx)) + .powWad(I_ONE.wadDiv(int256(params.wX))); + int256 fourth = int256(params.L).wadMul(-I_ONE + int256(params.wX)); + int256 fifth = params.xOverYPowWx.wadMul( + int256(params.v).wadMul(int256(params.wX)) + int256(params.rY) + ).wadMul(-I_ONE + params.gamma); + return first.wadMul(params.lMinusVTimesXOverYPowWx) + + int256(params.S).wadMul(third).wadMul(fourth - fifth); +} - uint256 denominator; - { - uint256 dFirst = ONE - params.wX; - uint256 dSecond = v + rX; - uint256 dThird = L.mulWadDown(rX).mulWadDown(uint256(yOverXPowWx)); - uint256 dFourth = v.mulWadDown(rY).mulWadDown(ONE - gamma); - denominator = dFirst.mulWadDown(dSecond).mulWadDown(dThird + dFourth); - } +struct DiffRaiseStruct { + uint256 wX; + uint256 v; + uint256 rY; + int256 lMinusVTimesXOverYPowWx; + int256 vPlusYPow; + uint256 L; + int256 xOverYPowWx; + int256 gamma; + uint256 S; + int256 vTimesXOverYPowWx; +} + +function getDiffRaiseStruct( + uint256 wX, + uint256 rX, + uint256 v, + uint256 rY, + uint256 L, + uint256 S, + uint256 swapFee +) view returns (DiffRaiseStruct memory) { + int256 vPlusYPow = (int256(v) + int256(rY)).powWad(-I_ONE + int256(wX)); + int256 xOverYPowWx = (int256(rX).wadDiv(int256(rY))).powWad(int256(wX)); + int256 vTimesXOverYPowWx = int256(v).wadMul(xOverYPowWx); + int256 gamma = I_ONE - int256(swapFee); + int256 lMinusVTimesXOverYPowWx = + int256(L) - vTimesXOverYPowWx.wadMul(-I_ONE + gamma); - int256 result = -int256(S) + int256(numerator.divWadDown(denominator)); - return result; + return DiffRaiseStruct({ + wX: wX, + v: v, + rY: rY, + lMinusVTimesXOverYPowWx: lMinusVTimesXOverYPowWx, + vPlusYPow: vPlusYPow, + L: L, + xOverYPowWx: xOverYPowWx, + gamma: gamma, + S: S, + vTimesXOverYPowWx: vTimesXOverYPowWx + }); } function diffRaise( @@ -227,41 +328,19 @@ function diffRaise( uint256 L, uint256 v, GeometricMeanParams memory params -) pure returns (int256) { - (int256 wx, int256 wy, int256 swapFee) = - (int256(params.wX), int256(params.wY), int256(params.swapFee)); - int256 I_ONE = int256(ONE); - int256 iS = int256(S); - int256 iX = int256(rX); - int256 iY = int256(rY); - int256 iL = int256(L); - int256 iV = int256(v); - int256 gamma = I_ONE - swapFee; - - int256 vPlusYPow = (iV + iY).powWad(-I_ONE + wx); - - int256 xOverYPowWx = (iX.wadDiv(iY)).powWad(wx); - int256 vTimesXOverYPowWx = iV.wadMul(xOverYPowWx); - int256 lMinusVTimesXOverYPowWx = - iL - vTimesXOverYPowWx.wadMul(-I_ONE + gamma); +) view returns (int256) { + DiffRaiseStruct memory diffRaiseParams = + getDiffRaiseStruct(params.wX, rX, v, rY, L, S, params.swapFee); - int256 numerator; - { - int256 first = wx.wadMul(iV + iY); - int256 second = lMinusVTimesXOverYPowWx; - int256 third = - (vPlusYPow.wadMul(lMinusVTimesXOverYPowWx)).powWad(I_ONE.wadDiv(wx)); - int256 fourth = iL.wadMul(-I_ONE + wx); - int256 fifth = - xOverYPowWx.wadMul(iV.wadMul(wx) + iY).wadMul(-I_ONE + gamma); - numerator = - first.wadMul(second) + iS.wadMul(third).wadMul(fourth - fifth); - } + int256 numerator = computeDiffRaiseNumerator(diffRaiseParams); int256 denominator; { - int256 first = wx.wadMul(iV + iY); - int256 second = -iL + vTimesXOverYPowWx.wadMul(-I_ONE + gamma); + int256 first = int256(params.wX).wadMul(int256(v) + int256(rY)); + int256 second = -int256(L) + + diffRaiseParams.vTimesXOverYPowWx.wadMul( + -I_ONE + diffRaiseParams.gamma + ); denominator = first.wadMul(second); } @@ -275,7 +354,7 @@ function computeOptimalLower( uint256 L, uint256 vUpper, GeometricMeanParams memory params -) pure returns (uint256 v) { +) view returns (uint256 v) { uint256 upper = vUpper; uint256 lower = 1000; int256 lowerBoundOutput = diffLower(S, rX, rY, L, lower, params); @@ -299,7 +378,7 @@ function computeOptimalRaise( uint256 L, uint256 vUpper, GeometricMeanParams memory params -) pure returns (uint256 v) { +) view returns (uint256 v) { uint256 upper = vUpper; uint256 lower = 1000; int256 lowerBoundOutput = diffRaise(S, rX, rY, L, lower, params); @@ -322,7 +401,7 @@ function computeNextLiquidity( int256 invariant, uint256 approximatedL, GeometricMeanParams memory params -) pure returns (uint256 L) { +) view returns (uint256 L) { uint256 upper = approximatedL; uint256 lower = approximatedL; int256 computedInvariant = invariant; diff --git a/src/GeometricMean/GeometricMean.sol b/src/GeometricMean/GeometricMean.sol index 38e2423b..3414f85e 100644 --- a/src/GeometricMean/GeometricMean.sol +++ b/src/GeometricMean/GeometricMean.sol @@ -178,6 +178,7 @@ contract GeometricMean is IStrategy { revert("invalid swap: inputs x and y have the same sign!"); } + /* liquidityDelta = int256(nextL) - int256( GeometricMeanLib.computeNextLiquidity( @@ -186,6 +187,7 @@ contract GeometricMean is IStrategy { abi.decode(getPoolParams(poolId), (GeometricMeanParams)) ) ); + */ invariant = GeometricMeanLib.tradingFunction(nextRx, nextRy, nextL, params); diff --git a/src/GeometricMean/GeometricMeanSolver.sol b/src/GeometricMean/GeometricMeanSolver.sol index fe2a9c9f..988a3549 100644 --- a/src/GeometricMean/GeometricMeanSolver.sol +++ b/src/GeometricMean/GeometricMeanSolver.sol @@ -69,7 +69,7 @@ contract GeometricMeanSolver { uint256 rx, uint256 S, GeometricMeanParams memory params - ) public pure returns (bytes memory) { + ) public view returns (bytes memory) { return computeInitialPoolData(rx, S, params); } diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 883bdba3..77f8ec59 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -8,6 +8,7 @@ import "./LogNormalLib.sol"; import "./LogNormal.sol"; import "solmate/tokens/ERC20.sol"; import "solstat/Gaussian.sol"; +import "forge-std/console2.sol"; using FixedPointMathLib for uint256; using FixedPointMathLib for int256; @@ -24,7 +25,7 @@ function computeLGivenX( uint256 rx, uint256 S, LogNormal.LogNormalParams memory params -) pure returns (uint256 L) { +) view returns (uint256 L) { int256 d1 = computeD1({ S: S, params: params }); int256 cdf = Gaussian.cdf(d1); uint256 unsignedCdf = LogNormalLib.toUint(cdf); @@ -38,7 +39,7 @@ function computeYGivenL( uint256 L, uint256 S, LogNormal.LogNormalParams memory params -) pure returns (uint256 ry) { +) view returns (uint256 ry) { int256 d2 = computeD2(S, params); int256 cdf = Gaussian.cdf(d2); uint256 unsignedCdf = LogNormalLib.toUint(cdf); @@ -52,7 +53,7 @@ function computeXGivenL( uint256 L, uint256 S, LogNormal.LogNormalParams memory params -) pure returns (uint256 rx) { +) view returns (uint256 rx) { int256 d1 = computeD1(S, params); int256 cdf = Gaussian.cdf(d1); uint256 unsignedCdf = LogNormalLib.toUint(cdf); @@ -66,7 +67,7 @@ function computeXGivenL( function computeD1( uint256 S, LogNormal.LogNormalParams memory params -) pure returns (int256 d1) { +) view returns (int256 d1) { (uint256 K, uint256 sigma, uint256 tau) = (params.strike, params.sigma, params.tau); uint256 sigmaSqrtTau = computeSigmaSqrtTau(sigma, tau); @@ -83,7 +84,7 @@ function computeD1( function computeD2( uint256 S, LogNormal.LogNormalParams memory params -) pure returns (int256 d2) { +) view returns (int256 d2) { (uint256 K, uint256 sigma, uint256 tau) = (params.strike, params.sigma, params.tau); uint256 sigmaSqrtTau = computeSigmaSqrtTau(sigma, tau); @@ -93,33 +94,33 @@ function computeD2( d2 = (lnSDivK - int256(halfSigmaPowTwoTau)) * 1e18 / int256(sigmaSqrtTau); } -/// @dev This is a pure anonymous function defined at the file level, which allows +/// @dev This is a view anonymous function defined at the file level, which allows /// it to be passed as an argument to another function. BisectionLib.sol takes this /// function as an argument to find the root of the trading function given the reserveYWad. -function findRootY(bytes memory data, uint256 ry) pure returns (int256) { +function findRootY(bytes memory data, uint256 ry) view returns (int256) { (uint256 rx, uint256 L,, LogNormal.LogNormalParams memory params) = abi.decode(data, (uint256, uint256, int256, LogNormal.LogNormalParams)); return LogNormalLib.tradingFunction({ rx: rx, ry: ry, L: L, params: params }); } -/// @dev This is a pure anonymous function defined at the file level, which allows +/// @dev This is a view anonymous function defined at the file level, which allows /// it to be passed as an argument to another function. BisectionLib.sol takes this /// function as an argument to find the root of the trading function given the reserveXWad. -function findRootX(bytes memory data, uint256 rx) pure returns (int256) { +function findRootX(bytes memory data, uint256 rx) view returns (int256) { (uint256 ry, uint256 L,, LogNormal.LogNormalParams memory params) = abi.decode(data, (uint256, uint256, int256, LogNormal.LogNormalParams)); return LogNormalLib.tradingFunction({ rx: rx, ry: ry, L: L, params: params }); } -/// @dev This is a pure anonymous function defined at the file level, which allows +/// @dev This is a view anonymous function defined at the file level, which allows /// it to be passed as an argument to another function. BisectionLib.sol takes this /// function as an argument to find the root of the trading function given the liquidity. function findRootLiquidity( bytes memory data, uint256 L -) pure returns (int256) { +) view returns (int256) { (uint256 rx, uint256 ry,, LogNormal.LogNormalParams memory params) = abi.decode(data, (uint256, uint256, int256, LogNormal.LogNormalParams)); return @@ -131,7 +132,7 @@ function computeInitialPoolData( uint256 amountX, uint256 initialPrice, LogNormal.LogNormalParams memory params -) pure returns (bytes memory) { +) view returns (bytes memory) { uint256 L = computeLGivenX(amountX, initialPrice, params); uint256 ry = computeYGivenL(L, initialPrice, params); int256 invariant = LogNormalLib.tradingFunction({ @@ -150,7 +151,7 @@ function computeNextLiquidity( int256 invariant, uint256 approximatedL, LogNormal.LogNormalParams memory params -) pure returns (uint256 L) { +) view returns (uint256 L) { uint256 upper = approximatedL; uint256 lower = approximatedL; int256 computedInvariant = invariant; @@ -191,7 +192,7 @@ function computeNextRx( int256 invariant, uint256 approximatedRx, LogNormal.LogNormalParams memory params -) pure returns (uint256 rx) { +) view returns (uint256 rx) { uint256 upper = approximatedRx; uint256 lower = approximatedRx; int256 computedInvariant = invariant; @@ -232,7 +233,7 @@ function computeNextRy( int256 invariant, uint256 approximatedRy, LogNormal.LogNormalParams memory params -) pure returns (uint256 ry) { +) view returns (uint256 ry) { uint256 upper = approximatedRy; uint256 lower = approximatedRy; int256 computedInvariant = invariant; @@ -267,152 +268,226 @@ function computeNextRy( ); } -function findRootLower(bytes memory data, uint256 v) pure returns (int256) { - ( - uint256 S, - uint256 rX, - uint256 rY, - uint256 L, - LogNormal.LogNormalParams memory params - ) = abi.decode( - data, (uint256, uint256, uint256, uint256, LogNormal.LogNormalParams) - ); - return diffLower({ S: S, rX: rX, rY: rY, L: L, v: v, params: params }); +function findRootLower(bytes memory data, uint256 v) view returns (int256) { + (uint256 S, uint256 rX, uint256 L, LogNormal.LogNormalParams memory params) + = abi.decode(data, (uint256, uint256, uint256, LogNormal.LogNormalParams)); + return diffLower({ + S: int256(S), + rX: int256(rX), + L: int256(L), + v: int256(v), + params: params + }); } -function findRootRaise(bytes memory data, uint256 v) pure returns (int256) { - ( - uint256 S, - uint256 rX, - uint256 rY, - uint256 L, - LogNormal.LogNormalParams memory params - ) = abi.decode( - data, (uint256, uint256, uint256, uint256, LogNormal.LogNormalParams) - ); - return diffRaise({ S: S, rX: rX, rY: rY, L: L, v: v, params: params }); +function findRootRaise(bytes memory data, uint256 v) view returns (int256) { + (uint256 S, uint256 rY, uint256 L, LogNormal.LogNormalParams memory params) + = abi.decode(data, (uint256, uint256, uint256, LogNormal.LogNormalParams)); + return diffRaise({ + S: int256(S), + rY: int256(rY), + L: int256(L), + v: int256(v), + params: params + }); } -function diffLower( - uint256 S, - uint256 rX, - uint256 rY, - uint256 L, - uint256 v, +struct DiffLowerStruct { + int256 ierfcResult; + int256 strike; + int256 sigma; + int256 tau; + int256 gamma; + int256 rX; + int256 L; + int256 v; + int256 S; + int256 sqrtTau; + int256 sqrtTwo; +} + +function createDiffLowerStruct( + int256 S, + int256 rx, + int256 L, + int256 gamma, + int256 v, LogNormal.LogNormalParams memory params -) pure returns (int256) { - (int256 strike, int256 sigma, int256 tau, int256 swapFee) = ( - int256(params.strike), - int256(params.sigma), - int256(params.tau), - int256(params.swapFee) - ); +) view returns (DiffLowerStruct memory) { + int256 a = I_TWO.wadMul(v + rx); + int256 b = L + v - v.wadMul(gamma); + int256 ierfcRes = Gaussian.ierfc(a.wadDiv(b)); + int256 sqrtTwo = int256(FixedPointMathLib.sqrt(TWO) * 1e9); int256 sqrtTau = int256(FixedPointMathLib.sqrt(params.tau) * 1e9); - int256 iS = int256(S); - int256 iX = int256(rX); - int256 iL = int256(L); - int256 iV = int256(v); - int256 gamma = I_ONE - swapFee; - - int256 ierfcNum = I_TWO.wadMul(iV + iX); - int256 ierfcDen = iL + iV - iV.wadMul(gamma); - int256 ierfcRes = Gaussian.ierfc(ierfcNum.wadDiv(ierfcDen)); - - int256 a; - { - int256 firstExp = -(sigma.wadMul(sigma).wadMul(tau).wadDiv(I_TWO)); - int256 secondExp = - sqrtTwo.wadMul(sigma).wadMul(sqrtTau).wadMul(ierfcRes); - - int256 first = FixedPointMathLib.expWad(firstExp + secondExp); - int256 second = strike.wadMul(iL + iX.wadMul(-I_ONE + gamma)); - - int256 firstNum = first.wadMul(second); - int256 firstDen = iL + iV - iV.wadMul(gamma); - a = firstNum.wadDiv(firstDen); - } - int256 b; - { - int256 first = I_HALF.wadMul(strike).wadMul(-I_ONE + gamma); - int256 erfcFirst = sigma.wadMul(sqrtTau).wadDiv(sqrtTwo); - int256 erfcSecond = ierfcRes; - b = first.wadMul(Gaussian.erfc(erfcFirst - erfcSecond)); - } + DiffLowerStruct memory ints = DiffLowerStruct({ + ierfcResult: ierfcRes, + strike: int256(params.strike), + sigma: int256(params.sigma), + tau: int256(params.tau), + gamma: gamma, + rX: rx, + L: L, + v: v, + S: S, + sqrtTwo: sqrtTwo, + sqrtTau: sqrtTau + }); - return -iS + a + b; + return ints; } -function diffRaise( - uint256 S, - uint256 rX, - uint256 rY, - uint256 L, - uint256 v, +function computeLowerA(DiffLowerStruct memory params) view returns (int256) { + int256 firstExp = + -(params.sigma.wadMul(params.sigma).wadMul(params.tau).wadDiv(I_TWO)); + int256 secondExp = params.sqrtTwo.wadMul(params.sigma).wadMul( + params.sqrtTau + ).wadMul(params.ierfcResult); + + int256 first = FixedPointMathLib.expWad(firstExp + secondExp); + int256 second = + params.strike.wadMul(params.L + params.rX.wadMul(-I_ONE + params.gamma)); + + int256 firstNum = first.wadMul(second); + int256 firstDen = params.L + params.v - params.v.wadMul(params.gamma); + return firstNum.wadDiv(firstDen); +} + +function computeLowerB(DiffLowerStruct memory params) view returns (int256) { + int256 a = I_HALF.wadMul(params.strike).wadMul(-I_ONE + params.gamma); + int256 b = params.sigma.wadMul(params.sqrtTau).wadDiv(params.sqrtTwo); + return a.wadMul(Gaussian.erfc(b - params.ierfcResult)); +} + +function diffLower( + int256 S, + int256 rX, + int256 L, + int256 v, LogNormal.LogNormalParams memory params -) pure returns (int256) { - (int256 strike, int256 sigma, int256 tau, int256 swapFee) = ( - int256(params.strike), - int256(params.sigma), - int256(params.tau), - int256(params.swapFee) - ); +) view returns (int256) { + int256 gamma = I_ONE - int256(params.swapFee); + DiffLowerStruct memory ints = + createDiffLowerStruct(S, rX, L, gamma, v, params); + int256 a = computeLowerA(ints); + int256 b = computeLowerB(ints); + + return -ints.S + a + b; +} + +struct DiffRaiseStruct { + int256 ierfcResult; + int256 strike; + int256 sigma; + int256 tau; + int256 gamma; + int256 rY; + int256 L; + int256 v; + int256 S; + int256 sqrtTwo; + int256 sqrtTau; +} + +function createDiffRaiseStruct( + int256 S, + int256 ry, + int256 L, + int256 gamma, + int256 v, + LogNormal.LogNormalParams memory params +) view returns (DiffRaiseStruct memory) { + int256 a = I_TWO.wadMul(v + ry); + int256 b = int256(params.strike).wadMul(L) + v - v.wadMul(gamma); + int256 intermediate = a.wadDiv(b); + console2.log(intermediate); + int256 ierfcRes = Gaussian.ierfc(a.wadDiv(b)); + console2.log(ierfcRes); + int256 sqrtTwo = int256(FixedPointMathLib.sqrt(TWO) * 1e9); int256 sqrtTau = int256(FixedPointMathLib.sqrt(params.tau) * 1e9); - int256 iS = int256(S); - int256 iY = int256(rY); - int256 iL = int256(L); - int256 iV = int256(v); - int256 gamma = I_ONE - swapFee; - - int256 ierfcNum = I_TWO.wadMul(iV + iY); - int256 ierfcDen = strike.wadMul(iL) + iV - iV.wadMul(gamma); - int256 ierfcRes = Gaussian.ierfc(ierfcNum.wadDiv(ierfcDen)); - - int256 a; - { - int256 firstExp = -(sigma.wadMul(sigma).wadMul(tau).wadDiv(I_TWO)); - int256 secondExp = - sqrtTwo.wadMul(sigma).wadMul(sqrtTau).wadMul(ierfcRes); - int256 first = FixedPointMathLib.expWad(firstExp + secondExp); - int256 second = iS.wadMul(strike.wadMul(iL) + iY.wadMul(-I_ONE + gamma)); - - int256 num = first.wadMul(second); - int256 den = strike.wadMul(strike.wadMul(iL) + iV - iV.wadMul(gamma)); - a = num.wadDiv(den); - } - int256 b; - { - int256 first = iS.wadMul(-I_ONE + gamma); - int256 erfcFirst = sigma.wadMul(sqrtTau).wadDiv(sqrtTwo); - int256 erfcSecond = ierfcRes; - int256 num = first.wadMul(Gaussian.erfc(erfcFirst - erfcSecond)); - int256 den = I_TWO.wadMul(strike); + DiffRaiseStruct memory ints = DiffRaiseStruct({ + ierfcResult: ierfcRes, + strike: int256(params.strike), + sigma: int256(params.sigma), + tau: int256(params.tau), + gamma: gamma, + rY: ry, + L: L, + S: S, + v: v, + sqrtTwo: sqrtTwo, + sqrtTau: sqrtTau + }); - b = num.wadDiv(den); - } + return ints; +} + +function computeRaiseA(DiffRaiseStruct memory params) view returns (int256) { + int256 firstExp = + -(params.sigma.wadMul(params.sigma).wadMul(params.tau).wadDiv(I_TWO)); + int256 secondExp = params.sqrtTwo.wadMul(params.sigma).wadMul( + params.sqrtTau + ).wadMul(params.ierfcResult); + int256 first = FixedPointMathLib.expWad(firstExp + secondExp); + console2.log(first); + int256 second = params.S.wadMul( + params.strike.wadMul(params.L) + params.rY.wadMul(-I_ONE + params.gamma) + ); + + int256 num = first.wadMul(second); + int256 den = params.strike.wadMul( + params.strike.wadMul(params.L) + params.v + - params.v.wadMul(params.gamma) + ); + console2.log(den); + return num.wadDiv(den); +} + +function computeRaiseB(DiffRaiseStruct memory params) view returns (int256) { + int256 first = params.S.wadMul(-I_ONE + params.gamma); + int256 erfcFirst = + params.sigma.wadMul(params.sqrtTau).wadDiv(params.sqrtTwo); + int256 num = first.wadMul(Gaussian.erfc(erfcFirst - params.ierfcResult)); + int256 den = I_TWO.wadMul(params.strike); + return num.wadDiv(den); +} + +function diffRaise( + int256 S, + int256 rY, + int256 L, + int256 v, + LogNormal.LogNormalParams memory params +) view returns (int256) { + int256 gamma = I_ONE - int256(params.swapFee); + console2.log("got here"); + DiffRaiseStruct memory ints = + createDiffRaiseStruct(S, rY, L, gamma, v, params); + console2.log("got here"); + int256 a = computeRaiseA(ints); + int256 b = computeRaiseB(ints); return -I_ONE + a + b; } function computeOptimalLower( - uint256 S, - uint256 rX, - uint256 rY, - uint256 L, + int256 S, + int256 rX, + int256 L, uint256 vUpper, LogNormal.LogNormalParams memory params -) pure returns (uint256 v) { +) view returns (uint256 v) { uint256 upper = vUpper; uint256 lower = 1000; - int256 lowerBoundOutput = diffLower(S, rX, rY, L, lower, params); + int256 lowerBoundOutput = diffLower(S, rX, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; } v = bisection( - abi.encode(S, rX, rY, L, params), + abi.encode(S, rX, L, params), lower, upper, uint256(1), @@ -422,21 +497,20 @@ function computeOptimalLower( } function computeOptimalRaise( - uint256 S, - uint256 rX, - uint256 rY, - uint256 L, + int256 S, + int256 rY, + int256 L, uint256 vUpper, LogNormal.LogNormalParams memory params -) pure returns (uint256 v) { +) view returns (uint256 v) { uint256 upper = vUpper; uint256 lower = 1000; - int256 lowerBoundOutput = diffRaise(S, rX, rY, L, lower, params); + int256 lowerBoundOutput = diffRaise(S, rY, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; } v = bisection( - abi.encode(S, rX, rY, L, params), + abi.encode(S, rY, L, params), lower, upper, uint256(1), @@ -444,3 +518,4 @@ function computeOptimalRaise( findRootRaise ); } + diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 482c8370..fa19b816 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -88,7 +88,7 @@ contract LogNormalSolver { uint256 rx, uint256 S, LogNormal.LogNormalParams memory params - ) public pure returns (bytes memory) { + ) public view returns (bytes memory) { return computeInitialPoolData(rx, S, params); } @@ -291,8 +291,8 @@ contract LogNormalSolver { uint256 v ) public view returns (int256) { LogNormal.LogNormalParams memory params = fetchPoolParams(poolId); - (uint256 rx, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); - return diffLower(S, rx, ry, L, v, params); + (uint256 rx,, uint256 L) = getReservesAndLiquidity(poolId); + return diffLower(int256(S), int256(rx), int256(L), int256(v), params); } function calculateDiffRaise( @@ -301,8 +301,8 @@ contract LogNormalSolver { uint256 v ) public view returns (int256) { LogNormal.LogNormalParams memory params = fetchPoolParams(poolId); - (uint256 rx, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); - return diffRaise(S, rx, ry, L, v, params); + (, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); + return diffRaise(int256(S), int256(ry), int256(L), int256(v), params); } function computeOptimalArbLowerPrice( @@ -311,8 +311,8 @@ contract LogNormalSolver { uint256 vUpper ) public view returns (uint256) { LogNormal.LogNormalParams memory params = fetchPoolParams(poolId); - (uint256 rx, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); - return computeOptimalLower(S, rx, ry, L, vUpper, params); + (uint256 rx,, uint256 L) = getReservesAndLiquidity(poolId); + return computeOptimalLower(int256(S), int256(rx), int256(L), vUpper, params); } function computeOptimalArbRaisePrice( @@ -321,7 +321,7 @@ contract LogNormalSolver { uint256 vUpper ) public view returns (uint256) { LogNormal.LogNormalParams memory params = fetchPoolParams(poolId); - (uint256 rx, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); - return computeOptimalRaise(S, rx, ry, L, vUpper, params); + (, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); + return computeOptimalRaise(int256(S), int256(ry), int256(L), vUpper, params); } } diff --git a/src/lib/BisectionLib.sol b/src/lib/BisectionLib.sol index fec3c7fc..8289aa8f 100644 --- a/src/lib/BisectionLib.sol +++ b/src/lib/BisectionLib.sol @@ -28,8 +28,8 @@ function bisection( uint256 upper, uint256 epsilon, uint256 maxIterations, - function (bytes memory,uint256) pure returns (int256) fx -) pure returns (uint256 root) { + function (bytes memory,uint256) view returns (int256) fx +) view returns (uint256 root) { 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. diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index d9394234..d58602ae 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -94,18 +94,18 @@ contract LogNormalTest is Test { _; } - modifier revert_scenario() { + modifier oob_scenario() { vm.warp(0); LogNormal.LogNormalParams memory params = LogNormal.LogNormalParams({ - strike: 0.67323818941934077 ether, - sigma: ONE, + strike: ONE, + sigma: 100_000_000_000_000, tau: ONE, - swapFee: TEST_SWAP_FEE, + swapFee: 10000000000000, controller: address(0) }); - uint256 init_p = 1_329_956_352_651_532_999; - uint256 init_x = 70.658087306013359413 ether; + uint256 init_p = 1 ether; + uint256 init_x = 100 ether; bytes memory initData = solver.getInitialPoolData(init_x, init_p, params); @@ -149,6 +149,30 @@ contract LogNormalTest is Test { assertApproxEqAbs(priceGivenY, priceGivenX, 100); } + function test_oob_diff_raise() public oob_scenario { + uint256 poolId = dfmm.nonce() - 1; + int256 diffRaised = solver.calculateDiffRaise( + poolId, 868046956976567012, 868046956976577012 + ); + + console2.log(diffRaised); + } + + function test_bisect_oob_error() public oob_scenario { + bool xIn = true; + uint256 poolId = dfmm.nonce() - 1; + uint256 amountIn = 97506664135616951612; + (,,, bytes memory swapData) = solver.simulateSwap(poolId, xIn, amountIn); + + dfmm.swap(poolId, swapData); + + (uint256 rx, uint256 ry, uint256 L) = solver.getReservesAndLiquidity(poolId); + console2.log(rx); + console2.log(ry); + uint256 internalPrice = solver.internalPrice(poolId); + console2.log(internalPrice); + } + function test_ln_diff_lower() public basic { uint256 poolId = dfmm.nonce() - 1; int256 diffLowered = solver.calculateDiffLower( From 785ab6070ee930bd3535e0d902e7e52380fd0622 Mon Sep 17 00:00:00 2001 From: kinrezc Date: Mon, 4 Mar 2024 14:50:22 -0500 Subject: [PATCH 09/37] add dy/dx given S helpers --- src/LogNormal/LogNormalExtendedLib.sol | 92 ++++++++++++++++++++++++-- src/LogNormal/LogNormalSolver.sol | 18 +++++ src/test/LogNormal/LogNormalTest.t.sol | 14 ++++ 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 77f8ec59..18db02e1 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -432,7 +432,6 @@ function computeRaiseA(DiffRaiseStruct memory params) view returns (int256) { params.sqrtTau ).wadMul(params.ierfcResult); int256 first = FixedPointMathLib.expWad(firstExp + secondExp); - console2.log(first); int256 second = params.S.wadMul( params.strike.wadMul(params.L) + params.rY.wadMul(-I_ONE + params.gamma) ); @@ -442,7 +441,6 @@ function computeRaiseA(DiffRaiseStruct memory params) view returns (int256) { params.strike.wadMul(params.L) + params.v - params.v.wadMul(params.gamma) ); - console2.log(den); return num.wadDiv(den); } @@ -463,10 +461,8 @@ function diffRaise( LogNormal.LogNormalParams memory params ) view returns (int256) { int256 gamma = I_ONE - int256(params.swapFee); - console2.log("got here"); DiffRaiseStruct memory ints = createDiffRaiseStruct(S, rY, L, gamma, v, params); - console2.log("got here"); int256 a = computeRaiseA(ints); int256 b = computeRaiseB(ints); @@ -518,4 +514,92 @@ function computeOptimalRaise( findRootRaise ); } +/* + +struct DyStruct { + int256 strike; + int256 sigma; + int256 tau; + int256 gamma; + int256 rY; + int256 L; + int256 S; +} + +function createDyStruct(int256 S, int256 rY, int256 L, LogNormal.LogNormalParams memory params) view returns (DyStruct memory dyStruct) { + dyStruct = DyStruct({ + S: S, + rY: rY, + L: L, + strike: int256(params.strike), + sigma: int256(params.sigma), + tau: int256(params.tau), + gamma: I_ONE - int256(params.swapFee) + }); +} + +function deltaCdf(int256 S, int256 strike, int256 sigma) view returns (int256) { + int256 lnSDivK = computeLnSDivK(uint256(S), uint256(strike)); + int256 halfSigmaSquared = sigma.wadMul(sigma).wadDiv(I_TWO); + + return Gaussian.cdf((lnSDivK - halfSigmaSquared).wadDiv(sigma)); +} + +function computeDyNumerator(DyStruct memory dyStruct) view returns (int256) { + int256 a = dyStruct.strike.wadMul(dyStruct.L); + int256 b = deltaCdf(dyStruct.S, dyStruct.strike, dyStruct.sigma); + + return a.wadMul(b) - dyStruct.rY; +} + +function computeDyDen(DyStruct memory dyStruct) view returns (int256) { + int256 a = I_ONE + (dyStruct.gamma - I_ONE); + int256 lnSDivK = computeLnSDivK(uint256(dyStruct.S), uint256(dyStruct.strike)); + int256 halfSigmaSquared = dyStruct.sigma.wadMul(dyStruct.sigma).wadDiv(I_TWO); + +} + + +function computeDyGivenTargetS( + int256 S, + int256 rY, + int256 L, + LogNormal.LogNormalParams memory params +) view returns (int256 dy) { + DyStruct memory dyStruct = createDyStruct(S, rY, L, params); + + int256 num = computeDyNumerator(dyStruct); + + + +} +*/ + +function computeDy(int256 S, int256 rY, int256 L, LogNormal.LogNormalParams memory params) view returns (int256 dy) { + int256 gamma = I_ONE - int256(params.swapFee); + int256 strike = int256(params.strike); + int256 sigma = int256(params.sigma); + + int256 lnSDivK = computeLnSDivK(uint256(S), params.strike); + int256 a = lnSDivK.wadDiv(sigma) - sigma.wadDiv(I_TWO); + int256 cdfA = Gaussian.cdf(a); + + int256 delta = L.wadMul(strike).wadMul(cdfA); + + dy = (delta - rY).wadDiv((gamma - I_ONE).wadMul(cdfA).wadDiv(rY.wadDiv(strike.wadMul(L))) + I_ONE); +} + +function computeDx(int256 S, int256 rX, int256 L, LogNormal.LogNormalParams memory params) view returns (int256 dx) { + int256 gamma = I_ONE - int256(params.swapFee); + int256 sigma = int256(params.sigma); + // lnSDivK + int256 lnSDivK = computeLnSDivK(uint256(S), params.strike); + // cdf((lnSDivK / sigma) + (sigma / 2)) + int256 a = Gaussian.cdf(lnSDivK.wadDiv(sigma) + sigma.wadDiv(I_TWO)); + // L * (1 - cdf) + int256 delta = L.wadMul(I_ONE - a); + + dx = (delta - rX).wadDiv((gamma - I_ONE).wadMul(I_ONE - a).wadDiv(rX.wadDiv(L)) + I_ONE); +} + diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index fa19b816..d9986a61 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -324,4 +324,22 @@ contract LogNormalSolver { (, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); return computeOptimalRaise(int256(S), int256(ry), int256(L), vUpper, params); } + + function getDyGivenS( + uint256 poolId, + uint256 S + ) public view returns (int256) { + LogNormal.LogNormalParams memory params = fetchPoolParams(poolId); + (, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); + return computeDy(int256(S), int256(ry), int256(L), params); + } + + function getDxGivenS( + uint256 poolId, + uint256 S + ) public view returns (int256) { + LogNormal.LogNormalParams memory params = fetchPoolParams(poolId); + (uint256 rx,, uint256 L) = getReservesAndLiquidity(poolId); + return computeDx(int256(S), int256(rx), int256(L), params); + } } diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index d58602ae..7baffe0a 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -212,4 +212,18 @@ contract LogNormalTest is Test { function test_atomic_events() public basic { atomic.logData(dfmm.nonce() - 1); } + + function test_compute_dy() public basic { + uint256 poolId = dfmm.nonce() - 1; + int256 dy = solver.getDyGivenS(poolId, 2.1 ether); + + console2.log(dy); + } + + function test_compute_dx() public basic { + uint256 poolId = dfmm.nonce() - 1; + int256 dx = solver.getDxGivenS(poolId, 1.9 ether); + + console2.log(dx); + } } From a6c7c297f45a889c430f4e33ed8b073045533e0f Mon Sep 17 00:00:00 2001 From: kinrezc Date: Mon, 4 Mar 2024 16:15:20 -0500 Subject: [PATCH 10/37] fix lower bound in bisection --- src/LogNormal/LogNormalExtendedLib.sol | 68 ++------------------------ src/test/LogNormal/LogNormalTest.t.sol | 21 ++++++++ 2 files changed, 24 insertions(+), 65 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 18db02e1..8f8dc0e5 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -400,10 +400,7 @@ function createDiffRaiseStruct( ) view returns (DiffRaiseStruct memory) { int256 a = I_TWO.wadMul(v + ry); int256 b = int256(params.strike).wadMul(L) + v - v.wadMul(gamma); - int256 intermediate = a.wadDiv(b); - console2.log(intermediate); int256 ierfcRes = Gaussian.ierfc(a.wadDiv(b)); - console2.log(ierfcRes); int256 sqrtTwo = int256(FixedPointMathLib.sqrt(TWO) * 1e9); int256 sqrtTau = int256(FixedPointMathLib.sqrt(params.tau) * 1e9); @@ -477,7 +474,7 @@ function computeOptimalLower( LogNormal.LogNormalParams memory params ) view returns (uint256 v) { uint256 upper = vUpper; - uint256 lower = 1000; + uint256 lower = 1; int256 lowerBoundOutput = diffLower(S, rX, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; @@ -500,7 +497,7 @@ function computeOptimalRaise( LogNormal.LogNormalParams memory params ) view returns (uint256 v) { uint256 upper = vUpper; - uint256 lower = 1000; + uint256 lower = 1; int256 lowerBoundOutput = diffRaise(S, rY, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; @@ -514,66 +511,6 @@ function computeOptimalRaise( findRootRaise ); } -/* - -struct DyStruct { - int256 strike; - int256 sigma; - int256 tau; - int256 gamma; - int256 rY; - int256 L; - int256 S; -} - -function createDyStruct(int256 S, int256 rY, int256 L, LogNormal.LogNormalParams memory params) view returns (DyStruct memory dyStruct) { - dyStruct = DyStruct({ - S: S, - rY: rY, - L: L, - strike: int256(params.strike), - sigma: int256(params.sigma), - tau: int256(params.tau), - gamma: I_ONE - int256(params.swapFee) - }); -} - -function deltaCdf(int256 S, int256 strike, int256 sigma) view returns (int256) { - int256 lnSDivK = computeLnSDivK(uint256(S), uint256(strike)); - int256 halfSigmaSquared = sigma.wadMul(sigma).wadDiv(I_TWO); - - return Gaussian.cdf((lnSDivK - halfSigmaSquared).wadDiv(sigma)); -} - -function computeDyNumerator(DyStruct memory dyStruct) view returns (int256) { - int256 a = dyStruct.strike.wadMul(dyStruct.L); - int256 b = deltaCdf(dyStruct.S, dyStruct.strike, dyStruct.sigma); - - return a.wadMul(b) - dyStruct.rY; -} - -function computeDyDen(DyStruct memory dyStruct) view returns (int256) { - int256 a = I_ONE + (dyStruct.gamma - I_ONE); - int256 lnSDivK = computeLnSDivK(uint256(dyStruct.S), uint256(dyStruct.strike)); - int256 halfSigmaSquared = dyStruct.sigma.wadMul(dyStruct.sigma).wadDiv(I_TWO); - -} - - -function computeDyGivenTargetS( - int256 S, - int256 rY, - int256 L, - LogNormal.LogNormalParams memory params -) view returns (int256 dy) { - DyStruct memory dyStruct = createDyStruct(S, rY, L, params); - - int256 num = computeDyNumerator(dyStruct); - - - -} -*/ function computeDy(int256 S, int256 rY, int256 L, LogNormal.LogNormalParams memory params) view returns (int256 dy) { int256 gamma = I_ONE - int256(params.swapFee); @@ -603,3 +540,4 @@ function computeDx(int256 S, int256 rX, int256 L, LogNormal.LogNormalParams memo } + diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index 7baffe0a..335e4e56 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -213,6 +213,27 @@ contract LogNormalTest is Test { atomic.logData(dfmm.nonce() - 1); } + function test_complete_arb_flow_dy() public basic { + uint256 poolId = dfmm.nonce() - 1; + uint256 S = 2.1 ether; + int256 dy = solver.getDyGivenS(poolId, S); + + uint256 optimalRaise = solver.computeOptimalArbRaisePrice(poolId, S, uint256(dy)); + + console2.log(optimalRaise); + } + + function test_complete_arb_flow_dx() public basic { + uint256 poolId = dfmm.nonce() - 1; + uint256 S = 1.9 ether; + int256 dx = solver.getDxGivenS(poolId, S); + + uint256 optimalLower = solver.computeOptimalArbLowerPrice(poolId, S, uint256(dx)); + + console2.log(optimalLower); + } + + function test_compute_dy() public basic { uint256 poolId = dfmm.nonce() - 1; int256 dy = solver.getDyGivenS(poolId, 2.1 ether); From 7baddb5a5cab9c1c85a234cda502a02e4aadd423 Mon Sep 17 00:00:00 2001 From: kinrezc Date: Mon, 4 Mar 2024 18:41:26 -0500 Subject: [PATCH 11/37] testing new bounds --- src/LogNormal/LogNormalExtendedLib.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 8f8dc0e5..673c5739 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -474,7 +474,7 @@ function computeOptimalLower( LogNormal.LogNormalParams memory params ) view returns (uint256 v) { uint256 upper = vUpper; - uint256 lower = 1; + uint256 lower = 100; int256 lowerBoundOutput = diffLower(S, rX, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; @@ -497,7 +497,7 @@ function computeOptimalRaise( LogNormal.LogNormalParams memory params ) view returns (uint256 v) { uint256 upper = vUpper; - uint256 lower = 1; + uint256 lower = 100; int256 lowerBoundOutput = diffRaise(S, rY, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; From a814f897aeab3d7f649b10873da9209477001efa Mon Sep 17 00:00:00 2001 From: kinrezc Date: Mon, 4 Mar 2024 18:45:29 -0500 Subject: [PATCH 12/37] set lower back to 1000 wei --- src/LogNormal/LogNormalExtendedLib.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 673c5739..4e4e818c 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -474,7 +474,7 @@ function computeOptimalLower( LogNormal.LogNormalParams memory params ) view returns (uint256 v) { uint256 upper = vUpper; - uint256 lower = 100; + uint256 lower = 1000; int256 lowerBoundOutput = diffLower(S, rX, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; @@ -497,7 +497,7 @@ function computeOptimalRaise( LogNormal.LogNormalParams memory params ) view returns (uint256 v) { uint256 upper = vUpper; - uint256 lower = 100; + uint256 lower = 1000; int256 lowerBoundOutput = diffRaise(S, rY, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; From 81aed61c842055a2d6f7e5429dba4e09ec175bf1 Mon Sep 17 00:00:00 2001 From: kinrezc Date: Mon, 4 Mar 2024 18:56:25 -0500 Subject: [PATCH 13/37] set lower back to 1 wei --- src/LogNormal/LogNormalExtendedLib.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 4e4e818c..8f8dc0e5 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -474,7 +474,7 @@ function computeOptimalLower( LogNormal.LogNormalParams memory params ) view returns (uint256 v) { uint256 upper = vUpper; - uint256 lower = 1000; + uint256 lower = 1; int256 lowerBoundOutput = diffLower(S, rX, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; @@ -497,7 +497,7 @@ function computeOptimalRaise( LogNormal.LogNormalParams memory params ) view returns (uint256 v) { uint256 upper = vUpper; - uint256 lower = 1000; + uint256 lower = 1; int256 lowerBoundOutput = diffRaise(S, rY, L, int256(lower), params); if (lowerBoundOutput < 0) { return 0; From 71c0ce25d5628732493ae74ce8568beea576f35d Mon Sep 17 00:00:00 2001 From: kinrezc Date: Mon, 4 Mar 2024 20:05:05 -0500 Subject: [PATCH 14/37] adjusted fee logic for lognormal --- src/LogNormal/LogNormal.sol | 4 +- src/LogNormal/LogNormalSolver.sol | 17 ++++---- src/test/LogNormal/LogNormalTest.t.sol | 57 +++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/LogNormal/LogNormal.sol b/src/LogNormal/LogNormal.sol index 836a977d..208e035d 100644 --- a/src/LogNormal/LogNormal.sol +++ b/src/LogNormal/LogNormal.sol @@ -172,12 +172,12 @@ contract LogNormal is IStrategy { if (nextRx > startRx) { amountIn = nextRx - startRx; fees = amountIn.mulWadUp(params.swapFee); - minLiquidityDelta += fees.mulWadUp(startL).divWadUp(startRx); + minLiquidityDelta += fees.mulWadUp(startL).divWadUp(startRx).mulWadUp(0.5 ether); } else if (nextRy > startRy) { // δl = δx * L / X, where δx = delta x * fee amountIn = nextRy - startRy; fees = amountIn.mulWadUp(params.swapFee); - minLiquidityDelta += fees.mulWadUp(startL).divWadUp(startRy); + minLiquidityDelta += fees.mulWadUp(startL).divWadUp(startRy).mulWadUp(0.5 ether); } else { // should never get here! revert("invalid swap: inputs x and y have the same sign!"); diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index d9986a61..edd3873a 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -17,6 +17,7 @@ contract LogNormalSolver { uint256 rx; uint256 ry; uint256 L; + uint256 approxPrice; } uint256 public constant BISECTION_EPSILON = 0; @@ -203,17 +204,16 @@ contract LogNormalSolver { ); if (swapXIn) { - uint256 deltaL = amountIn.mulWadUp(poolParams.swapFee); + uint256 deltaL = amountIn.mulWadUp(poolParams.swapFee).mulWadUp(startReserves.L).divWadUp(startReserves.rx).mulWadUp(0.5 ether); endReserves.rx = startReserves.rx + amountIn; endReserves.L = startComputedL + deltaL; - uint256 approxPrice = + endReserves.approxPrice = getPriceGivenXL(poolId, endReserves.rx, endReserves.L); endReserves.ry = getNextReserveY( - poolId, endReserves.rx, endReserves.L, approxPrice + poolId, endReserves.rx, endReserves.L, endReserves.approxPrice ); - endReserves.ry += 1; require( endReserves.ry < startReserves.ry, @@ -221,19 +221,16 @@ contract LogNormalSolver { ); amountOut = startReserves.ry - endReserves.ry; } else { - uint256 deltaL = amountIn.mulWadUp(poolParams.swapFee).divWadUp( - poolParams.strike - ); + uint256 deltaL = amountIn.mulWadUp(poolParams.swapFee).mulWadUp(startReserves.L).divWadUp(startReserves.ry).mulWadUp(0.5 ether); endReserves.ry = startReserves.ry + amountIn; endReserves.L = startComputedL + deltaL; - uint256 approxPrice = + endReserves.approxPrice = getPriceGivenYL(poolId, endReserves.ry, endReserves.L); endReserves.rx = getNextReserveX( - poolId, endReserves.ry, endReserves.L, approxPrice + poolId, endReserves.ry, endReserves.L, endReserves.approxPrice ); - endReserves.rx += 1; require( endReserves.rx < startReserves.rx, diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index 335e4e56..29746cc5 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -25,8 +25,8 @@ contract LogNormalTest is Test { function setUp() public { tokenX = address(new MockERC20("tokenX", "X", 18)); tokenY = address(new MockERC20("tokenY", "Y", 18)); - MockERC20(tokenX).mint(address(this), 100_000_000 ether); - MockERC20(tokenY).mint(address(this), 100_000_000 ether); + MockERC20(tokenX).mint(address(this), 100_000_000_000 ether); + MockERC20(tokenY).mint(address(this), 100_000_000_000 ether); lex = new Lex(tokenX, tokenY, ONE); dfmm = new DFMM(address(0)); @@ -94,6 +94,34 @@ contract LogNormalTest is Test { _; } + modifier deep_liq() { + vm.warp(0); + + LogNormal.LogNormalParams memory params = LogNormal.LogNormalParams({ + strike: ONE, + sigma: 0.1 ether, + tau: ONE, + swapFee: TEST_SWAP_FEE, + controller: address(0) + }); + uint256 init_p = 1.1 ether; + uint256 init_x = ONE * 100_000_000; + bytes memory initData = + solver.getInitialPoolData(init_x, init_p, params); + + IDFMM.InitParams memory initParams = IDFMM.InitParams({ + strategy: address(logNormal), + tokenX: tokenX, + tokenY: tokenY, + data: initData + }); + + dfmm.init(initParams); + + _; + } + + modifier oob_scenario() { vm.warp(0); @@ -247,4 +275,29 @@ contract LogNormalTest is Test { console2.log(dx); } + + function test_deep_liq_x_in() public deep_liq { + bool xIn = true; + uint256 amountIn = 1 ether; + uint256 poolId = dfmm.nonce() - 1; + (,,, bytes memory swapData) = solver.simulateSwap(poolId, xIn, amountIn); + + (uint256 input, uint256 output) = dfmm.swap(poolId, swapData); + + console2.log(input); + console2.log(output); + } + + function test_deep_liq_y_in() public deep_liq { + bool xIn = false; + uint256 amountIn = 1 ether; + uint256 poolId = dfmm.nonce() - 1; + (,,, bytes memory swapData) = solver.simulateSwap(poolId, xIn, amountIn); + + (uint256 input, uint256 output) = dfmm.swap(poolId, swapData); + + console2.log(input); + console2.log(output); + } + } From ef7fe5c12b52fa2bb445ed7496d3e2704143ebd3 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:07:27 -0500 Subject: [PATCH 15/37] add console logs --- src/LogNormal/LogNormalExtendedLib.sol | 3 ++ src/LogNormal/LogNormalSolver.sol | 17 ++++++---- src/test/LogNormal/LogNormalTest.t.sol | 44 ++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 8f8dc0e5..70b8ac9c 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -400,7 +400,10 @@ function createDiffRaiseStruct( ) view returns (DiffRaiseStruct memory) { int256 a = I_TWO.wadMul(v + ry); int256 b = int256(params.strike).wadMul(L) + v - v.wadMul(gamma); + int256 intermediate = a.wadDiv(b); + console2.log("intermediate", intermediate); int256 ierfcRes = Gaussian.ierfc(a.wadDiv(b)); + console2.log("ierfc res", ierfcRes); int256 sqrtTwo = int256(FixedPointMathLib.sqrt(TWO) * 1e9); int256 sqrtTau = int256(FixedPointMathLib.sqrt(params.tau) * 1e9); diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index edd3873a..5d0d88fc 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -185,6 +185,15 @@ contract LogNormalSolver { ); } + function computeDeltaL( + uint256 amountIn, + uint256 swapFee, + uint256 L, + uint256 reserve + ) public view returns (uint256 deltaL) { + deltaL = amountIn.mulWadUp(swapFee).mulWadUp(L).divWadUp(reserve).mulWadUp(HALF); + } + /// @dev Estimates a swap's reserves and adjustments and returns its validity. function simulateSwap( uint256 poolId, @@ -204,10 +213,8 @@ contract LogNormalSolver { ); if (swapXIn) { - uint256 deltaL = amountIn.mulWadUp(poolParams.swapFee).mulWadUp(startReserves.L).divWadUp(startReserves.rx).mulWadUp(0.5 ether); - endReserves.rx = startReserves.rx + amountIn; - endReserves.L = startComputedL + deltaL; + endReserves.L = startComputedL + computeDeltaL(amountIn, poolParams.swapFee, startReserves.L, startReserves.rx); endReserves.approxPrice = getPriceGivenXL(poolId, endReserves.rx, endReserves.L); @@ -221,10 +228,8 @@ contract LogNormalSolver { ); amountOut = startReserves.ry - endReserves.ry; } else { - uint256 deltaL = amountIn.mulWadUp(poolParams.swapFee).mulWadUp(startReserves.L).divWadUp(startReserves.ry).mulWadUp(0.5 ether); - endReserves.ry = startReserves.ry + amountIn; - endReserves.L = startComputedL + deltaL; + endReserves.L = startComputedL + computeDeltaL(amountIn, poolParams.swapFee, startReserves.L, startReserves.ry); endReserves.approxPrice = getPriceGivenYL(poolId, endReserves.ry, endReserves.L); diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index 29746cc5..d8359eb0 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -121,6 +121,33 @@ contract LogNormalTest is Test { _; } + modifier infinity_case() { + vm.warp(0); + + LogNormal.LogNormalParams memory params = LogNormal.LogNormalParams({ + strike: ONE, + sigma: 100000000000000, + tau: ONE, + swapFee: 100000000000000, + controller: address(0) + }); + uint256 init_p = ONE; + uint256 init_x = ONE * 100; + bytes memory initData = + solver.getInitialPoolData(init_x, init_p, params); + + IDFMM.InitParams memory initParams = IDFMM.InitParams({ + strategy: address(logNormal), + tokenX: tokenX, + tokenY: tokenY, + data: initData + }); + + dfmm.init(initParams); + + _; + } + modifier oob_scenario() { vm.warp(0); @@ -300,4 +327,21 @@ contract LogNormalTest is Test { console2.log(output); } + function test_inf_scenario() public infinity_case { + uint256 poolId = dfmm.nonce() - 1; + bool xIn = true; + uint256 amountIn = 93184003566910952224; + (,,, bytes memory swapData) = solver.simulateSwap(poolId, xIn, amountIn); + dfmm.swap(poolId, swapData); + + (uint256 rx, uint256 ry, uint256 L) = solver.getReservesAndLiquidity(poolId); + console2.log(rx); + console2.log(ry); + console2.log(L); + + int256 raise = solver.calculateDiffRaise(poolId, 1000284890278334600, 193204839774776442304); + + console2.log(raise); + } + } From 419a18af4a829f7de69838562e3d11d2402f2eaa Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:28:19 -0500 Subject: [PATCH 16/37] testing rx gt L --- src/LogNormal/LogNormal.sol | 5 ++++- src/LogNormal/LogNormalExtendedLib.sol | 4 ++++ src/LogNormal/LogNormalSolver.sol | 4 ++++ src/test/LogNormal/LogNormalTest.t.sol | 5 +++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/LogNormal/LogNormal.sol b/src/LogNormal/LogNormal.sol index 208e035d..8a5f4f5f 100644 --- a/src/LogNormal/LogNormal.sol +++ b/src/LogNormal/LogNormal.sol @@ -6,6 +6,7 @@ import "src/interfaces/IDFMM.sol"; import "src/interfaces/IStrategy.sol"; import "src/lib/DynamicParamLib.sol"; import "src/lib/StrategyLib.sol"; +import "forge-std/console2.sol" /// @notice Log Normal has three variable parameters: /// K - strike price @@ -184,7 +185,9 @@ contract LogNormal is IStrategy { } liquidityDelta = int256(nextL) - int256(startL); - + console2.log("nextRx", nextRx); + console2.log("nextL", nextL); + console2.log("x gt L", nextRx > nextL); invariant = LogNormalLib.tradingFunction(nextRx, nextRy, nextL, params); valid = -(EPSILON) < invariant && invariant < EPSILON; } diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 70b8ac9c..ce08e510 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -425,6 +425,10 @@ function createDiffRaiseStruct( return ints; } +function testIerfc(int256 x) view returns (int256) { + return Gaussian.ierfc(x); +} + function computeRaiseA(DiffRaiseStruct memory params) view returns (int256) { int256 firstExp = -(params.sigma.wadMul(params.sigma).wadMul(params.tau).wadDiv(I_TWO)); diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 5d0d88fc..6b492d25 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -344,4 +344,8 @@ contract LogNormalSolver { (uint256 rx,, uint256 L) = getReservesAndLiquidity(poolId); return computeDx(int256(S), int256(rx), int256(L), params); } + + function callIerfc(int256 x) public view returns (int256) { + return testIerfc(x); + } } diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index d8359eb0..3bf85370 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -344,4 +344,9 @@ contract LogNormalTest is Test { console2.log(raise); } + function test_ierfc_input() public basic { + int256 res = solver.callIerfc(1999999999999999999); + console2.log(res); + } + } From 16fa4f9004eb33c2694a167dca7604d4a4174f54 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:29:21 -0500 Subject: [PATCH 17/37] testing rx gt L --- src/LogNormal/LogNormal.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LogNormal/LogNormal.sol b/src/LogNormal/LogNormal.sol index 8a5f4f5f..d4783c62 100644 --- a/src/LogNormal/LogNormal.sol +++ b/src/LogNormal/LogNormal.sol @@ -6,7 +6,7 @@ import "src/interfaces/IDFMM.sol"; import "src/interfaces/IStrategy.sol"; import "src/lib/DynamicParamLib.sol"; import "src/lib/StrategyLib.sol"; -import "forge-std/console2.sol" +import "forge-std/console2.sol"; /// @notice Log Normal has three variable parameters: /// K - strike price From 6fd4147e30589ce33015c1d9f3b89d7ee78fa243 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:37:38 -0500 Subject: [PATCH 18/37] logging things --- src/LogNormal/LogNormalSolver.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 6b492d25..346df63b 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -208,9 +208,11 @@ contract LogNormalSolver { uint256 amountOut; { + console2.log("computing next L"); uint256 startComputedL = getNextLiquidity( poolId, startReserves.rx, startReserves.ry, startReserves.L ); + console2.log("computed next L"); if (swapXIn) { endReserves.rx = startReserves.rx + amountIn; @@ -218,9 +220,11 @@ contract LogNormalSolver { endReserves.approxPrice = getPriceGivenXL(poolId, endReserves.rx, endReserves.L); + console2.log("computing next Y"); endReserves.ry = getNextReserveY( poolId, endReserves.rx, endReserves.L, endReserves.approxPrice ); + console2.log("computed next Y"); require( endReserves.ry < startReserves.ry, @@ -233,9 +237,11 @@ contract LogNormalSolver { endReserves.approxPrice = getPriceGivenYL(poolId, endReserves.ry, endReserves.L); + console2.log("computing next X"); endReserves.rx = getNextReserveX( poolId, endReserves.ry, endReserves.L, endReserves.approxPrice ); + console2.log("computed next X"); require( endReserves.rx < startReserves.rx, From 7a056a1a7eb6deb793b682fa61c49faf7d991d9e Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:41:21 -0500 Subject: [PATCH 19/37] wip --- src/LogNormal/LogNormalSolver.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 346df63b..15ffdc00 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -152,6 +152,9 @@ contract LogNormalSolver { uint256 L ) public view returns (uint256) { bytes memory data = abi.encode(rx, ry, L); + console2.log("rx in nextL", rx); + console2.log("L in nextL", L); + int256 invariant = IStrategy(strategy).computeSwapConstant(poolId, data); return computeNextLiquidity(rx, ry, invariant, L, fetchPoolParams(poolId)); From 86fa5e89de306652d03fe628ff59f387815560b4 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:43:37 -0500 Subject: [PATCH 20/37] wip --- src/LogNormal/LogNormalSolver.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 15ffdc00..5ca23bb8 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -212,6 +212,8 @@ contract LogNormalSolver { uint256 amountOut; { console2.log("computing next L"); + console2.log("start rx", startReserves.rx); + console2.log("start L", startReserves.L); uint256 startComputedL = getNextLiquidity( poolId, startReserves.rx, startReserves.ry, startReserves.L ); From cfa0d621101e6e3c6c7b1791f21a7423870611ec Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:45:18 -0500 Subject: [PATCH 21/37] wip --- src/LogNormal/LogNormalSolver.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 5ca23bb8..b39dc9a0 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -211,9 +211,9 @@ contract LogNormalSolver { uint256 amountOut; { - console2.log("computing next L"); console2.log("start rx", startReserves.rx); console2.log("start L", startReserves.L); + console2.log("computing next L"); uint256 startComputedL = getNextLiquidity( poolId, startReserves.rx, startReserves.ry, startReserves.L ); From c16cdf9b010ad7d41a0065e2a8651a0aeaab46a5 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:49:24 -0500 Subject: [PATCH 22/37] log invariant --- src/LogNormal/LogNormalSolver.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index b39dc9a0..510fd5be 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -156,6 +156,7 @@ contract LogNormalSolver { console2.log("L in nextL", L); int256 invariant = IStrategy(strategy).computeSwapConstant(poolId, data); + console2.log("invariant", invariant); return computeNextLiquidity(rx, ry, invariant, L, fetchPoolParams(poolId)); } From a612df5eb958b8dc411b2a9771ebb729c1c86633 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:51:48 -0500 Subject: [PATCH 23/37] use rx as next liquidity lower bound --- src/LogNormal/LogNormalExtendedLib.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index ce08e510..4486c806 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -157,7 +157,7 @@ function computeNextLiquidity( int256 computedInvariant = invariant; if (computedInvariant < 0) { while (computedInvariant < 0) { - lower = lower.mulDivDown(999, 1000); + lower = rx + 1; computedInvariant = LogNormalLib.tradingFunction({ rx: rx, ry: ry, From d3adce9b31f4623e488aa1b25939911fe6a31ca1 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 14:57:24 -0500 Subject: [PATCH 24/37] use rx as next liquidity lower bound --- src/LogNormal/LogNormalExtendedLib.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 4486c806..8be78608 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -157,7 +157,7 @@ function computeNextLiquidity( int256 computedInvariant = invariant; if (computedInvariant < 0) { while (computedInvariant < 0) { - lower = rx + 1; + lower = rx + 1000; computedInvariant = LogNormalLib.tradingFunction({ rx: rx, ry: ry, From 6fe6b3b923c909c93cac81d1cc482c9bb54cade4 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 15:01:26 -0500 Subject: [PATCH 25/37] debugging --- src/LogNormal/LogNormalExtendedLib.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 8be78608..5d3d957f 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -158,6 +158,7 @@ function computeNextLiquidity( if (computedInvariant < 0) { while (computedInvariant < 0) { lower = rx + 1000; + console2.log("rx div L", rx.divWadDown(L)); computedInvariant = LogNormalLib.tradingFunction({ rx: rx, ry: ry, From 087ed9f84c536cb59f15e90edad400ba4e8483de Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 15:02:47 -0500 Subject: [PATCH 26/37] wip --- src/LogNormal/LogNormalExtendedLib.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 5d3d957f..10be0f0b 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -157,8 +157,8 @@ function computeNextLiquidity( int256 computedInvariant = invariant; if (computedInvariant < 0) { while (computedInvariant < 0) { - lower = rx + 1000; - console2.log("rx div L", rx.divWadDown(L)); + lower = rx + 10_000; + console2.log("rx div L", rx.divWadDown(lower)); computedInvariant = LogNormalLib.tradingFunction({ rx: rx, ry: ry, From 1ed6e4f26e0891e64eef4300a7f2462b6e9860c4 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 15:09:24 -0500 Subject: [PATCH 27/37] check computed invariant --- src/LogNormal/LogNormalExtendedLib.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 10be0f0b..ab91ca6c 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -177,6 +177,7 @@ function computeNextLiquidity( }); } } + console2.log("computedInvariant", computedInvariant); L = bisection( abi.encode(rx, ry, computedInvariant, params), lower, From 208133d7daba7936586a5873d045a718a1f99850 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 15:14:15 -0500 Subject: [PATCH 28/37] wip --- src/LogNormal/LogNormalSolver.sol | 38 ++++++++++++++++++++++++++ src/test/LogNormal/LogNormalTest.t.sol | 4 +++ 2 files changed, 42 insertions(+) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 510fd5be..2a5d1ce7 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -213,6 +213,7 @@ contract LogNormalSolver { uint256 amountOut; { console2.log("start rx", startReserves.rx); + console2.log("start ry", startReserves.ry); console2.log("start L", startReserves.L); console2.log("computing next L"); uint256 startComputedL = getNextLiquidity( @@ -360,4 +361,41 @@ contract LogNormalSolver { function callIerfc(int256 x) public view returns (int256) { return testIerfc(x); } + + function solverTradingFunction( + uint256 rx, + uint256 ry, + uint256 L, + LogNormal.LogNormalParams memory params + ) public view returns (int256) { + require(rx < L, "tradingFunction: invalid x"); + + int256 AAAAA; + int256 BBBBB; + if (FixedPointMathLib.divWadDown(rx, L) >= ONE) { + AAAAA = int256(2 ** 255 - 1); + } else { + AAAAA = Gaussian.ppf(int256(FixedPointMathLib.divWadDown(rx, L))); + } + if ( + FixedPointMathLib.divWadDown( + ry, FixedPointMathLib.mulWadDown(params.strike, L) + ) >= ONE + ) { + BBBBB = int256(2 ** 255 - 1); + } else { + BBBBB = Gaussian.ppf( + int256( + FixedPointMathLib.divWadDown( + ry, FixedPointMathLib.mulWadDown(params.strike, L) + ) + ) + ); + } + + int256 CCCCC = int256(computeSigmaSqrtTau(params.sigma, params.tau)); + + return AAAAA + BBBBB + CCCCC; + } + } diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index 3bf85370..8a1ba172 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -349,4 +349,8 @@ contract LogNormalTest is Test { console2.log(res); } + function test_solver_tf() public basic { + + } + } From 23b972ad58e86997cff92546e1218cba78df962b Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 15:35:24 -0500 Subject: [PATCH 29/37] fix lower bound for next liquidity --- src/LogNormal/LogNormalExtendedLib.sol | 2 +- src/LogNormal/LogNormalSolver.sol | 7 +++++ src/test/LogNormal/LogNormalTest.t.sol | 42 +++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index ab91ca6c..eea35bab 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -157,7 +157,7 @@ function computeNextLiquidity( int256 computedInvariant = invariant; if (computedInvariant < 0) { while (computedInvariant < 0) { - lower = rx + 10_000; + lower = rx > ry.divWadDown(params.strike) ? rx + 1000 : ry.divWadDown(params.strike) + 1000; console2.log("rx div L", rx.divWadDown(lower)); computedInvariant = LogNormalLib.tradingFunction({ rx: rx, diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 2a5d1ce7..9b3ee265 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -376,13 +376,16 @@ contract LogNormalSolver { AAAAA = int256(2 ** 255 - 1); } else { AAAAA = Gaussian.ppf(int256(FixedPointMathLib.divWadDown(rx, L))); + console2.log("a", AAAAA); } if ( FixedPointMathLib.divWadDown( ry, FixedPointMathLib.mulWadDown(params.strike, L) ) >= ONE ) { + console2.log("in max int branch"); BBBBB = int256(2 ** 255 - 1); + console2.log("b", BBBBB); } else { BBBBB = Gaussian.ppf( int256( @@ -394,6 +397,10 @@ contract LogNormalSolver { } int256 CCCCC = int256(computeSigmaSqrtTau(params.sigma, params.tau)); + console2.log("c", CCCCC); + + console2.log("a + c", AAAAA + CCCCC); + console2.log("a + b + c", AAAAA + BBBBB + CCCCC); return AAAAA + BBBBB + CCCCC; } diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index 8a1ba172..28717de9 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -11,6 +11,7 @@ import "../helpers/Lex.sol"; contract LogNormalTest is Test { using stdStorage for StdStorage; + using FixedPointMathLib for uint256; DFMM dfmm; LogNormal logNormal; @@ -94,6 +95,34 @@ contract LogNormalTest is Test { _; } + modifier next_L() { + vm.warp(0); + + LogNormal.LogNormalParams memory params = LogNormal.LogNormalParams({ + strike: ONE, + sigma: 0.0001 ether, + tau: ONE, + swapFee: 0.0001 ether, + controller: address(0) + }); + uint256 init_p = ONE; + uint256 init_x = ONE; + bytes memory initData = + solver.getInitialPoolData(init_x, init_p, params); + + IDFMM.InitParams memory initParams = IDFMM.InitParams({ + strategy: address(logNormal), + tokenX: tokenX, + tokenY: tokenY, + data: initData + }); + + dfmm.init(initParams); + + _; + } + + modifier deep_liq() { vm.warp(0); @@ -349,7 +378,18 @@ contract LogNormalTest is Test { console2.log(res); } - function test_solver_tf() public basic { + function test_solver_tf() public next_L { + uint256 rx = 58724093250934788978; + uint256 ry = 141290607496809311119; + //uint256 L = 200021587103761615868; + + LogNormal.LogNormalParams memory params = solver.fetchPoolParams(0); + + uint256 L = rx > ry.divWadDown(params.strike) ? rx + 1000 : ry.divWadDown(params.strike) + 1000; + + solver.solverTradingFunction(rx, ry, L, params); + + } From 03b0fc93e4ad86654a81d4d043dece4664ce5855 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 15:43:46 -0500 Subject: [PATCH 30/37] conditionally use min fallback in computeNextLiquiditY --- src/LogNormal/LogNormalExtendedLib.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index eea35bab..0622971e 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -157,8 +157,9 @@ function computeNextLiquidity( int256 computedInvariant = invariant; if (computedInvariant < 0) { while (computedInvariant < 0) { - lower = rx > ry.divWadDown(params.strike) ? rx + 1000 : ry.divWadDown(params.strike) + 1000; - console2.log("rx div L", rx.divWadDown(lower)); + lower = lower.mulDivDown(999, 1000); + uint256 min = rx > ry.divWadDown(params.strike) ? rx + 1000 : ry.divWadDown(params.strike) + 1000; + lower = lower < rx ? min : lower; computedInvariant = LogNormalLib.tradingFunction({ rx: rx, ry: ry, @@ -177,7 +178,6 @@ function computeNextLiquidity( }); } } - console2.log("computedInvariant", computedInvariant); L = bisection( abi.encode(rx, ry, computedInvariant, params), lower, From 17f404f9d2a83e59d2ddca68eb6d7aa4fb05d385 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 15:48:15 -0500 Subject: [PATCH 31/37] log computed dy --- src/LogNormal/LogNormalSolver.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 9b3ee265..fa3f65f8 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -346,7 +346,9 @@ contract LogNormalSolver { ) public view returns (int256) { LogNormal.LogNormalParams memory params = fetchPoolParams(poolId); (, uint256 ry, uint256 L) = getReservesAndLiquidity(poolId); - return computeDy(int256(S), int256(ry), int256(L), params); + int256 dy = computeDy(int256(S), int256(ry), int256(L), params); + console2.log("====computed dy=====", dy); + return dy; } function getDxGivenS( From a1e71504dbf10fe251c745c5f39c49d8e646733f Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 16:00:23 -0500 Subject: [PATCH 32/37] update dx and dy logic --- src/LogNormal/LogNormalExtendedLib.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 0622971e..3d33db72 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -531,8 +531,9 @@ function computeDy(int256 S, int256 rY, int256 L, LogNormal.LogNormalParams memo int256 cdfA = Gaussian.cdf(a); int256 delta = L.wadMul(strike).wadMul(cdfA); + dy = delta - rY; - dy = (delta - rY).wadDiv((gamma - I_ONE).wadMul(cdfA).wadDiv(rY.wadDiv(strike.wadMul(L))) + I_ONE); + //dy = (delta - rY).wadDiv((gamma - I_ONE).wadMul(cdfA).wadDiv(rY.wadDiv(strike.wadMul(L))) + I_ONE); } function computeDx(int256 S, int256 rX, int256 L, LogNormal.LogNormalParams memory params) view returns (int256 dx) { @@ -544,8 +545,9 @@ function computeDx(int256 S, int256 rX, int256 L, LogNormal.LogNormalParams memo int256 a = Gaussian.cdf(lnSDivK.wadDiv(sigma) + sigma.wadDiv(I_TWO)); // L * (1 - cdf) int256 delta = L.wadMul(I_ONE - a); + dx = delta - rX; - dx = (delta - rX).wadDiv((gamma - I_ONE).wadMul(I_ONE - a).wadDiv(rX.wadDiv(L)) + I_ONE); + //dx = (delta - rX).wadDiv((gamma - I_ONE).wadMul(I_ONE - a).wadDiv(rX.wadDiv(L)) + I_ONE); } From 78155689a76103f645132fd1c4941dd1554e6869 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 16:08:07 -0500 Subject: [PATCH 33/37] log next x and current x --- src/LogNormal/LogNormalSolver.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index fa3f65f8..3bdf590d 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -249,6 +249,8 @@ contract LogNormalSolver { poolId, endReserves.ry, endReserves.L, endReserves.approxPrice ); console2.log("computed next X"); + console2.log("next x:", endReserves.rx); + console2.log("start x:", startReserves.rx); require( endReserves.rx < startReserves.rx, From 536536b4260eb6573c055646522456da6ccd7bcb Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 16:17:19 -0500 Subject: [PATCH 34/37] update next rx bounds --- src/LogNormal/LogNormalExtendedLib.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 3d33db72..513b8824 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -197,10 +197,14 @@ function computeNextRx( ) view returns (uint256 rx) { uint256 upper = approximatedRx; uint256 lower = approximatedRx; + console2.log("approximatedRx", approximatedRx); int256 computedInvariant = invariant; + console2.log("computedInvariant", computedInvariant); if (computedInvariant < 0) { while (computedInvariant < 0) { upper = upper.mulDivUp(1001, 1000); + console2.log("rx upper", upper); + upper = upper > L ? L : upper; computedInvariant = LogNormalLib.tradingFunction({ rx: upper, ry: ry, From ecae212d699f3bab68a39c5255b1c0eb2b99224a Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 16:25:32 -0500 Subject: [PATCH 35/37] fix lower bound for next rx --- src/LogNormal/LogNormalExtendedLib.sol | 2 ++ src/LogNormal/LogNormalSolver.sol | 1 + 2 files changed, 3 insertions(+) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 513b8824..278355a4 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -215,6 +215,8 @@ function computeNextRx( } else { while (computedInvariant > 0) { lower = lower.mulDivDown(999, 1000); + console2.log("rx lower", lower); + lower = lower > L ? L : lower; computedInvariant = LogNormalLib.tradingFunction({ rx: lower, ry: ry, diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 3bdf590d..c0d0a9f1 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -168,6 +168,7 @@ contract LogNormalSolver { uint256 S ) public view returns (uint256) { uint256 approximatedRx = computeXGivenL(L, S, fetchPoolParams(poolId)); + console2.log("approximated rx given price", approximatedRx); bytes memory data = abi.encode(approximatedRx, ry, L); int256 invariant = IStrategy(strategy).computeSwapConstant(poolId, data); return computeNextRx( From 961ca178f1e33b43aa63b44f69176b93b5e206d4 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 16:31:00 -0500 Subject: [PATCH 36/37] more logS --- src/LogNormal/LogNormalSolver.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index c0d0a9f1..f7aed258 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -242,6 +242,8 @@ contract LogNormalSolver { } else { endReserves.ry = startReserves.ry + amountIn; endReserves.L = startComputedL + computeDeltaL(amountIn, poolParams.swapFee, startReserves.L, startReserves.ry); + console2.log("end ry", endReserves.ry); + console2.log("end L", endReserves.L); endReserves.approxPrice = getPriceGivenYL(poolId, endReserves.ry, endReserves.L); From 5e0a7da0ac109373316703d91554a7095c8b660e Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Tue, 5 Mar 2024 16:44:24 -0500 Subject: [PATCH 37/37] refactor fee calculations --- src/LogNormal/LogNormalSolver.sol | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index f7aed258..75138ed1 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -199,6 +199,33 @@ contract LogNormalSolver { deltaL = amountIn.mulWadUp(swapFee).mulWadUp(L).divWadUp(reserve).mulWadUp(HALF); } + function computeDeltaLXIn( + uint256 poolId, + uint256 amountIn, + uint256 rx, + uint256 ry, + uint256 L, + LogNormal.LogNormalParams memory params + ) public view returns (uint256 deltaL) { + uint256 fees = params.swapFee.mulWadUp(amountIn); + uint256 px = getPriceGivenXL(poolId, rx, L); + deltaL = fees.divWadDown(px.mulWadDown(rx) + ry); + } + + function computeDeltaLYIn( + uint256 poolId, + uint256 amountIn, + uint256 rx, + uint256 ry, + uint256 L, + LogNormal.LogNormalParams memory params + ) public view returns (uint256 deltaL) { + uint256 fees = params.swapFee.mulWadUp(amountIn); + uint256 py = getPriceGivenYL(poolId, ry, L); + deltaL = fees.divWadDown(py.mulWadDown(rx) + ry); + } + + /// @dev Estimates a swap's reserves and adjustments and returns its validity. function simulateSwap( uint256 poolId, @@ -224,7 +251,7 @@ contract LogNormalSolver { if (swapXIn) { endReserves.rx = startReserves.rx + amountIn; - endReserves.L = startComputedL + computeDeltaL(amountIn, poolParams.swapFee, startReserves.L, startReserves.rx); + endReserves.L = startComputedL + computeDeltaLXIn(poolId, amountIn, startReserves.rx, startReserves.ry, startReserves.L, poolParams); endReserves.approxPrice = getPriceGivenXL(poolId, endReserves.rx, endReserves.L); @@ -241,7 +268,7 @@ contract LogNormalSolver { amountOut = startReserves.ry - endReserves.ry; } else { endReserves.ry = startReserves.ry + amountIn; - endReserves.L = startComputedL + computeDeltaL(amountIn, poolParams.swapFee, startReserves.L, startReserves.ry); + endReserves.L = startComputedL + computeDeltaLYIn(poolId, amountIn, startReserves.rx, startReserves.ry, startReserves.L, poolParams); console2.log("end ry", endReserves.ry); console2.log("end L", endReserves.L); endReserves.approxPrice =