diff --git a/evm/interfaces/IPairFunctions.sol b/evm/interfaces/IPairFunctions.sol index 68656fc..398cb05 100644 --- a/evm/interfaces/IPairFunctions.sol +++ b/evm/interfaces/IPairFunctions.sol @@ -15,7 +15,7 @@ import "interfaces/IPairFunctionsTypes.sol"; /// @dev Last but not least, the price function is the derivative of the swap /// @dev function. It represents the best possible price a user can get from a /// @dev pair after swapping x of the specified token. -/// @dev During calls to price, swap and getLimits, the caller can be assumed to +/// @dev During calls to swap and getLimits, the caller can be assumed to /// @dev have the required sell or buy token balance as well as unlimited approvals /// @dev to this contract. interface IPairFunctions is IPairFunctionTypes { @@ -46,7 +46,11 @@ interface IPairFunctions is IPairFunctionTypes { /// @dev the swap and change the state of the evm accordingly. /// @dev Please include a gas usage estimate for each amount. This can be achieved /// @dev e.g. by using the `gasleft()` function. - /// @dev + /// @dev The return type trade, has a price attribute which should contain the + /// value of `price(specifiedAmount)`. As this is optional, defined via + /// `Capability.PriceFunction`, it is valid to return a zero value for this + /// price in that case it will be estimated numerically. To return zero use + /// Fraction(0, 1). /// @param pairId The ID of the trading pair. /// @param sellToken The token being sold. /// @param buyToken The token being bought. @@ -79,10 +83,6 @@ interface IPairFunctions is IPairFunctionTypes { external returns (Capabilities[] memory); - /// @notice Minimum gas usage of exchange logic excluding transfers. - /// @return gasUsage the amount of gas used by the exchange logic - function minGasUsage() external view returns (uint256); - /// @notice Retrieves the tokens in the selected pair. /// @dev Mainly used for testing as this is redundant with the required substreams /// @dev implementation. diff --git a/evm/interfaces/IPairFunctionsTypes.sol b/evm/interfaces/IPairFunctionsTypes.sol index 68364f8..ec0c22f 100644 --- a/evm/interfaces/IPairFunctionsTypes.sol +++ b/evm/interfaces/IPairFunctionsTypes.sol @@ -12,9 +12,9 @@ interface IPairFunctionTypes { } /// @dev The Capabilities enum represents possible features of a trading pair. - enum Capabilities - // Support SwapSide.Sell values (required) - { + enum Capabilities { + Unset, + // Support SwapSide.Sell values (required) SellSide, // Support SwapSide.Buy values (optional) BuySide, diff --git a/evm/src/uniswap-v2/UniswapV2PairFunctions.sol b/evm/src/uniswap-v2/UniswapV2PairFunctions.sol index 12a9b78..b4f4dbb 100644 --- a/evm/src/uniswap-v2/UniswapV2PairFunctions.sol +++ b/evm/src/uniswap-v2/UniswapV2PairFunctions.sol @@ -36,9 +36,6 @@ contract UniswapV2PairFunctions is IPairFunctions { pure returns (Fraction memory) { - if (amountIn == 0) { - return Fraction(0, 0); - } if (reserveIn == 0 || reserveOut == 0) { revert Unavailable("At least one reserve is zero!"); } @@ -186,7 +183,7 @@ contract UniswapV2PairFunctions is IPairFunctions { override returns (Capabilities[] memory capabilities) { - capabilities = new Capabilities[](10); + capabilities = new Capabilities[](3); capabilities[0] = Capabilities.SellSide; capabilities[1] = Capabilities.BuySide; capabilities[2] = Capabilities.PriceFunction; @@ -219,10 +216,6 @@ contract UniswapV2PairFunctions is IPairFunctions { ids[i] = bytes20(factory.allPairs(offset + i)); } } - - function minGasUsage() external view returns (uint256) { - return 30000; - } } interface IUniswapV2Pair { diff --git a/evm/test/UniswapV2PairFunction.t.sol b/evm/test/UniswapV2PairFunction.t.sol index 088291f..60f49b0 100644 --- a/evm/test/UniswapV2PairFunction.t.sol +++ b/evm/test/UniswapV2PairFunction.t.sol @@ -19,7 +19,7 @@ contract UniswapV2PairFunctionTest is Test, IPairFunctionTypes { UniswapV2PairFunctions(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f); } - function testPriceFuzz(uint256 amount0, uint256 amount1) public view { + function testPriceFuzz(uint256 amount0, uint256 amount1) public { bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); uint256[] memory limits = pairFunctions.getLimits(pair, SwapSide.Sell); vm.assume(amount0 < limits[0]); @@ -29,7 +29,13 @@ contract UniswapV2PairFunctionTest is Test, IPairFunctionTypes { amounts[0] = amount0; amounts[1] = amount1; - pairFunctions.price(pair, WETH, USDC, amounts); + Fraction[] memory prices = + pairFunctions.price(pair, WETH, USDC, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].nominator, 0); + assertGt(prices[i].denominator, 0); + } } function testPriceDecreasing() public { @@ -43,8 +49,10 @@ contract UniswapV2PairFunctionTest is Test, IPairFunctionTypes { Fraction[] memory prices = pairFunctions.price(pair, WETH, USDC, amounts); - for (uint256 i = 1; i < 99; i++) { + for (uint256 i = 0; i < 99; i++) { assertEq(compareFractions(prices[i], prices[i + 1]), 1); + assertGt(prices[i].denominator, 0); + assertGt(prices[i + 1].denominator, 0); } } @@ -109,4 +117,16 @@ contract UniswapV2PairFunctionTest is Test, IPairFunctionTypes { function testSwapBuyIncreasing() public { executeIncreasingSwaps(SwapSide.Buy); } + + function testGetCapabilities(bytes32 pair, address t0, address t1) public { + Capabilities[] memory res = + pairFunctions.getCapabilities(pair, IERC20(t0), IERC20(t1)); + + assertEq(res.length, 3); + } + + function testGetLimits() public { + bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); + pairFunctions.getLimits(pair, SwapSide.Sell); + } }