Skip to main content

Provide liquidity

Liquidity on BarkSwap is concentrated: you choose a price range (tickLowertickUpper) and your capital is only active within it. Positions are minted as ERC-721 NFTs by the NonfungiblePositionManager (NPM).

Parameter shape

Like swaps, the NPM mint struct takes a deployer field instead of a fee tier. Pass address(0) for the default deployer.

1. Approve both tokens

import { Contract, MaxUint256 } from 'ethers';

const NPM = '0xf596329a6c7E03F0708199cB5435f86783DB4302';
const ERC20_ABI = ['function approve(address spender, uint256 amount) returns (bool)'];

for (const tokenAddr of [token0, token1]) {
const token = new Contract(tokenAddr, ERC20_ABI, signer);
await (await token.approve(NPM, MaxUint256)).wait();
}

token0 and token1 must be sorted ascending by address (token0 < token1), matching the pool's ordering.

2. Mint a position

const NPM_ABI = [
'function mint((address token0,address token1,address deployer,int24 tickLower,int24 tickUpper,uint256 amount0Desired,uint256 amount1Desired,uint256 amount0Min,uint256 amount1Min,address recipient,uint256 deadline)) payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1)',
];
const ZERO = '0x0000000000000000000000000000000000000000';

const npm = new Contract(NPM, NPM_ABI, signer);

const tx = await npm.mint({
token0,
token1,
deployer: ZERO,
tickLower, // must be a multiple of the pool tickSpacing
tickUpper,
amount0Desired,
amount1Desired,
amount0Min: 0n, // set real minimums in production to bound slippage
amount1Min: 0n,
recipient: await signer.getAddress(),
deadline: Math.floor(Date.now() / 1000) + 60 * 10,
});
const receipt = await tx.wait();
// The new position's tokenId is in the IncreaseLiquidity / Transfer event logs.

3. Manage the position

The NPM exposes the standard lifecycle calls:

ActionCall
Add liquidityincreaseLiquidity((tokenId, amount0Desired, amount1Desired, amount0Min, amount1Min, deadline))
Remove liquiditydecreaseLiquidity((tokenId, liquidity, amount0Min, amount1Min, deadline))
Collect fees / withdrawn tokenscollect((tokenId, recipient, amount0Max, amount1Max))
Read positionpositions(tokenId)
Burn empty positionburn(tokenId)

decreaseLiquidity only credits tokens to the position; you must then collect to receive them.

Earning emissions on your position

Trading fees accrue automatically. To also earn BARK emissions, stake the position NFT into the pool's gauge — see ve(3,3): lock, vote, earn.

Gotchas

  • Tick alignment. tickLower / tickUpper must be multiples of the pool tickSpacing, or the mint reverts. Read tickSpacing() from the pool.
  • Token order. Always sort token0 < token1; the NPM does not reorder for you.
  • Set minimums in production. amount0Min / amount1Min of 0 accepts any execution price.
  • Out-of-range mints. If the current price is outside [tickLower, tickUpper], you deposit only one of the two tokens.