// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import {IUniswapV3Pool} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; import {IWETH9} from "../../src/interfaces/IWETH9.sol"; import {Kraiken} from "../../src/Kraiken.sol"; import {TickMath} from "@aperture/uni-v3-lib/TickMath.sol"; /** * @title SwapExecutor * @notice Helper contract to execute swaps on Uniswap V3 pools for analysis scripts * @dev Extracted from analysis scripts to avoid code duplication */ contract SwapExecutor { IUniswapV3Pool public pool; IWETH9 public weth; Kraiken public harberg; bool public token0isWeth; constructor(IUniswapV3Pool _pool, IWETH9 _weth, Kraiken _harberg, bool _token0isWeth) { pool = _pool; weth = _weth; harberg = _harberg; token0isWeth = _token0isWeth; } function executeBuy(uint256 amount, address recipient) external { // For buying HARB with WETH, we're swapping in the direction that increases HARB price // zeroForOne = true if WETH is token0, false if WETH is token1 bool zeroForOne = token0isWeth; // Set appropriate price limit based on swap direction uint160 sqrtPriceLimitX96; if (zeroForOne) { // Price goes down (in terms of token0/token1 ratio) sqrtPriceLimitX96 = TickMath.MIN_SQRT_RATIO + 1; } else { // Price goes up sqrtPriceLimitX96 = TickMath.MAX_SQRT_RATIO - 1; } try pool.swap( recipient, zeroForOne, int256(amount), sqrtPriceLimitX96, "" ) {} catch { // Swap failed, likely due to extreme price - ignore } } function executeSell(uint256 amount, address recipient) external { // For selling HARB for WETH, we're swapping in the direction that decreases HARB price // zeroForOne = false if WETH is token0, true if WETH is token1 bool zeroForOne = !token0isWeth; // Set appropriate price limit based on swap direction uint160 sqrtPriceLimitX96; if (zeroForOne) { // Price goes down (in terms of token0/token1 ratio) sqrtPriceLimitX96 = TickMath.MIN_SQRT_RATIO + 1; } else { // Price goes up sqrtPriceLimitX96 = TickMath.MAX_SQRT_RATIO - 1; } try pool.swap( recipient, zeroForOne, int256(amount), sqrtPriceLimitX96, "" ) {} catch { // Swap failed, likely due to extreme price - ignore } } // Callback required for Uniswap V3 swaps function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata ) external { require(msg.sender == address(pool), "Unauthorized callback"); if (amount0Delta > 0) { IWETH9(pool.token0()).transfer(address(pool), uint256(amount0Delta)); } if (amount1Delta > 0) { IWETH9(pool.token1()).transfer(address(pool), uint256(amount1Delta)); } } }