Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/quoter mixed exact out non v4 #13

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 19 additions & 29 deletions src/MixedQuoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback {
}

/// @dev Fetch an exactIn quote for a V3 Pool on chain
function quoteExactInputSingleV3(QuoteExactInputSingleV3Params memory params)
function quoteExactInputSingleV3(QuoteExactSingleV3Params memory params)
public
override
returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)
Expand All @@ -135,7 +135,7 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback {
try pool.swap(
address(this), // address(0) might cause issues with some tokens
zeroForOne,
params.amountIn.toInt256(),
params.exactAmount.toInt256(),
params.sqrtPriceLimitX96 == 0
? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)
: params.sqrtPriceLimitX96,
Expand All @@ -151,31 +151,31 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback {
*/

/// @dev Fetch an exactIn quote for a V2 pair on chain
function quoteExactInputSingleV2(QuoteExactInputSingleV2Params memory params)
function quoteExactInputSingleV2(QuoteExactSingleV2Params memory params)
public
view
override
returns (uint256 amountOut)
{
(uint256 reserveIn, uint256 reserveOut) =
V3SmartRouterHelper.getReserves(factoryV2, params.tokenIn, params.tokenOut);
amountOut = V3SmartRouterHelper.getAmountOut(params.amountIn, reserveIn, reserveOut);
amountOut = V3SmartRouterHelper.getAmountOut(params.exactAmount, reserveIn, reserveOut);
}

/**
* Stable *************************************************
*/

/// @dev Fetch an exactIn quote for a Stable pair on chain
function quoteExactInputSingleStable(QuoteExactInputSingleStableParams memory params)
function quoteExactInputSingleStable(QuoteExactInputStableParams memory params)
public
view
override
returns (uint256 amountOut)
{
(uint256 i, uint256 j, address swapContract) =
V3SmartRouterHelper.getStableInfo(factoryStable, params.tokenIn, params.tokenOut, params.flag);
amountOut = IStableSwap(swapContract).get_dy(i, j, params.amountIn);
amountOut = IStableSwap(swapContract).get_dy(i, j, params.exactAmount);
}

/**
Expand All @@ -201,25 +201,25 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback {
(tokenIn, tokenOut) = convertNativeToWETH(tokenIn, tokenOut);
// params[actionIndex] is zero bytes
amountIn = quoteExactInputSingleV2(
QuoteExactInputSingleV2Params({tokenIn: tokenIn, tokenOut: tokenOut, amountIn: amountIn})
QuoteExactSingleV2Params({tokenIn: tokenIn, tokenOut: tokenOut, exactAmount: amountIn})
);
} else if (action == MixedQuoterActions.V3_EXACT_INPUT_SINGLE) {
(tokenIn, tokenOut) = convertNativeToWETH(tokenIn, tokenOut);
// params[actionIndex]: abi.encode(fee)
uint24 fee = abi.decode(params[actionIndex], (uint24));
(uint256 _amountOut,,,) = quoteExactInputSingleV3(
QuoteExactInputSingleV3Params({
QuoteExactSingleV3Params({
tokenIn: tokenIn,
tokenOut: tokenOut,
amountIn: amountIn,
exactAmount: amountIn,
fee: fee,
sqrtPriceLimitX96: 0
})
);
amountIn = _amountOut;
} else if (action == MixedQuoterActions.V4_CL_EXACT_INPUT_SINGLE) {
QuoteMixedV4ExactInputSingleParams memory clParams =
abi.decode(params[actionIndex], (QuoteMixedV4ExactInputSingleParams));
QuoteMixedV4ExactSingleParams memory clParams =
abi.decode(params[actionIndex], (QuoteMixedV4ExactSingleParams));
(tokenIn, tokenOut) = convertWETHToV4NativeCurency(clParams.poolKey, tokenIn, tokenOut);
bool zeroForOne = tokenIn < tokenOut;
checkV4PoolKeyCurrency(clParams.poolKey, zeroForOne, tokenIn, tokenOut);
Expand All @@ -234,8 +234,8 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback {
);
amountIn = deltaAmounts[zeroForOne ? 1 : 0].toUint256();
} else if (action == MixedQuoterActions.V4_BIN_EXACT_INPUT_SINGLE) {
QuoteMixedV4ExactInputSingleParams memory binParams =
abi.decode(params[actionIndex], (QuoteMixedV4ExactInputSingleParams));
QuoteMixedV4ExactSingleParams memory binParams =
abi.decode(params[actionIndex], (QuoteMixedV4ExactSingleParams));
(tokenIn, tokenOut) = convertWETHToV4NativeCurency(binParams.poolKey, tokenIn, tokenOut);
bool zeroForOne = tokenIn < tokenOut;
checkV4PoolKeyCurrency(binParams.poolKey, zeroForOne, tokenIn, tokenOut);
Expand All @@ -252,23 +252,13 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback {
(tokenIn, tokenOut) = convertNativeToWETH(tokenIn, tokenOut);
// params[actionIndex] is zero bytes
amountIn = quoteExactInputSingleStable(
QuoteExactInputSingleStableParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
amountIn: amountIn,
flag: 2
})
QuoteExactInputStableParams({tokenIn: tokenIn, tokenOut: tokenOut, exactAmount: amountIn, flag: 2})
);
} else if (action == MixedQuoterActions.SS_3_EXACT_INPUT_SINGLE) {
(tokenIn, tokenOut) = convertNativeToWETH(tokenIn, tokenOut);
// params[actionIndex] is zero bytes
amountIn = quoteExactInputSingleStable(
QuoteExactInputSingleStableParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
amountIn: amountIn,
flag: 3
})
QuoteExactInputStableParams({tokenIn: tokenIn, tokenOut: tokenOut, exactAmount: amountIn, flag: 3})
);
} else {
revert UnsupportedAction(action);
Expand All @@ -294,8 +284,8 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback {

uint256 action = uint256(uint8(actions[actionIndex - 1]));
if (action == MixedQuoterActions.V4_CL_EXACT_OUTPUT_SINGLE) {
QuoteMixedV4ExactInputSingleParams memory clParams =
abi.decode(params[actionIndex - 1], (QuoteMixedV4ExactInputSingleParams));
QuoteMixedV4ExactSingleParams memory clParams =
abi.decode(params[actionIndex - 1], (QuoteMixedV4ExactSingleParams));
bool zeroForOne = tokenIn < tokenOut;
checkV4PoolKeyCurrency(clParams.poolKey, zeroForOne, tokenIn, tokenOut);
(int128[] memory deltaAmounts,,) = clQuoter.quoteExactOutputSingle(
Expand All @@ -309,8 +299,8 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback {
);
amountOut = uint256(int256(-deltaAmounts[zeroForOne ? 0 : 1]));
} else if (action == MixedQuoterActions.V4_BIN_EXACT_OUTPUT_SINGLE) {
QuoteMixedV4ExactInputSingleParams memory binParams =
abi.decode(params[actionIndex - 1], (QuoteMixedV4ExactInputSingleParams));
QuoteMixedV4ExactSingleParams memory binParams =
abi.decode(params[actionIndex - 1], (QuoteMixedV4ExactSingleParams));
bool zeroForOne = tokenIn < tokenOut;
checkV4PoolKeyCurrency(binParams.poolKey, zeroForOne, tokenIn, tokenOut);
(int128[] memory deltaAmounts,) = binQuoter.quoteExactOutputSingle(
Expand Down
40 changes: 19 additions & 21 deletions src/interfaces/IMixedQuoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,29 @@ interface IMixedQuoter {
error NoActions();
error UnsupportedAction(uint256 action);

struct QuoteMixedV4ExactInputSingleParams {
struct QuoteMixedV4ExactSingleParams {
PoolKey poolKey;
bytes hookData;
}

struct QuoteExactInputSingleV3Params {
struct QuoteExactSingleV3Params {
address tokenIn;
address tokenOut;
uint256 amountIn;
uint256 exactAmount;
uint24 fee;
uint160 sqrtPriceLimitX96;
}

struct QuoteExactInputSingleV2Params {
struct QuoteExactSingleV2Params {
address tokenIn;
address tokenOut;
uint256 amountIn;
uint256 exactAmount;
}

struct QuoteExactInputSingleStableParams {
struct QuoteExactInputStableParams {
address tokenIn;
address tokenOut;
uint256 amountIn;
uint256 exactAmount;
uint256 flag;
}

Expand All @@ -50,8 +50,8 @@ interface IMixedQuoter {
/// SS_3_EXACT_INPUT_SINGLE params are zero bytes
/// V2_EXACT_INPUT_SINGLE params are zero bytes
/// V3_EXACT_INPUT_SINGLE params are encoded as `uint24 fee`
/// V4_CL_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedV4ExactInputSingleParams`
/// V4_BIN_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedV4ExactInputSingleParams`
/// V4_CL_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedV4ExactSingleParams`
/// V4_BIN_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedV4ExactSingleParams`
/// @param amountIn The amount of the first token to swap
/// @return amountOut The amount of the last token that would be received
function quoteMixedExactInput(
Expand All @@ -65,8 +65,8 @@ interface IMixedQuoter {
/// @param paths The path of the swap, i.e. each token pair in the path
/// @param actions The actions to take for each pair in the path
/// @param params The params for each action in the path
/// V4_CL_EXACT_OUTPUT_SINGLE params are encoded as `QuoteMixedV4ExactInputSingleParams`
/// V4_BIN_EXACT_OUTPUT_SINGLE params are encoded as `QuoteMixedV4ExactInputSingleParams`
/// V4_CL_EXACT_OUTPUT_SINGLE params are encoded as `QuoteMixedV4ExactSingleParams`
/// V4_BIN_EXACT_OUTPUT_SINGLE params are encoded as `QuoteMixedV4ExactSingleParams`
/// @param amountOut The amount of the last token to receive
/// @return amountIn The amount of first token required to be paid
function quoteMixedExactOutput(
Expand All @@ -81,34 +81,32 @@ interface IMixedQuoter {
/// tokenIn The token being swapped in
/// tokenOut The token being swapped out
/// fee The fee of the token pool to consider for the pair
/// amountIn The desired input amount
/// exactAmount The desired input amount
/// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap
/// @return amountOut The amount of `tokenOut` that would be received
/// @return sqrtPriceX96After The sqrt price of the pool after the swap
/// @return initializedTicksCrossed The number of initialized ticks that the swap crossed
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactInputSingleV3(QuoteExactInputSingleV3Params memory params)
function quoteExactInputSingleV3(QuoteExactSingleV3Params memory params)
external
returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate);

/// @notice Returns the amount out received for a given exact input but for a swap of a single V2 pool
/// @param params The params for the quote, encoded as `QuoteExactInputSingleV2Params`
/// @param params The params for the quote, encoded as `QuoteExactSingleV2Params`
/// tokenIn The token being swapped in
/// tokenOut The token being swapped out
/// amountIn The desired input amount
/// exactAmount The desired input amount
/// @return amountOut The amount of `tokenOut` that would be received
function quoteExactInputSingleV2(QuoteExactInputSingleV2Params memory params)
external
returns (uint256 amountOut);
function quoteExactInputSingleV2(QuoteExactSingleV2Params memory params) external returns (uint256 amountOut);

/// @notice Returns the amount out received for a given exact input but for a swap of a single Stable pool
/// @param params The params for the quote, encoded as `QuoteExactInputSingleStableParams`
/// @param params The params for the quote, encoded as `QuoteExactInputStableParams`
/// tokenIn The token being swapped in
/// tokenOut The token being swapped out
/// amountIn The desired input amount
/// exactAmount The desired input amount
/// flag The token amount in a single Stable pool. 2 for 2pool, 3 for 3pool
/// @return amountOut The amount of `tokenOut` that would be received
function quoteExactInputSingleStable(QuoteExactInputSingleStableParams memory params)
function quoteExactInputSingleStable(QuoteExactInputStableParams memory params)
external
returns (uint256 amountOut);

Expand Down
15 changes: 0 additions & 15 deletions src/libraries/external/V3SmartRouterHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,6 @@ library V3SmartRouterHelper {
amountIn = (numerator / denominator) + 1;
}

// performs chained getAmountIn calculations on any number of pairs
function getAmountsIn(address factory, uint256 amountOut, address[] memory path)
internal
view
returns (uint256[] memory amounts)
{
require(path.length >= 2);
amounts = new uint256[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint256 i = path.length - 1; i > 0; i--) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i - 1], path[i]);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}

/**
* V3 *************************************************
*/
Expand Down
Loading
Loading