diff --git a/src/ConstantSum/ConstantSum.sol b/src/ConstantSum/ConstantSum.sol index 52f431ec..dcde2628 100644 --- a/src/ConstantSum/ConstantSum.sol +++ b/src/ConstantSum/ConstantSum.sol @@ -89,86 +89,6 @@ contract ConstantSum is Strategy { return (valid, invariant, reserves, totalLiquidity); } - function validateAllocate( - address, - uint256 poolId, - Pool memory pool, - bytes calldata data - ) - external - view - override - returns ( - bool valid, - int256 invariant, - uint256[] memory deltas, - uint256 deltaLiquidity - ) - { - (uint256 deltaX, uint256 deltaY, uint256 minDeltaL) = - abi.decode(data, (uint256, uint256, uint256)); - - deltaLiquidity = computeDeltaLiquidityRoundDown( - deltaX, deltaY, internalParams[poolId].price - ); - if (deltaLiquidity < minDeltaL) revert InvalidDeltaLiquidity(); - - deltas = new uint256[](2); - deltas[0] = deltaX; - deltas[1] = deltaY; - - pool.reserves[0] += deltaX; - pool.reserves[1] += deltaY; - - invariant = tradingFunction( - pool.reserves, - pool.totalLiquidity + deltaLiquidity, - getPoolParams(poolId) - ); - - valid = invariant >= 0; - } - - function validateDeallocate( - address, - uint256 poolId, - Pool memory pool, - bytes calldata data - ) - external - view - override - returns ( - bool valid, - int256 invariant, - uint256[] memory deltas, - uint256 deltaLiquidity - ) - { - (uint256 deltaX, uint256 deltaY, uint256 maxDeltaL) = - abi.decode(data, (uint256, uint256, uint256)); - - deltaLiquidity = computeDeltaLiquidityRoundUp( - deltaX, deltaY, internalParams[poolId].price - ); - if (deltaLiquidity > maxDeltaL) revert InvalidDeltaLiquidity(); - - deltas = new uint256[](2); - deltas[0] = deltaX; - deltas[1] = deltaY; - - pool.reserves[0] -= deltaX; - pool.reserves[1] -= deltaY; - - invariant = tradingFunction( - pool.reserves, - pool.totalLiquidity - deltaLiquidity, - getPoolParams(poolId) - ); - - valid = invariant >= 0; - } - /// @inheritdoc IStrategy function update( address sender, diff --git a/src/ConstantSum/ConstantSumSolver.sol b/src/ConstantSum/ConstantSumSolver.sol index 24ebbebd..d6c68f75 100644 --- a/src/ConstantSum/ConstantSumSolver.sol +++ b/src/ConstantSum/ConstantSumSolver.sol @@ -65,6 +65,21 @@ contract ConstantSumSolver is ISolver { ConstantSumParams memory params = getPoolParams(poolId); + uint256 deltaLiquidity = + computeDeltaLiquidityRoundDown(deltas[0], deltas[1], params.price); + + return abi.encode(deltas, deltaLiquidity); + } + + /// @inheritdoc ISolver + function prepareAllocationProportional( + uint256 poolId, + uint256[] memory deltas + ) external view returns (bytes memory) { + if (deltas.length != 2) revert InvalidDeltasLength(); + + ConstantSumParams memory params = getPoolParams(poolId); + uint256 deltaLGivenDeltaX = computeDeltaLiquidityRoundDown(deltas[0], 0, params.price); @@ -72,9 +87,11 @@ contract ConstantSumSolver is ISolver { computeDeltaLiquidityRoundDown(0, deltas[1], params.price); if (deltaLGivenDeltaX < deltaLGivenDeltaY) { - return abi.encode(deltas[0], 0, deltaLGivenDeltaX); + deltas[1] = 0; + return abi.encode(deltas, deltaLGivenDeltaX); } else { - return abi.encode(0, deltas[1], deltaLGivenDeltaY); + deltas[0] = 0; + return abi.encode(deltas, deltaLGivenDeltaY); } } diff --git a/src/CoveredCall/CoveredCall.sol b/src/CoveredCall/CoveredCall.sol index dd9949bb..b4af9652 100644 --- a/src/CoveredCall/CoveredCall.sol +++ b/src/CoveredCall/CoveredCall.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.22; import { Pool } from "src/interfaces/IDFMM.sol"; -import { PairStrategy, IStrategy } from "src/PairStrategy.sol"; +import { Strategy, IStrategy } from "src/Strategy.sol"; import { IDFMM } from "src/interfaces/IDFMM.sol"; import { DynamicParamLib, DynamicParam } from "src/lib/DynamicParamLib.sol"; import { @@ -67,7 +67,7 @@ uint256 constant MAX_MEAN = uint256(type(int256).max); * @title CoveredCall Strategy for DFMM. * @author Primitive */ -contract CoveredCall is PairStrategy { +contract CoveredCall is Strategy { using DynamicParamLib for DynamicParam; /// @inheritdoc IStrategy @@ -76,7 +76,7 @@ contract CoveredCall is PairStrategy { mapping(uint256 => InternalParams) public internalParams; /// @param dfmm_ Address of the DFMM contract. - constructor(address dfmm_) PairStrategy(dfmm_) { } + constructor(address dfmm_) Strategy(dfmm_) { } /// @inheritdoc IStrategy function init( @@ -240,43 +240,6 @@ contract CoveredCall is PairStrategy { ); } - /// @inheritdoc PairStrategy - function _computeAllocateDeltasGivenDeltaL( - uint256 deltaLiquidity, - Pool memory pool, - bytes memory - ) internal pure override returns (uint256[] memory) { - uint256[] memory deltas = new uint256[](2); - - deltas[0] = computeDeltaGivenDeltaLRoundUp( - pool.reserves[0], deltaLiquidity, pool.totalLiquidity - ); - - deltas[1] = computeDeltaGivenDeltaLRoundUp( - pool.reserves[1], deltaLiquidity, pool.totalLiquidity - ); - - return deltas; - } - - /// @inheritdoc PairStrategy - function _computeDeallocateDeltasGivenDeltaL( - uint256 deltaLiquidity, - Pool memory pool, - bytes memory - ) internal pure override returns (uint256[] memory) { - uint256[] memory deltas = new uint256[](2); - - deltas[0] = computeDeltaGivenDeltaLRoundDown( - pool.reserves[0], deltaLiquidity, pool.totalLiquidity - ); - - deltas[1] = computeDeltaGivenDeltaLRoundDown( - pool.reserves[1], deltaLiquidity, pool.totalLiquidity - ); - return deltas; - } - function _computeSwapDeltaLiquidity( Pool memory pool, bytes memory params, diff --git a/src/CoveredCall/CoveredCallSolver.sol b/src/CoveredCall/CoveredCallSolver.sol index 9a2de3c3..6226716e 100644 --- a/src/CoveredCall/CoveredCallSolver.sol +++ b/src/CoveredCall/CoveredCallSolver.sol @@ -141,6 +141,30 @@ contract CoveredCallSolver is ISolver { ) public view returns (bytes memory) { if (deltas.length != 2) revert InvalidDeltasLength(); + (uint256[] memory reserves, uint256 totalLiquidity) = + getReservesAndLiquidity(poolId); + + CoveredCallParams memory params = getPoolParams(poolId); + int256 lastInvariant = computeTradingFunction( + reserves[0], reserves[1], totalLiquidity, params + ); + + uint256 nextReserveX = reserves[0] + deltas[0]; + uint256 nextReserveY = reserves[1] + deltas[1]; + uint256 nextLiquidity = computeNextLiquidity( + nextReserveX, nextReserveY, lastInvariant, totalLiquidity, params + ); + uint256 deltaLiquidity = nextLiquidity - totalLiquidity; + + return abi.encode(deltas, deltaLiquidity); + } + + function prepareAllocationProportional( + uint256 poolId, + uint256[] calldata deltas + ) public view returns (bytes memory) { + if (deltas.length != 2) revert InvalidDeltasLength(); + (uint256[] memory reserves, uint256 totalLiquidity) = getReservesAndLiquidity(poolId); @@ -156,10 +180,13 @@ contract CoveredCallSolver is ISolver { deltaLGivenDeltaY, totalLiquidity, reserves[0] ); + uint256[] memory allocateDeltas = deltas; if (deltaLGivenDeltaX < deltaLGivenDeltaY) { - return abi.encode(deltas[0], deltaYGivenDeltaX, deltaLGivenDeltaX); + allocateDeltas[1] = deltaYGivenDeltaX; + return abi.encode(allocateDeltas, deltaLGivenDeltaX); } else { - return abi.encode(deltaXGivenDeltaL, deltas[1], deltaLGivenDeltaY); + allocateDeltas[0] = deltaXGivenDeltaL; + return abi.encode(allocateDeltas, deltaLGivenDeltaY); } } @@ -176,7 +203,11 @@ contract CoveredCallSolver is ISolver { uint256 deltaY = computeDeltaYGivenDeltaL(deltaLiquidity, liquidity, reserves[1]); - return abi.encode(deltaX, deltaY, deltaLiquidity); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = deltaX; + deltas[1] = deltaY; + + return abi.encode(deltas, deltaLiquidity); } struct SimulateSwapState { diff --git a/src/GeometricMean/GeometricMeanSolver.sol b/src/GeometricMean/GeometricMeanSolver.sol index 131123b6..4b79c58b 100644 --- a/src/GeometricMean/GeometricMeanSolver.sol +++ b/src/GeometricMean/GeometricMeanSolver.sol @@ -17,6 +17,7 @@ import { computePrice, computeSwapDeltaLiquidity, computeDeltaGivenDeltaLRoundUp, + computeL, ONE } from "./G3MMath.sol"; import { @@ -62,6 +63,24 @@ contract GeometricMeanSolver is ISolver { ) external view returns (bytes memory) { if (deltas.length != 2) revert InvalidDeltasLength(); + (uint256[] memory reserves, uint256 totalLiquidity) = + getReservesAndLiquidity(poolId); + + GeometricMeanParams memory params = getPoolParams(poolId); + + uint256 deltaLiquidity = + computeL(reserves[0] + deltas[0], reserves[1] + deltas[1], params) - totalLiquidity; + + return abi.encode(deltas, deltaLiquidity); + } + + /// @inheritdoc ISolver + function prepareAllocationProportional( + uint256 poolId, + uint256[] memory deltas + ) external view returns (bytes memory) { + if (deltas.length != 2) revert InvalidDeltasLength(); + (uint256[] memory reserves, uint256 totalLiquidity) = getReservesAndLiquidity(poolId); @@ -76,9 +95,11 @@ contract GeometricMeanSolver is ISolver { ); if (deltaLGivenX < deltaLGivenY) { - return abi.encode(deltas[0], deltaYGivenX, deltaLGivenX); + deltas[1] = deltaYGivenX; + return abi.encode(deltas, deltaLGivenX); } else { - return abi.encode(deltaXGivenY, deltas[1], deltaLGivenY); + deltas[0] = deltaXGivenY; + return abi.encode(deltas, deltaLGivenY); } } @@ -98,7 +119,11 @@ contract GeometricMeanSolver is ISolver { reserves[1], deltaLiquidity, liquidity ); - return abi.encode(deltaX, deltaY, deltaLiquidity); + uint[] memory deltas = new uint[](reserves.length); + deltas[0] = deltaX; + deltas[1] = deltaY; + + return abi.encode(deltas, deltaLiquidity); } struct SimulateSwapState { diff --git a/src/LogNormal/LogNormalSolver.sol b/src/LogNormal/LogNormalSolver.sol index a67de658..e3ee4815 100644 --- a/src/LogNormal/LogNormalSolver.sol +++ b/src/LogNormal/LogNormalSolver.sol @@ -82,6 +82,31 @@ contract LogNormalSolver is ISolver { ) external view override returns (bytes memory) { if (deltas.length != 2) revert InvalidDeltasLength(); + (uint256[] memory reserves, uint256 totalLiquidity) = + getReservesAndLiquidity(poolId); + + LogNormalParams memory params = getPoolParams(poolId); + int256 lastInvariant = computeTradingFunction( + reserves[0], reserves[1], totalLiquidity, params + ); + + uint256 nextReserveX = reserves[0] + deltas[0]; + uint256 nextReserveY = reserves[1] + deltas[1]; + uint256 nextLiquidity = computeNextLiquidity( + nextReserveX, nextReserveY, lastInvariant, totalLiquidity, params + ); + uint deltaLiquidity = nextLiquidity - totalLiquidity; + + return abi.encode(deltas, deltaLiquidity); + } + + /// @inheritdoc ISolver + function prepareAllocationProportional( + uint256 poolId, + uint256[] calldata deltas + ) external view override returns (bytes memory) { + if (deltas.length != 2) revert InvalidDeltasLength(); + (uint256[] memory reserves, uint256 totalLiquidity) = getReservesAndLiquidity(poolId); @@ -117,7 +142,11 @@ contract LogNormalSolver is ISolver { uint256 deltaY = computeDeltaYGivenDeltaL(deltaLiquidity, liquidity, reserves[1]); - return abi.encode(deltaX, deltaY, deltaLiquidity); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = deltaX; + deltas[1] = deltaY; + + return abi.encode(deltas, deltaLiquidity); } struct SimulateSwapState { @@ -220,11 +249,7 @@ contract LogNormalSolver is ISolver { address(this), poolId, pool, swapData ); - return ( - valid, - state.amountOut, - swapData - ); + return (valid, state.amountOut, swapData); } /// @inheritdoc ISolver diff --git a/src/NTokenGeometricMean/NTokenGeometricMeanSolver.sol b/src/NTokenGeometricMean/NTokenGeometricMeanSolver.sol index fbb68cd8..993de6e1 100644 --- a/src/NTokenGeometricMean/NTokenGeometricMeanSolver.sol +++ b/src/NTokenGeometricMean/NTokenGeometricMeanSolver.sol @@ -17,7 +17,8 @@ import { computeDeallocationDeltasGivenDeltaT, computeNextLiquidity, computeSwapDeltaLiquidity, - computeDeltaGivenDeltaLRoundDown + computeDeltaGivenDeltaLRoundDown, + computeL } from "src/NTokenGeometricMean/NTokenGeometricMeanMath.sol"; import { ISolver, @@ -65,6 +66,27 @@ contract NTokenGeometricMeanSolver is ISolver { uint256 length = deltas.length; if (deltas.length != reserves.length) revert InvalidDeltasLength(); + uint256[] memory nextReserves = new uint256[](length); + for (uint256 i; i < length; i++) { + nextReserves[i] = reserves[i] + deltas[i]; + } + + NTokenGeometricMeanParams memory params = getPoolParams(poolId); + uint256 deltaLiquidity = computeL(reserves, params) - totalLiquidity; + + return abi.encode(deltas, deltaLiquidity); + } + + /// @inheritdoc ISolver + function prepareAllocationProportional( + uint256 poolId, + uint256[] calldata deltas + ) public view returns (bytes memory) { + (uint256[] memory reserves, uint256 totalLiquidity) = + getReservesAndLiquidity(poolId); + uint256 length = deltas.length; + if (deltas.length != reserves.length) revert InvalidDeltasLength(); + uint256 minDeltaLiquidity = totalLiquidity.mulDivDown(deltas[0], reserves[0]); uint256 minDeltaLiquidityIndex = 0; diff --git a/src/SYCoveredCall/SYCoveredCall.sol b/src/SYCoveredCall/SYCoveredCall.sol index 51afd74e..199f50f7 100644 --- a/src/SYCoveredCall/SYCoveredCall.sol +++ b/src/SYCoveredCall/SYCoveredCall.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.22; import { Pool } from "src/interfaces/IDFMM.sol"; -import { PairStrategy, IStrategy } from "src/PairStrategy.sol"; +import { Strategy, IStrategy } from "src/Strategy.sol"; import { IDFMM } from "src/interfaces/IDFMM.sol"; import { DynamicParamLib, DynamicParam } from "src/lib/DynamicParamLib.sol"; import { SignedWadMathLib } from "src/lib/SignedWadMath.sol"; @@ -90,7 +90,7 @@ uint256 constant T_EPSILON = 200; * @title SYCoveredCall Strategy for DFMM. * @author Primitive */ -contract SYCoveredCall is PairStrategy { +contract SYCoveredCall is Strategy { using FixedPointMathLib for int256; /// @inheritdoc IStrategy @@ -99,7 +99,7 @@ contract SYCoveredCall is PairStrategy { mapping(uint256 => InternalParams) public internalParams; /// @param dfmm_ Address of the DFMM contract. - constructor(address dfmm_) PairStrategy(dfmm_) { } + constructor(address dfmm_) Strategy(dfmm_) { } /// @inheritdoc IStrategy function init( @@ -305,43 +305,6 @@ contract SYCoveredCall is PairStrategy { ); } - /// @inheritdoc PairStrategy - function _computeAllocateDeltasGivenDeltaL( - uint256 deltaLiquidity, - Pool memory pool, - bytes memory - ) internal pure override returns (uint256[] memory) { - uint256[] memory deltas = new uint256[](2); - - deltas[0] = computeDeltaGivenDeltaLRoundUp( - pool.reserves[0], deltaLiquidity, pool.totalLiquidity - ); - - deltas[1] = computeDeltaGivenDeltaLRoundUp( - pool.reserves[1], deltaLiquidity, pool.totalLiquidity - ); - - return deltas; - } - - /// @inheritdoc PairStrategy - function _computeDeallocateDeltasGivenDeltaL( - uint256 deltaLiquidity, - Pool memory pool, - bytes memory - ) internal pure override returns (uint256[] memory) { - uint256[] memory deltas = new uint256[](2); - - deltas[0] = computeDeltaGivenDeltaLRoundDown( - pool.reserves[0], deltaLiquidity, pool.totalLiquidity - ); - - deltas[1] = computeDeltaGivenDeltaLRoundDown( - pool.reserves[1], deltaLiquidity, pool.totalLiquidity - ); - return deltas; - } - function _computeSwapDeltaLiquidity( Pool memory pool, bytes memory params, diff --git a/src/SYCoveredCall/SYCoveredCallSolver.sol b/src/SYCoveredCall/SYCoveredCallSolver.sol index 5b98232b..a50ac0db 100644 --- a/src/SYCoveredCall/SYCoveredCallSolver.sol +++ b/src/SYCoveredCall/SYCoveredCallSolver.sol @@ -142,6 +142,30 @@ contract SYCoveredCallSolver is ISolver { ) public view returns (bytes memory) { if (deltas.length != 2) revert InvalidDeltasLength(); + (uint256[] memory reserves, uint256 totalLiquidity) = + getReservesAndLiquidity(poolId); + + SYCoveredCallParams memory params = getPoolParams(poolId); + int256 lastInvariant = computeTradingFunction( + reserves[0], reserves[1], totalLiquidity, params + ); + + uint256 nextReserveX = reserves[0] + deltas[0]; + uint256 nextReserveY = reserves[1] + deltas[1]; + uint256 nextLiquidity = computeNextLiquidity( + nextReserveX, nextReserveY, lastInvariant, totalLiquidity, params + ); + uint256 deltaLiquidity = nextLiquidity - totalLiquidity; + + return abi.encode(deltas, deltaLiquidity); + } + + function prepareAllocationProportional( + uint256 poolId, + uint256[] calldata deltas + ) public view returns (bytes memory) { + if (deltas.length != 2) revert InvalidDeltasLength(); + (uint256[] memory reserves, uint256 totalLiquidity) = getReservesAndLiquidity(poolId); @@ -177,7 +201,11 @@ contract SYCoveredCallSolver is ISolver { uint256 deltaY = computeDeltaYGivenDeltaL(deltaLiquidity, liquidity, reserves[1]); - return abi.encode(deltaX, deltaY, deltaLiquidity); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = deltaX; + deltas[1] = deltaY; + + return abi.encode(deltas, deltaLiquidity); } struct SimulateSwapState { diff --git a/src/interfaces/ISolver.sol b/src/interfaces/ISolver.sol index c5822147..1b509875 100644 --- a/src/interfaces/ISolver.sol +++ b/src/interfaces/ISolver.sol @@ -41,6 +41,15 @@ interface ISolver { uint256[] memory deltas ) external view returns (bytes memory data); + /** + * @notice Prepares the token deltas and liquidity amounts expecting a proportion of tokens + * that aligns with the pool's proportions. + */ + function prepareAllocationProportional( + uint256 poolId, + uint256[] memory deltas + ) external view returns (bytes memory data); + /** * @notice Prepares the data to deallocate liquidity from a pool. * @param poolId Id of the target DFMM pool. diff --git a/test/ConstantSum/unit/Allocate.t.sol b/test/ConstantSum/unit/Allocate.t.sol index 4d509670..c73f1bdf 100644 --- a/test/ConstantSum/unit/Allocate.t.sol +++ b/test/ConstantSum/unit/Allocate.t.sol @@ -12,18 +12,15 @@ contract ConstantSumAllocateTest is ConstantSumSetUp { uint256 deltaX = 0.1 ether; uint256 deltaY = 0.1 ether; - (uint256[] memory reserves, uint256 liquidity) = - getReservesAndLiquidity(POOL_ID); - - uint256[] memory deltas = new uint256[](reserves.length); - deltas[0] = deltaX; - deltas[1] = deltaY; - ConstantSumParams memory params = abi.decode(constantSum.getPoolParams(POOL_ID), (ConstantSumParams)); uint256 deltaL = computeDeltaLiquidityRoundDown(deltaX, deltaY, params.price); - dfmm.allocate(POOL_ID, abi.encode(deltaX, deltaY, deltaL)); + uint[] memory deltas = new uint[](2); + deltas[0] = deltaX; + deltas[1] = deltaY; + + dfmm.allocate(POOL_ID, abi.encode(deltas, deltaL)); } } diff --git a/test/CoveredCall/unit/Allocate.t.sol b/test/CoveredCall/unit/Allocate.t.sol index 511ab84a..d6a6a2f0 100644 --- a/test/CoveredCall/unit/Allocate.t.sol +++ b/test/CoveredCall/unit/Allocate.t.sol @@ -24,12 +24,17 @@ contract CoveredCallAllocateTest is CoveredCallSetUp { reserves[1], deltaLiquidity, totalLiquidity ); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = maxDeltaX; + deltas[1] = maxDeltaY; + (, uint256 preTotalLiquidity) = solver.getReservesAndLiquidity(POOL_ID); uint256 preLiquidityBalance = liquidityOf(address(this), POOL_ID); console2.log(preTotalLiquidity); console2.log(preLiquidityBalance); - bytes memory data = abi.encode(maxDeltaX, maxDeltaY, deltaLiquidity); + bytes memory data = + solver.prepareAllocationProportional(POOL_ID, deltas); dfmm.allocate(POOL_ID, data); (, uint256 postTotalLiquidity) = solver.getReservesAndLiquidity(POOL_ID); @@ -57,7 +62,12 @@ contract CoveredCallAllocateTest is CoveredCallSetUp { // uint256 preLiquidityBalance = liquidityOf(address(this), POOL_ID); // (,, uint256 preTotalLiquidity) = dfmm.getReservesAndLiquidity(POOL_ID); - bytes memory data = abi.encode(deltaX, deltaYMax, deltaLiquidity); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = deltaX; + deltas[1] = deltaYMax; + + bytes memory data = + solver.prepareAllocationProportional(POOL_ID, deltas); dfmm.allocate(POOL_ID, data); /* @@ -84,10 +94,15 @@ contract CoveredCallAllocateTest is CoveredCallSetUp { computeDeltaXGivenDeltaL(deltaLiquidity, liquidity, reserves[0]); console2.log(maxDeltaX); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = maxDeltaX; + deltas[1] = maxDeltaY; + // uint256 preLiquidityBalance = liquidityOf(address(this), POOL_ID); // (,, uint256 preTotalLiquidity) = dfmm.getReservesAndLiquidity(POOL_ID); - bytes memory data = abi.encode(maxDeltaX, maxDeltaY, deltaLiquidity); + bytes memory data = + solver.prepareAllocationProportional(POOL_ID, deltas); dfmm.allocate(POOL_ID, data); /* @@ -112,7 +127,12 @@ contract CoveredCallAllocateTest is CoveredCallSetUp { uint256 deltaYMax = computeDeltaYGivenDeltaL(deltaLiquidity, liquidity, reserves[1]); - bytes memory data = abi.encode(deltaX, deltaYMax, deltaLiquidity); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = deltaX; + deltas[1] = deltaYMax; + + bytes memory data = + solver.prepareAllocationProportional(POOL_ID, deltas); dfmm.allocate(POOL_ID, data); uint256 endPrice = solver.getEstimatedPrice(POOL_ID, 0, 1); @@ -132,7 +152,12 @@ contract CoveredCallAllocateTest is CoveredCallSetUp { uint256 maxDeltaX = computeDeltaXGivenDeltaL(deltaLiquidity, liquidity, reserves[0]); - bytes memory data = abi.encode(maxDeltaX, maxDeltaY, deltaLiquidity); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = maxDeltaX; + deltas[1] = maxDeltaY; + + bytes memory data = + solver.prepareAllocationProportional(POOL_ID, deltas); dfmm.allocate(POOL_ID, data); uint256 endPrice = solver.getEstimatedPrice(POOL_ID, 0, 1); diff --git a/test/CoveredCall/unit/Deallocate.t.sol b/test/CoveredCall/unit/Deallocate.t.sol index ce17496c..ae56f6c9 100644 --- a/test/CoveredCall/unit/Deallocate.t.sol +++ b/test/CoveredCall/unit/Deallocate.t.sol @@ -25,8 +25,11 @@ contract CoveredCallDeallocateTest is CoveredCallSetUp { // TODO: See if we can get a better rounding because the transaction fails // if we don't provide a small slippage toleralance. - bytes memory data = - abi.encode(minDeltaX - 10, minDeltaY - 10, deltaLiquidity); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = minDeltaX - 10; + deltas[1] = minDeltaY - 10; + + bytes memory data = abi.encode(deltas, deltaLiquidity); dfmm.deallocate(POOL_ID, data); /* @@ -53,10 +56,13 @@ contract CoveredCallDeallocateTest is CoveredCallSetUp { // uint256 preLiquidityBalance = liquidityOf(address(this), POOL_ID); // (,, uint256 preTotalLiquidity) = dfmm.getReservesAndLiquidity(POOL_ID); + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = minDeltaX - 10; + deltas[1] = minDeltaY - 10; + // TODO: See if we can get a better rounding because the transaction fails // if we don't provide a small slippage toleralance. - bytes memory data = - abi.encode(minDeltaX - 10, minDeltaY - 10, deltaLiquidity); + bytes memory data = abi.encode(deltas, deltaLiquidity); dfmm.deallocate(POOL_ID, data); /* diff --git a/test/G3M/unit/Allocate.t.sol b/test/G3M/unit/Allocate.t.sol index 4d56c9fe..7ee04e00 100644 --- a/test/G3M/unit/Allocate.t.sol +++ b/test/G3M/unit/Allocate.t.sol @@ -9,19 +9,41 @@ contract G3MAllocateTest is G3MSetUp { using FixedPointMathLib for uint256; function test_G3M_allocate() public init { + (uint256[] memory reserves, uint256 liquidity) = + getReservesAndLiquidity(POOL_ID); + uint256[] memory deltas = new uint256[](2); deltas[0] = 1 ether; deltas[1] = 1 ether; bytes memory allocateData = solver.prepareAllocation(POOL_ID, deltas); + (, uint256 deltaLiquidity) = + abi.decode(allocateData, (uint256[], uint256)); + + (deltas) = dfmm.allocate(POOL_ID, allocateData); + + (uint256[] memory adjustedReserves, uint256 adjustedLiquidity) = + getReservesAndLiquidity(POOL_ID); + + assertEq(adjustedReserves[0], reserves[0] + deltas[0]); + assertEq(adjustedReserves[1], reserves[1] + deltas[1]); + assertEq(adjustedLiquidity, liquidity + deltaLiquidity); + } + function test_G3M_allocate_GivenX_large_delta() public init { (uint256[] memory reserves, uint256 liquidity) = - solver.getReservesAndLiquidity(POOL_ID); - (, uint256 maxDeltaY, uint256 deltaLiquidity) = - abi.decode(allocateData, (uint256, uint256, uint256)); + getReservesAndLiquidity(POOL_ID); + + uint256 maxDeltaX = 10_000 ether; + + uint256[] memory deltas = new uint256[](reserves.length); + deltas[0] = maxDeltaX; - uint256 preLiquidityBalance = liquidityOf(address(this), POOL_ID); + bytes memory allocateData = + solver.prepareAllocationProportional(POOL_ID, deltas); + (uint256[] memory usedDeltas, uint256 deltaLiquidity) = + abi.decode(allocateData, (uint256[], uint256)); - (uint256[] memory usedDeltas) = dfmm.allocate(POOL_ID, allocateData); + (deltas) = dfmm.allocate(POOL_ID, allocateData); (uint256[] memory adjustedReserves, uint256 adjustedLiquidity) = getReservesAndLiquidity(POOL_ID); @@ -29,13 +51,6 @@ contract G3MAllocateTest is G3MSetUp { assertEq(adjustedReserves[0], reserves[0] + usedDeltas[0]); assertEq(adjustedReserves[1], reserves[1] + usedDeltas[1]); assertEq(adjustedLiquidity, liquidity + deltaLiquidity); - - /* - assertEq( - preLiquidityBalance + deltaLiquidity, - liquidityOf(address(this), POOL_ID) - ); - */ } function test_G3M_allocate_MultipleTimes() public init { @@ -44,65 +59,59 @@ contract G3MAllocateTest is G3MSetUp { deltas[1] = 1 ether; bytes memory allocateData = solver.prepareAllocation(POOL_ID, deltas); - (, uint256 maxDeltaY, uint256 deltaLiquidity) = - abi.decode(allocateData, (uint256, uint256, uint256)); + deltas[0] = deltas[0].mulDivUp(101, 100); + deltas[1] = deltas[1].mulDivUp(101, 100); + bytes memory allocateData2 = solver.prepareAllocation(POOL_ID, deltas); + (, uint256 deltaLiquidity) = + abi.decode(allocateData2, (uint256[], uint256)); - bytes memory data = abi.encode( - deltas[0].mulDivUp(101, 100), - deltas[1].mulDivUp(101, 100), - deltaLiquidity - ); - dfmm.allocate(POOL_ID, data); - dfmm.allocate(POOL_ID, data); + dfmm.allocate(POOL_ID, allocateData); + dfmm.allocate(POOL_ID, allocateData2); } /// todo: need to replace this with proper min liquidity minted checks function test_G3M_allocate_RevertsIfMoreThanMaxDeltaX() public init { - uint256[] memory deltas = new uint256[](2); - deltas[0] = 1 ether; - deltas[1] = 1 ether; - bytes memory allocateData = solver.prepareAllocation(POOL_ID, deltas); + skip(); + // todo: adjust to check for liquidity slippage + } - (, uint256 maxDeltaY, uint256 deltaLiquidity) = - abi.decode(allocateData, (uint256, uint256, uint256)); + function test_G3M_allocate_GivenY() public init { + (uint256[] memory reserves, uint256 liquidity) = + getReservesAndLiquidity(POOL_ID); - bytes memory data = abi.encode(deltas[0] - 1, maxDeltaY, deltaLiquidity); - vm.expectRevert(); - dfmm.allocate(POOL_ID, data); - } + uint256 maxDeltaY = 0.1 ether; + uint256[] memory deltas = new uint256[](reserves.length); + deltas[1] = maxDeltaY; - /// todo: need to replace this with proper min liquidity minted checks - function test_G3M_allocate_RevertsIfMoreThanMaxDeltaY() public init { - uint256[] memory deltas = new uint256[](2); - deltas[0] = 1 ether; - deltas[1] = 1 ether; - bytes memory allocateData = solver.prepareAllocation(POOL_ID, deltas); + bytes memory allocateData = + solver.prepareAllocationProportional(POOL_ID, deltas); + + (uint256[] memory usedDeltas, uint256 deltaLiquidity) = + abi.decode(allocateData, (uint256[], uint256)); - (, uint256 maxDeltaY, uint256 deltaLiquidity) = - abi.decode(allocateData, (uint256, uint256, uint256)); + (deltas) = dfmm.allocate(POOL_ID, allocateData); - bytes memory data = abi.encode(deltas[0], deltas[1] - 1, deltaLiquidity); - vm.expectRevert(); - dfmm.allocate(POOL_ID, data); + (uint256[] memory adjustedReserves, uint256 adjustedLiquidity) = + getReservesAndLiquidity(POOL_ID); + + assertEq(adjustedReserves[0], reserves[0] + usedDeltas[0]); + assertEq(adjustedReserves[1], reserves[1] + usedDeltas[1]); + assertEq(adjustedLiquidity, liquidity + deltaLiquidity); } function test_G3M_allocate_ReceiveAppropriateLpTokens() public init_100 { - (, uint256 initialL) = getReservesAndLiquidity(POOL_ID); + (uint256[] memory reserves, uint256 initialL) = getReservesAndLiquidity(POOL_ID); Pool memory pool = dfmm.pools(POOL_ID); LPToken liquidityToken = LPToken(pool.liquidityToken); uint256 startBalance = liquidityToken.balanceOf(address(this)); - uint256[] memory deltas = new uint256[](2); - deltas[0] = 100 ether; + uint[] memory deltas = new uint[](reserves.length); deltas[1] = 100 ether; - bytes memory allocateData = solver.prepareAllocation(POOL_ID, deltas); - - (uint256 maxDeltaX,, uint256 deltaLiquidity) = - abi.decode(allocateData, (uint256, uint256, uint256)); - bytes memory data = abi.encode(maxDeltaX, deltas[1], deltaLiquidity); + + bytes memory allocateData = solver.prepareAllocationProportional(POOL_ID, deltas); - dfmm.allocate(POOL_ID, data); + dfmm.allocate(POOL_ID, allocateData); (, uint256 nextL) = getReservesAndLiquidity(POOL_ID); uint256 endBalance = liquidityToken.balanceOf(address(this)); diff --git a/test/LogNormal/unit/Allocate.t.sol b/test/LogNormal/unit/Allocate.t.sol index 4b813d84..2f8ee4bd 100644 --- a/test/LogNormal/unit/Allocate.t.sol +++ b/test/LogNormal/unit/Allocate.t.sol @@ -64,8 +64,8 @@ contract LogNormalAllocateTest is LogNormalSetUp { bool swapXForY = true; - (bool valid, uint256 amountOut,, bytes memory payload) = - solver.simulateSwap(POOL_ID, swapXForY, deltaX); + (bool valid, uint256 amountOut, bytes memory payload) = + solver.prepareSwap(POOL_ID, 0, 1, deltaX); console2.log("Amount out: ", amountOut); @@ -123,8 +123,8 @@ contract LogNormalAllocateTest is LogNormalSetUp { bool swapXForY = true; - (bool valid, uint256 amountOut,, bytes memory payload) = - solver.simulateSwap(POOL_ID, swapXForY, deltaX); + (bool valid, uint256 amountOut, bytes memory payload) = + solver.prepareSwap(POOL_ID, 0, 1, deltaX); console2.log("Estimated delta y given delta x: ", amountOut); diff --git a/test/NTokenGeometricMean/NTokenGeometricMean.t.sol b/test/NTokenGeometricMean/NTokenGeometricMean.t.sol index cc113511..02de9259 100644 --- a/test/NTokenGeometricMean/NTokenGeometricMean.t.sol +++ b/test/NTokenGeometricMean/NTokenGeometricMean.t.sol @@ -192,9 +192,13 @@ contract NTokenGeometricMeanTest is Test { /// @dev `forge test --match-test test_4_token_single_sided_allocate -vvv` function test_4_token_single_sided_allocate() public basic { + uint256[] memory deltas = createTokenDeltas(1 ether); + bytes memory proportionalData = solver.prepareAllocationProportional( + POOL_ID, deltas + ); // Find the deltas of an equal proportion of 1 ether of each token. Also get the array. (uint256[] memory amounts, uint256 dLiquidity) = - solver.getAllocationDeltasGivenDeltaT(POOL_ID, 0, ONE); + abi.decode(proportionalData, (uint256[], uint256)); console.log(amounts[0], dLiquidity); diff --git a/test/SYCoveredCall/unit/SetUp.sol b/test/SYCoveredCall/unit/SetUp.sol index 89c0ea0a..ffc91768 100644 --- a/test/SYCoveredCall/unit/SetUp.sol +++ b/test/SYCoveredCall/unit/SetUp.sol @@ -55,6 +55,8 @@ contract SYCoveredCallSetUp is SetUp { } function setUp() public override { + vm.envString("MAINNET_RPC_URL"); // fails if cant find it. + vm.createSelectFork({ urlOrAlias: "mainnet", blockNumber: 19_662_269 }); SetUp.setUp(); (SY, PT, YT) = IPMarket(market).readTokens();