From 55d9838cef9393df005d3073c57f785eec8cd291 Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Wed, 13 Mar 2024 16:25:39 -0400 Subject: [PATCH 1/4] updated lognormal fee logic --- src/LogNormal/LogNormalMath.sol | 24 ++++++++++++++++++++++++ src/LogNormal/LogNormalSolver.sol | 9 +++++---- test/LogNormal/unit/Swap.t.sol | 3 +++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/LogNormal/LogNormalMath.sol b/src/LogNormal/LogNormalMath.sol index ba58d4b9..9fac3c09 100644 --- a/src/LogNormal/LogNormalMath.sol +++ b/src/LogNormal/LogNormalMath.sol @@ -168,6 +168,30 @@ function computePriceGivenY( return params.mean.mulWadUp(uint256(exp)); } +function computeDeltaLXIn( + uint256 amountIn, + uint256 rx, + uint256 ry, + uint256 L, + LogNormalParams memory params +) pure returns (uint256 deltaL) { + uint256 fees = params.swapFee.mulWadUp(amountIn); + uint256 px = computePriceGivenX(rx, L, params); + deltaL = px.mulWadUp(L).mulWadUp(fees).divWadDown(px.mulWadDown(rx) + ry); +} + +function computeDeltaLYIn( + uint256 amountIn, + uint256 rx, + uint256 ry, + uint256 L, + LogNormalParams memory params +) pure returns (uint256 deltaL) { + uint256 fees = params.swapFee.mulWadUp(amountIn); + uint256 py = computePriceGivenY(ry, L, params); + deltaL = L.mulWadUp(fees).divWadDown(py.mulWadDown(rx) + ry); +} + /// @dev This is a pure 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. diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index d26f037f..574113f0 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -26,7 +26,9 @@ import { computeYGivenL, computeNextRy, computePriceGivenX, - computePriceGivenY + computePriceGivenY, + computeDeltaLXIn, + computeDeltaLYIn } from "src/LogNormal/LogNormalMath.sol"; contract LogNormalSolver { @@ -254,7 +256,7 @@ contract LogNormalSolver { ); if (swapXIn) { - state.deltaLiquidity = amountIn.mulWadUp(poolParams.swapFee); + state.deltaLiquidity = computeDeltaLXIn(amountIn, preReserves[0], preReserves[1], preTotalLiquidity, poolParams); endReserves.rx = preReserves[0] + amountIn; endReserves.L = startComputedL + state.deltaLiquidity; @@ -271,8 +273,7 @@ contract LogNormalSolver { ); state.amountOut = preReserves[1] - endReserves.ry; } else { - state.deltaLiquidity = amountIn.mulWadUp(poolParams.swapFee) - .divWadUp(poolParams.mean); + state.deltaLiquidity = computeDeltaLYIn(amountIn, preReserves[0], preReserves[1], preTotalLiquidity, poolParams); endReserves.ry = preReserves[1] + amountIn; endReserves.L = startComputedL + state.deltaLiquidity; diff --git a/test/LogNormal/unit/Swap.t.sol b/test/LogNormal/unit/Swap.t.sol index a4b54fdf..8bdc3d15 100644 --- a/test/LogNormal/unit/Swap.t.sol +++ b/test/LogNormal/unit/Swap.t.sol @@ -99,4 +99,7 @@ contract LogNormalSwapTest is LogNormalSetUp { vm.expectRevert(); dfmm.swap(POOL_ID, payload); } + function test_LogNormal_swap_ChargesCorrectFees() public init { + + } } From f63fcc05da4b5c523462e7e7eba2e14adc0dbf6b Mon Sep 17 00:00:00 2001 From: Kinrezc Date: Wed, 13 Mar 2024 17:38:38 -0400 Subject: [PATCH 2/4] wip --- src/LogNormal/LogNormalMath.sol | 4 ++-- src/LogNormal/LogNormalSolver.sol | 3 +++ test/LogNormal/unit/SetUp.sol | 33 +++++++++++++++++++++++++++++++ test/LogNormal/unit/Swap.t.sol | 28 +++++++++++++++++++++++++- test/utils/SetUp.sol | 4 ++-- 5 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/LogNormal/LogNormalMath.sol b/src/LogNormal/LogNormalMath.sol index 9fac3c09..50bc82ac 100644 --- a/src/LogNormal/LogNormalMath.sol +++ b/src/LogNormal/LogNormalMath.sol @@ -188,8 +188,8 @@ function computeDeltaLYIn( LogNormalParams memory params ) pure returns (uint256 deltaL) { uint256 fees = params.swapFee.mulWadUp(amountIn); - uint256 py = computePriceGivenY(ry, L, params); - deltaL = L.mulWadUp(fees).divWadDown(py.mulWadDown(rx) + ry); + uint256 px = computePriceGivenX(rx, L, params); + deltaL = L.mulWadUp(fees).divWadDown(px.mulWadDown(rx) + ry); } /// @dev This is a pure anonymous function defined at the file level, which allows diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 574113f0..50e2837d 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -30,6 +30,7 @@ import { computeDeltaLXIn, computeDeltaLYIn } from "src/LogNormal/LogNormalMath.sol"; +import "forge-std/console2.sol"; contract LogNormalSolver { using FixedPointMathLib for uint256; @@ -257,6 +258,7 @@ contract LogNormalSolver { if (swapXIn) { state.deltaLiquidity = computeDeltaLXIn(amountIn, preReserves[0], preReserves[1], preTotalLiquidity, poolParams); + console2.log("x dL", state.deltaLiquidity); endReserves.rx = preReserves[0] + amountIn; endReserves.L = startComputedL + state.deltaLiquidity; @@ -274,6 +276,7 @@ contract LogNormalSolver { state.amountOut = preReserves[1] - endReserves.ry; } else { state.deltaLiquidity = computeDeltaLYIn(amountIn, preReserves[0], preReserves[1], preTotalLiquidity, poolParams); + console2.log("y dL", state.deltaLiquidity); endReserves.ry = preReserves[1] + amountIn; endReserves.L = startComputedL + state.deltaLiquidity; diff --git a/test/LogNormal/unit/SetUp.sol b/test/LogNormal/unit/SetUp.sol index 19d9d501..0a399a35 100644 --- a/test/LogNormal/unit/SetUp.sol +++ b/test/LogNormal/unit/SetUp.sol @@ -19,11 +19,24 @@ contract LogNormalSetUp is SetUp { controller: address(this) }); + LogNormalParams defaultParamsDeep = LogNormalParams({ + mean: ONE, + width: 0.25 ether, + swapFee: TEST_SWAP_FEE, + controller: address(this) + }); + + uint256 defaultReserveX = ONE; + uint256 defaultReserveXDeep = ONE * 10_000_000; + uint256 defaultPrice = ONE; bytes defaultInitialPoolData = computeInitialPoolData(defaultReserveX, defaultPrice, defaultParams); + bytes defaultInitialPoolDataDeep = + computeInitialPoolData(defaultReserveXDeep, defaultPrice, defaultParamsDeep); + function setUp() public override { SetUp.setUp(); logNormal = new LogNormal(address(dfmm)); @@ -50,6 +63,26 @@ contract LogNormalSetUp is SetUp { _; } + modifier deep() { + vm.warp(0); + + address[] memory tokens = new address[](2); + tokens[0] = address(tokenX); + tokens[1] = address(tokenY); + + InitParams memory defaultInitParamsDeep = InitParams({ + name: "", + symbol: "", + strategy: address(logNormal), + tokens: tokens, + data: defaultInitialPoolDataDeep + }); + + (POOL_ID,,) = dfmm.init(defaultInitParamsDeep); + + _; + } + modifier initRealistic() { vm.warp(0); diff --git a/test/LogNormal/unit/Swap.t.sol b/test/LogNormal/unit/Swap.t.sol index 8bdc3d15..2c43abb3 100644 --- a/test/LogNormal/unit/Swap.t.sol +++ b/test/LogNormal/unit/Swap.t.sol @@ -99,7 +99,33 @@ contract LogNormalSwapTest is LogNormalSetUp { vm.expectRevert(); dfmm.swap(POOL_ID, payload); } - function test_LogNormal_swap_ChargesCorrectFees() public init { + function test_LogNormal_swap_ChargesCorrectFeesYIn() public deep { + uint256 amountIn = 1 ether; + bool swapXForY = false; + + (bool valid,,, bytes memory payload) = + solver.simulateSwap(POOL_ID, swapXForY, amountIn); + + (,, uint256 inputAmount, uint256 outputAmount) = + dfmm.swap(POOL_ID, payload); + + console2.log(inputAmount); + console2.log(outputAmount); + + } + + function test_LogNormal_swap_ChargesCorrectFeesXIn() public deep { + uint256 amountIn = 1 ether; + bool swapXForY = true; + + (bool valid,,, bytes memory payload) = + solver.simulateSwap(POOL_ID, swapXForY, amountIn); + + (,, uint256 inputAmount, uint256 outputAmount) = + dfmm.swap(POOL_ID, payload); + + console2.log(inputAmount); + console2.log(outputAmount); } } diff --git a/test/utils/SetUp.sol b/test/utils/SetUp.sol index c41ffc36..094ff6be 100644 --- a/test/utils/SetUp.sol +++ b/test/utils/SetUp.sol @@ -17,8 +17,8 @@ contract SetUp is Test { function setUp() public virtual { tokenX = new MockERC20("Test Token X", "TSTX", 18); tokenY = new MockERC20("Test Token Y", "TSTY", 18); - tokenX.mint(address(this), 100_000e18); - tokenY.mint(address(this), 100_000e18); + tokenX.mint(address(this), 10_000_000_000_000e18); + tokenY.mint(address(this), 10_000_000_000_000e18); weth = new WETH(); dfmm = new DFMM(address(weth)); From 41d3ec011c7365918739b5803750d2b08b44d493 Mon Sep 17 00:00:00 2001 From: clemlak Date: Thu, 14 Mar 2024 11:26:06 +0400 Subject: [PATCH 3/4] test: add missing init params in LogNormal deep pool SetUp --- test/LogNormal/unit/SetUp.sol | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/LogNormal/unit/SetUp.sol b/test/LogNormal/unit/SetUp.sol index 2a4b76cd..8c4428b1 100644 --- a/test/LogNormal/unit/SetUp.sol +++ b/test/LogNormal/unit/SetUp.sol @@ -26,7 +26,6 @@ contract LogNormalSetUp is SetUp { controller: address(this) }); - uint256 defaultReserveX = ONE; uint256 defaultReserveXDeep = ONE * 10_000_000; @@ -34,8 +33,9 @@ contract LogNormalSetUp is SetUp { bytes defaultInitialPoolData = computeInitialPoolData(defaultReserveX, defaultPrice, defaultParams); - bytes defaultInitialPoolDataDeep = - computeInitialPoolData(defaultReserveXDeep, defaultPrice, defaultParamsDeep); + bytes defaultInitialPoolDataDeep = computeInitialPoolData( + defaultReserveXDeep, defaultPrice, defaultParamsDeep + ); function setUp() public override { SetUp.setUp(); @@ -77,7 +77,9 @@ contract LogNormalSetUp is SetUp { symbol: "", strategy: address(logNormal), tokens: tokens, - data: defaultInitialPoolDataDeep + data: defaultInitialPoolDataDeep, + feeCollector: address(0), + controllerFee: 0 }); (POOL_ID,,) = dfmm.init(defaultInitParamsDeep); From e6ecaee01d04161023366c630b2bbae1ab87b3a7 Mon Sep 17 00:00:00 2001 From: clemlak Date: Thu, 14 Mar 2024 12:33:23 +0400 Subject: [PATCH 4/4] chore: remove console2 --- src/LogNormal/LogNormalSolver.sol | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index 50e2837d..18e9cfa0 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -30,7 +30,6 @@ import { computeDeltaLXIn, computeDeltaLYIn } from "src/LogNormal/LogNormalMath.sol"; -import "forge-std/console2.sol"; contract LogNormalSolver { using FixedPointMathLib for uint256; @@ -257,8 +256,13 @@ contract LogNormalSolver { ); if (swapXIn) { - state.deltaLiquidity = computeDeltaLXIn(amountIn, preReserves[0], preReserves[1], preTotalLiquidity, poolParams); - console2.log("x dL", state.deltaLiquidity); + state.deltaLiquidity = computeDeltaLXIn( + amountIn, + preReserves[0], + preReserves[1], + preTotalLiquidity, + poolParams + ); endReserves.rx = preReserves[0] + amountIn; endReserves.L = startComputedL + state.deltaLiquidity; @@ -275,8 +279,13 @@ contract LogNormalSolver { ); state.amountOut = preReserves[1] - endReserves.ry; } else { - state.deltaLiquidity = computeDeltaLYIn(amountIn, preReserves[0], preReserves[1], preTotalLiquidity, poolParams); - console2.log("y dL", state.deltaLiquidity); + state.deltaLiquidity = computeDeltaLYIn( + amountIn, + preReserves[0], + preReserves[1], + preTotalLiquidity, + poolParams + ); endReserves.ry = preReserves[1] + amountIn; endReserves.L = startComputedL + state.deltaLiquidity;