From 9411fc2b67439c058c51e348313a18934c966cd9 Mon Sep 17 00:00:00 2001 From: czanella Date: Sat, 3 Aug 2024 10:53:25 +0100 Subject: [PATCH 1/3] Discount fees from USV2 getPriceAt logic add marginal price capability --- evm/src/uniswap-v2/UniswapV2SwapAdapter.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol b/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol index 679a6b4..4cf969b 100644 --- a/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol +++ b/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol @@ -54,13 +54,10 @@ contract UniswapV2SwapAdapter is ISwapAdapter { if (reserveIn == 0 || reserveOut == 0) { revert Unavailable("At least one reserve is zero!"); } - uint256 amountInWithFee = amountIn * 997; - uint256 numerator = amountInWithFee * reserveOut; - uint256 denominator = (reserveIn * 1000) + amountInWithFee; - uint256 amountOut = numerator / denominator; + uint256 amountOut = getAmountOut(amountIn, reserveIn, reserveOut); uint256 newReserveOut = reserveOut - amountOut; uint256 newReserveIn = reserveIn + amountIn; - return Fraction(newReserveOut * 1000, newReserveIn * 997); + return Fraction(newReserveOut * 997, newReserveIn * 1000); } /// @inheritdoc ISwapAdapter @@ -233,10 +230,11 @@ contract UniswapV2SwapAdapter is ISwapAdapter { override returns (Capability[] memory capabilities) { - capabilities = new Capability[](3); + capabilities = new Capability[](4); capabilities[0] = Capability.SellOrder; capabilities[1] = Capability.BuyOrder; capabilities[2] = Capability.PriceFunction; + capabilities[3] = Capability.MarginalPrice; } /// @inheritdoc ISwapAdapter From 30bd0c2a5c495604ab49157619757345376ed72c Mon Sep 17 00:00:00 2001 From: czanella Date: Sat, 3 Aug 2024 10:54:25 +0100 Subject: [PATCH 2/3] Fix some assertions in integration test The foundation is: marginal price > executed price > price after swap. And this check is verified for multiple amounts --- evm/test/AdapterTest.sol | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/evm/test/AdapterTest.sol b/evm/test/AdapterTest.sol index 643064f..188eab3 100644 --- a/evm/test/AdapterTest.sol +++ b/evm/test/AdapterTest.sol @@ -83,6 +83,8 @@ contract AdapterTest is Test, ISwapAdapterTypes { console2.log("TEST: Testing behavior for price at 0"); assertGt(prices[0].numerator, 0, "Nominator shouldn't be 0"); assertGt(prices[0].denominator, 0, "Denominator shouldn't be 0"); + uint256 priceAtZero = fractionToInt(prices[0]); + console2.log("TEST: Price at 0: %d", priceAtZero); Trade memory trade; deal(tokenIn, address(this), 5 * amounts[amounts.length - 1]); @@ -104,14 +106,14 @@ contract AdapterTest is Test, ISwapAdapterTypes { uint256 executedPrice = trade.calculatedAmount * pricePrecision / amounts[j]; uint256 priceAfterSwap = fractionToInt(trade.price); - console2.log("TEST: - Pool price: %d", priceAtAmount); console2.log("TEST: - Executed price: %d", executedPrice); + console2.log("TEST: - Price at amount: %d", priceAtAmount); console2.log("TEST: - Price after swap: %d", priceAfterSwap); if (hasPriceImpact) { assertGe( - priceAtAmount, executedPrice, + priceAtAmount, "Price should be greated than executed price." ); assertGt( @@ -120,24 +122,24 @@ contract AdapterTest is Test, ISwapAdapterTypes { "Executed price should be greater than price after swap." ); assertGt( - priceAtAmount, - priceAfterSwap, + priceAtZero, + executedPrice, "Price should be greated than price after swap." ); } else { assertGe( - priceAtAmount, - executedPrice, - "Price should be greater or equal to executed price." - ); - assertGe( - executedPrice, + priceAtZero, priceAfterSwap, "Executed price should be or equal to price after swap." ); assertGe( + priceAtZero, priceAtAmount, - priceAfterSwap, + "Executed price should be or equal to price after swap." + ); + assertGe( + priceAtZero, + executedPrice, "Price should be or equal to price after swap." ); } From 1ab96ce292bb2aba8a7358b8320d40c1e2a024c3 Mon Sep 17 00:00:00 2001 From: czanella Date: Mon, 5 Aug 2024 10:32:43 +0100 Subject: [PATCH 3/3] Update other failing tests --- evm/test/AdapterTest.sol | 7 ++++--- evm/test/BalancerV2SwapAdapter.t.sol | 4 ++-- evm/test/UniswapV2SwapAdapter.t.sol | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/evm/test/AdapterTest.sol b/evm/test/AdapterTest.sol index 188eab3..76950ea 100644 --- a/evm/test/AdapterTest.sol +++ b/evm/test/AdapterTest.sol @@ -19,9 +19,10 @@ contract AdapterTest is Test, ISwapAdapterTypes { // sell amounts. Asserts that the prices behaves as expected. // @param adapter The swap adapter to test // @param poolIds The list of pool ids to test - function testPoolBehaviour(ISwapAdapter adapter, bytes32[] memory poolIds) - public - { + function runPoolBehaviourTest( + ISwapAdapter adapter, + bytes32[] memory poolIds + ) public { bool hasPriceImpact = !hasCapability( adapter.getCapabilities(poolIds[0], address(0), address(0)), Capability.ConstantPrice diff --git a/evm/test/BalancerV2SwapAdapter.t.sol b/evm/test/BalancerV2SwapAdapter.t.sol index e4cb188..e75933a 100644 --- a/evm/test/BalancerV2SwapAdapter.t.sol +++ b/evm/test/BalancerV2SwapAdapter.t.sol @@ -207,7 +207,7 @@ contract BalancerV2SwapAdapterTest is AdapterTest { { Capability[] memory res = adapter.getCapabilities(pool, t0, t1); - assertEq(res.length, 3); + assertEq(res.length, 4); assertEq(uint256(res[0]), uint256(Capability.SellOrder)); assertEq(uint256(res[1]), uint256(Capability.BuyOrder)); assertEq(uint256(res[2]), uint256(Capability.PriceFunction)); @@ -232,6 +232,6 @@ contract BalancerV2SwapAdapterTest is AdapterTest { function testBalancerV2PoolBehaviour() public { bytes32[] memory poolIds = new bytes32[](1); poolIds[0] = B_80BAL_20WETH_POOL_ID; - testPoolBehaviour(adapter, poolIds); + runPoolBehaviourTest(adapter, poolIds); } } diff --git a/evm/test/UniswapV2SwapAdapter.t.sol b/evm/test/UniswapV2SwapAdapter.t.sol index d3aebbd..4ed3eb7 100644 --- a/evm/test/UniswapV2SwapAdapter.t.sol +++ b/evm/test/UniswapV2SwapAdapter.t.sol @@ -151,7 +151,7 @@ contract UniswapV2PairFunctionTest is AdapterTest { function testGetCapabilities(bytes32 pair, address t0, address t1) public { Capability[] memory res = adapter.getCapabilities(pair, t0, t1); - assertEq(res.length, 3); + assertEq(res.length, 4); } function testGetLimits() public { @@ -164,6 +164,6 @@ contract UniswapV2PairFunctionTest is AdapterTest { function testUsv2PoolBehaviour() public { bytes32[] memory poolIds = new bytes32[](1); poolIds[0] = bytes32(bytes20(USDC_WETH_PAIR)); - testPoolBehaviour(adapter, poolIds); + runPoolBehaviourTest(adapter, poolIds); } }