@@ -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 /**********************************************************************************************/
@@ -891,7 +926,101 @@ contract ForeignController is AccessControl {
891926 })
892927 );
893928 }
929+
930+ /**********************************************************************************************/
931+ /*** Uniswap V4 functions ***/
932+ /**********************************************************************************************/
933+
934+ function mintPositionUniswapV4 (
935+ bytes32 poolId ,
936+ int24 tickLower ,
937+ int24 tickUpper ,
938+ uint128 liquidity ,
939+ uint256 amount0Max ,
940+ uint256 amount1Max
941+ )
942+ external
943+ {
944+ _checkRole (RELAYER);
945+
946+ UniswapV4Lib.mintPosition ({
947+ proxy : address (proxy),
948+ rateLimits : address (rateLimits),
949+ poolId : poolId,
950+ tickLower : tickLower,
951+ tickUpper : tickUpper,
952+ liquidity : liquidity,
953+ amount0Max : amount0Max,
954+ amount1Max : amount1Max,
955+ tickLimits : uniswapV4TickLimits
956+ });
957+ }
894958
959+ function increaseLiquidityUniswapV4 (
960+ bytes32 poolId ,
961+ uint256 tokenId ,
962+ uint128 liquidityIncrease ,
963+ uint256 amount0Max ,
964+ uint256 amount1Max
965+ )
966+ external
967+ {
968+ _checkRole (RELAYER);
969+
970+ UniswapV4Lib.increasePosition ({
971+ proxy : address (proxy),
972+ rateLimits : address (rateLimits),
973+ poolId : poolId,
974+ tokenId : tokenId,
975+ liquidityIncrease : liquidityIncrease,
976+ amount0Max : amount0Max,
977+ amount1Max : amount1Max,
978+ tickLimits : uniswapV4TickLimits
979+ });
980+ }
981+
982+ function decreaseLiquidityUniswapV4 (
983+ bytes32 poolId ,
984+ uint256 tokenId ,
985+ uint128 liquidityDecrease ,
986+ uint256 amount0Min ,
987+ uint256 amount1Min
988+ )
989+ external
990+ {
991+ _checkRole (RELAYER);
992+
993+ UniswapV4Lib.decreasePosition ({
994+ proxy : address (proxy),
995+ rateLimits : address (rateLimits),
996+ poolId : poolId,
997+ tokenId : tokenId,
998+ liquidityDecrease : liquidityDecrease,
999+ amount0Min : amount0Min,
1000+ amount1Min : amount1Min
1001+ });
1002+ }
1003+
1004+ function swapUniswapV4 (
1005+ bytes32 poolId ,
1006+ address tokenIn ,
1007+ uint128 amountIn ,
1008+ uint128 amountOutMin
1009+ )
1010+ external
1011+ {
1012+ _checkRole (RELAYER);
1013+
1014+ UniswapV4Lib.swap ({
1015+ proxy : address (proxy),
1016+ rateLimits : address (rateLimits),
1017+ poolId : poolId,
1018+ tokenIn : tokenIn,
1019+ amountIn : amountIn,
1020+ amountOutMin : amountOutMin,
1021+ maxSlippage : maxSlippages[address (uint160 (uint256 (poolId)))]
1022+ });
1023+ }
8951024
8961025 /**********************************************************************************************/
8971026 /*** Internal helper functions ***/
0 commit comments