Kodiak Islands are concentrated liquidity management vaults built on top of Kodiak V3 pools. This guide covers the technical aspects of integrating with Kodiak Islands from a smart contract perspective.
1. Usage with existing/Deployed Islands
What can be achieved
Depositing into existing Islands
Withdrawing from existing Islands
Checking current island position
Checking current fee earned
Calling rebalance to invest any pending fees
Prerequisites
Before integrating with Kodiak Islands, you should understand:
Kodiak V3 concentrated liquidity concepts
ERC20 token standards and approvals
Basic understanding of what's slippage and slippage protection mechanisms
Deployed contract addresses
Understanding of token ratio that is needed to deposit tokens into the island.
Finding the correct deposit params for double sided token deposits.
Finding the correct deposit and swap params for single sided token deposits.
Core Contracts
The main contracts involved for integration with existing islands are:
Island Router Contract: Handles complex operations like zaps and slippage protection
Island Contract: The actual vault contract managing the Kodiak V3 position
Integration Examples
1. Basic Position Information
interface IKodiakIsland {
function getUnderlyingBalances() external view returns (uint256 amount0Current, uint256 amount1Current);
function token0() external view returns (IERC20);
function token1() external view returns (IERC20);
function pool() external view returns (IUniswapV3Pool);
function lowerTick() external view returns (int24);
function upperTick() external view returns (int24);
}
2. Depositing with Both Tokens
interface IKodiakIslandRouter {
function addLiquidity(
IKodiakIsland island,
uint256 amount0Max,
uint256 amount1Max,
uint256 amount0Min,
uint256 amount1Min,
uint256 amountSharesMin,
address receiver
) external returns (uint256 amount0, uint256 amount1, uint256 mintAmount);
}
contract IslandDepositor {
IKodiakIslandRouter public immutable router;
constructor(address _router) {
router = IKodiakIslandRouter(_router);
}
function deposit(
IKodiakIsland island,
uint256 amount0,
uint256 amount1,
uint256 slippageBPS,
uint minShares
) external returns (uint256 mintAmount) {
// Transfer tokens to this contract
IERC20(island.token0()).transferFrom(msg.sender, address(this), amount0);
IERC20(island.token1()).transferFrom(msg.sender, address(this), amount1);
// Approve router
IERC20(island.token0()).approve(address(router), amount0);
IERC20(island.token1()).approve(address(router), amount1);
// Calculate minimum amounts with slippage
uint256 amount0Min = amount0 * (10000 - slippageBPS) / 10000;
uint256 amount1Min = amount1 * (10000 - slippageBPS) / 10000;
// Add liquidity
(,, mintAmount) = router.addLiquidity(
island,
amount0,
amount1,
amount0Min,
amount1Min,
minShares, // Min shares, can be calculated based on simulation before calling this
msg.sender
);
}
}
3. Single Token Deposits (Zaps)
For single token deposits, the swap calldata needs to be prepared off-chain using the Kodiak Quoter API. The process involves:
Getting the optimal swap amount using the formula: