Skip to main content

Pool Addresses

Overview#

For each token pair, there are possibly many multiple pools with different configurations. As such, it is necessary to specify which pools are to be used for fetching token rates, trade execution and liquidity provision.

getPools#

The best way to get all pools for a specific token pair is to call getPools on the factory, then selecting one of the pools from the returned array. If none exists, an empty array is returned.

address[] memory poolAddresses = dmmFactory.getPools(usdt, dai);

Selecting The Right Pool#

Given a token pair, the DMM website will show the unamplified pool and those created by the Kyber team.

Unamplified Pool#

For direct smart contract integrations, the unamplified pool (amplification factor 1) is recommended for simplicity. This pool supports an infinite price range, and therefore should always have liquidity. The pool address can be fetched by calling getUnamplifiedPool on the factory.

address poolAddress = dmmFactory.getUnamplifiedPool(usdt, dai);

Pool with best liquidity#

An alternative method is to call the factory's getPools method to fetch all pools for the token pair, then sorting by liquidity.

This can be done by fetching each pool's kLast method, then whichever pool has the highest kLast value should be used. We provide a short code snippet below.

address[] memory poolAddresses = dmmFactory.getPools(usdt, dai);
address bestPool;
uint256 highestKLast = 0;
uint256 bestIndex = 0;
for (uint i = 0; i < poolAddresses.length; i++) {
uint256 currentKLast = IDMMPool(poolAddresses[i]).kLast();
if (currentKLast > highestKLast) {
highestKLast = currentKLast;
bestIndex = i;
}
}
// handle case if highestKLast is 0 (no liquidity)
if (highestKLast == 0) {
bestPool = address(0);
} else {
bestPool = poolAddresses[i];
}
// use bestPool for rate queries, liquidity provision or swaps

To save on gas costs, this process is recommended to be performed off-chain, then have the pool address(es) specified as an input. See the first method in the example below.

Example#

We showcase 3 methods for getting pool addresses to calculate the USDT amount needed to obtain 100 DAI.

Note that we import the router and factory interfaces.

pragma solidity 0.6.6;
import "./IDMMRouter02.sol";
import "./IDMMFactory.sol";
contract Example {
IDMMRouter02 public dmmRouter;
IDMMFactory public dmmFactory;
IERC20 public usdt = 0xdac17f958d2ee523a2206206994597c13d831ec7; // mainnet USDT address
IERC20 public dai = '0x6b175474e89094c44da98b954eedeac495271d0f'; // mainnet DAI address
IERC20[] public tokensPath = [usdt,dai];
constructor(IDMMRouter02 _dmmRouter) {
dmmRouter = _dmmRouter;
dmmFactory = IDMMFactory(dmmRouter.factory());
}
// the first (and our recommended) method is to
// query for the best pool off-chain and pass it as an input
function getRateFirstMethod(address[] poolsPath) external view returns (uint256[] amounts) {
// return amounts
return dmmRouter.getAmountsIn(
1e20, // 100 DAI
poolsPath,
tokensPath
);
}
// the second method is to use the unamplified pool
// while convenient, it may not be optimal
function getRateSecondMethod() external view returns (uint256[] amounts) {
address poolAddress = dmmFactory.getUnamplifiedPool(usdt, dai);
// use unamplified pool
addresss[] memory poolsPath = new address[](1);
poolsPath[0] = poolAddress;
// return amounts
return dmmRouter.getAmountsIn(
1e20, // 100 DAI
poolPath,
tokensPath
);
}
// the third method is to use the pool found in the first index of the pool array
// if no pools are available, return empty array
function getRateThirdMethod() external view returns (uint256[] amounts) {
address[] memory poolAddresses = dmmFactory.getPools(usdt, dai);
if (poolAddresses.length == 0) return;
// use the pool address of the first index of the pool array
addresss[] memory poolsPath = new address[](1);
poolsPath[0] = poolAddresses[0];
// return amounts
return dmmRouter.getAmountsIn(
1e20, // 100 DAI
poolPath,
tokensPath
);
}
}