From 3b058539325baf091822c3f8c1cad55b87f8e12e Mon Sep 17 00:00:00 2001 From: Matt Czernik Date: Thu, 22 Feb 2024 17:09:31 -0500 Subject: [PATCH] fix lognormal fee accounting and update optimal arb logic (#16) --- src/LogNormal/LogNormalExtendedLib.sol | 56 +++++++++++++------------- src/LogNormal/LogNormalSolver.sol | 12 ++---- src/lib/StrategyLib.sol | 1 + src/test/LogNormal/LogNormalTest.t.sol | 4 +- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/LogNormal/LogNormalExtendedLib.sol b/src/LogNormal/LogNormalExtendedLib.sol index 26bbab4f..883bdba3 100644 --- a/src/LogNormal/LogNormalExtendedLib.sol +++ b/src/LogNormal/LogNormalExtendedLib.sol @@ -315,35 +315,33 @@ function diffLower( int256 iV = int256(v); int256 gamma = I_ONE - swapFee; - int256 ierfcNum = I_TWO.wadMul(iX).wadMul(iV + iX); - int256 ierfcDen = iL.wadMul(iV + iX - iV.wadMul(gamma)); + int256 ierfcNum = I_TWO.wadMul(iV + iX); + int256 ierfcDen = iL + iV - iV.wadMul(gamma); int256 ierfcRes = Gaussian.ierfc(ierfcNum.wadDiv(ierfcDen)); - int256 firstFrac; + int256 a; { - int256 firstExp = -(sigma.powWad(I_TWO).wadMul(tau).wadDiv(I_TWO)); + 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(iX).wadMul(gamma); + int256 second = strike.wadMul(iL + iX.wadMul(-I_ONE + gamma)); int256 firstNum = first.wadMul(second); - int256 firstDen = iV + iX - iV.wadMul(gamma); - firstFrac = firstNum.wadDiv(firstDen); + int256 firstDen = iL + iV - iV.wadMul(gamma); + a = firstNum.wadDiv(firstDen); } - int256 secondFrac; + int256 b; { - int256 first = strike.wadMul(iL).wadMul(-I_ONE + gamma); + int256 first = I_HALF.wadMul(strike).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(iX); - secondFrac = num.wadDiv(den); + b = first.wadMul(Gaussian.erfc(erfcFirst - erfcSecond)); } - return -iS + firstFrac + secondFrac; + return -iS + a + b; } function diffRaise( @@ -363,40 +361,40 @@ function diffRaise( int256 sqrtTwo = int256(FixedPointMathLib.sqrt(TWO) * 1e9); int256 sqrtTau = int256(FixedPointMathLib.sqrt(params.tau) * 1e9); 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 ierfcNum = I_TWO.wadMul(iY).wadMul(iV + iY); - int256 ierfcDen = -strike.wadMul(iL).wadMul(iV + iY) - + strike.wadMul(iL).wadMul(iV).wadMul(gamma); - int256 ierfcRes = Gaussian.ierfc(-ierfcNum.wadDiv(ierfcDen)); + int256 ierfcNum = I_TWO.wadMul(iV + iY); + int256 ierfcDen = strike.wadMul(iL) + iV - iV.wadMul(gamma); + int256 ierfcRes = Gaussian.ierfc(ierfcNum.wadDiv(ierfcDen)); - int256 firstFrac; + int256 a; { - int256 firstExp = -(sigma.powWad(I_TWO).wadMul(tau).wadDiv(I_TWO)); + 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(iY).wadMul(gamma); - int256 firstNum = first.wadMul(second); - int256 firstDen = strike.wadMul(iV + iY - iV.wadMul(gamma)); - firstFrac = firstNum.wadDiv(firstDen); + 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 secondFrac; + int256 b; { - int256 first = iL.wadMul(iS).wadMul(-I_ONE + gamma); + 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(iY); - secondFrac = num.wadDiv(den); + int256 den = I_TWO.wadMul(strike); + + b = num.wadDiv(den); } - return -I_ONE + firstFrac + secondFrac; + return -I_ONE + a + b; } function computeOptimalLower( diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index c37c37f1..7997ddac 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -203,10 +203,7 @@ contract LogNormalSolver { ); if (swapXIn) { - uint256 fees = amountIn.mulWadUp(poolParams.swapFee); - uint256 deltaL = - fees.mulWadUp(startComputedL).divWadUp(startReserves.rx); - deltaL += 1; + uint256 deltaL = amountIn.mulWadUp(poolParams.swapFee); endReserves.rx = startReserves.rx + amountIn; endReserves.L = startComputedL + deltaL; @@ -224,10 +221,9 @@ contract LogNormalSolver { ); amountOut = startReserves.ry - endReserves.ry; } else { - uint256 fees = amountIn.mulWadUp(poolParams.swapFee); - uint256 deltaL = - fees.mulWadUp(startComputedL).divWadUp(startReserves.ry); - deltaL += 1; + uint256 deltaL = amountIn.mulWadUp(poolParams.swapFee).divWadUp( + poolParams.strike + ); endReserves.ry = startReserves.ry + amountIn; endReserves.L = startComputedL + deltaL; diff --git a/src/lib/StrategyLib.sol b/src/lib/StrategyLib.sol index e65a6f26..2c49b6be 100644 --- a/src/lib/StrategyLib.sol +++ b/src/lib/StrategyLib.sol @@ -13,6 +13,7 @@ uint256 constant INFINITY_IS_NOT_REAL = type(uint256).max; uint256 constant ZERO = 0; int256 constant I_ONE = int256(ONE); int256 constant I_TWO = int256(TWO); +int256 constant I_HALF = int256(HALF); /// @dev the swap constant should never fall outside of range [-EPSILON, EPSILON] int256 constant EPSILON = 20; diff --git a/src/test/LogNormal/LogNormalTest.t.sol b/src/test/LogNormal/LogNormalTest.t.sol index fb4d8940..16bc02e5 100644 --- a/src/test/LogNormal/LogNormalTest.t.sol +++ b/src/test/LogNormal/LogNormalTest.t.sol @@ -147,7 +147,7 @@ contract LogNormalTest is Test { function test_ln_diff_lower() public basic { uint256 poolId = dfmm.nonce() - 1; int256 diffLowered = solver.calculateDiffLower( - poolId, 1.9 ether, 160_249_195_342_896_967 + poolId, 1.9 ether, 171_917_954_632_821_596 ); console2.log(diffLowered); @@ -156,7 +156,7 @@ contract LogNormalTest is Test { function test_ln_diff_raise() public basic { uint256 poolId = dfmm.nonce() - 1; int256 diffLowered = solver.calculateDiffRaise( - poolId, 2.1 ether, 302_756_023_375_108_995 + poolId, 2.1 ether, 326_118_838_819_816_034 ); console2.log(diffLowered);