@@ -25,6 +25,7 @@ import { PendleLib } from "./libraries/PendleLib.sol";
2525import { CCTPLib } from "./libraries/CCTPLib.sol " ;
2626import { ERC20Lib } from "./libraries/common/ERC20Lib.sol " ;
2727import { UniswapV3Lib } from "./libraries/UniswapV3Lib.sol " ;
28+ import { UniswapV4Lib } from "./libraries/UniswapV4Lib.sol " ;
2829
2930import { ISwapRouter, INonfungiblePositionManager } from "./interfaces/UniswapV3Interfaces.sol " ;
3031import { ICentrifugeV3VaultLike, IAsyncRedeemManagerLike, ISpokeLike } from "./interfaces/CentrifugeInterfaces.sol " ;
@@ -66,6 +67,12 @@ contract ForeignController is AccessControl {
6667 event UniswapV3PoolUpperTickUpdated (address indexed pool , int24 upperTick );
6768 event UniswapV3PoolMaxTickDeltaSet (address indexed pool , uint24 maxTickDelta );
6869 event UniswapV3PoolTwapSecondsAgoUpdated (address indexed pool , uint32 twapSecondsAgo );
70+ event UniswapV4TickLimitsSet (
71+ bytes32 indexed poolId ,
72+ int24 tickLowerMin ,
73+ int24 tickUpperMax ,
74+ uint24 maxTickSpacing
75+ );
6976
7077 /**********************************************************************************************/
7178 /*** State variables ***/
@@ -124,6 +131,9 @@ contract ForeignController is AccessControl {
124131 // ERC4626 exchange rate thresholds (1e36 precision)
125132 mapping (address token = > uint256 maxExchangeRate ) public maxExchangeRates;
126133
134+ // Uniswap V4 tick ranges
135+ mapping (bytes32 poolId = > UniswapV4Lib.TickLimits tickLimits ) public uniswapV4TickLimits;
136+
127137 /**********************************************************************************************/
128138 /*** Initialization ***/
129139 /**********************************************************************************************/
@@ -268,6 +278,31 @@ contract ForeignController is AccessControl {
268278 );
269279 }
270280
281+ function setUniswapV4TickLimits (
282+ bytes32 poolId ,
283+ int24 tickLowerMin ,
284+ int24 tickUpperMax ,
285+ uint24 maxTickSpacing
286+ )
287+ external
288+ {
289+ _checkRole (DEFAULT_ADMIN_ROLE);
290+
291+ require (
292+ ((tickLowerMin == 0 ) && (tickUpperMax == 0 ) && (maxTickSpacing == 0 )) ||
293+ ((maxTickSpacing > 0 ) && (tickLowerMin < tickUpperMax)),
294+ "FC/invalid-ticks "
295+ );
296+
297+ uniswapV4TickLimits[poolId] = UniswapV4Lib.TickLimits ({
298+ tickLowerMin : tickLowerMin,
299+ tickUpperMax : tickUpperMax,
300+ maxTickSpacing : maxTickSpacing
301+ });
302+
303+ emit UniswapV4TickLimitsSet (poolId, tickLowerMin, tickUpperMax, maxTickSpacing);
304+ }
305+
271306 /**********************************************************************************************/
272307 /*** Freezer functions ***/
273308 /**********************************************************************************************/
@@ -877,7 +912,101 @@ contract ForeignController is AccessControl {
877912 })
878913 );
879914 }
915+
916+ /**********************************************************************************************/
917+ /*** Uniswap V4 functions ***/
918+ /**********************************************************************************************/
919+
920+ function mintPositionUniswapV4 (
921+ bytes32 poolId ,
922+ int24 tickLower ,
923+ int24 tickUpper ,
924+ uint128 liquidity ,
925+ uint256 amount0Max ,
926+ uint256 amount1Max
927+ )
928+ external
929+ {
930+ _checkRole (RELAYER);
931+
932+ UniswapV4Lib.mintPosition ({
933+ proxy : address (proxy),
934+ rateLimits : address (rateLimits),
935+ poolId : poolId,
936+ tickLower : tickLower,
937+ tickUpper : tickUpper,
938+ liquidity : liquidity,
939+ amount0Max : amount0Max,
940+ amount1Max : amount1Max,
941+ tickLimits : uniswapV4TickLimits
942+ });
943+ }
880944
945+ function increaseLiquidityUniswapV4 (
946+ bytes32 poolId ,
947+ uint256 tokenId ,
948+ uint128 liquidityIncrease ,
949+ uint256 amount0Max ,
950+ uint256 amount1Max
951+ )
952+ external
953+ {
954+ _checkRole (RELAYER);
955+
956+ UniswapV4Lib.increasePosition ({
957+ proxy : address (proxy),
958+ rateLimits : address (rateLimits),
959+ poolId : poolId,
960+ tokenId : tokenId,
961+ liquidityIncrease : liquidityIncrease,
962+ amount0Max : amount0Max,
963+ amount1Max : amount1Max,
964+ tickLimits : uniswapV4TickLimits
965+ });
966+ }
967+
968+ function decreaseLiquidityUniswapV4 (
969+ bytes32 poolId ,
970+ uint256 tokenId ,
971+ uint128 liquidityDecrease ,
972+ uint256 amount0Min ,
973+ uint256 amount1Min
974+ )
975+ external
976+ {
977+ _checkRole (RELAYER);
978+
979+ UniswapV4Lib.decreasePosition ({
980+ proxy : address (proxy),
981+ rateLimits : address (rateLimits),
982+ poolId : poolId,
983+ tokenId : tokenId,
984+ liquidityDecrease : liquidityDecrease,
985+ amount0Min : amount0Min,
986+ amount1Min : amount1Min
987+ });
988+ }
989+
990+ function swapUniswapV4 (
991+ bytes32 poolId ,
992+ address tokenIn ,
993+ uint128 amountIn ,
994+ uint128 amountOutMin
995+ )
996+ external
997+ {
998+ _checkRole (RELAYER);
999+
1000+ UniswapV4Lib.swap ({
1001+ proxy : address (proxy),
1002+ rateLimits : address (rateLimits),
1003+ poolId : poolId,
1004+ tokenIn : tokenIn,
1005+ amountIn : amountIn,
1006+ amountOutMin : amountOutMin,
1007+ maxSlippage : maxSlippages[address (uint160 (uint256 (poolId)))]
1008+ });
1009+ }
8811010
8821011 /**********************************************************************************************/
8831012 /*** Internal helper functions ***/
0 commit comments