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.
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.
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.
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.
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.
pragmasolidity 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 inputfunctiongetRateFirstMethod(address[] poolsPath) externalviewreturns (uint256[] amounts) {// return amountsreturn dmmRouter.getAmountsIn(1e20,// 100 DAI poolsPath, tokensPath ); }// the second method is to use the unamplified pool// while convenient, it may not be optimalfunctiongetRateSecondMethod() externalviewreturns (uint256[] amounts) {address poolAddress = dmmFactory.getUnamplifiedPool(usdt, dai);// use unamplified pool addresss[] memory poolsPath =newaddress[](1); poolsPath[0] = poolAddress;// return amountsreturn 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 arrayfunctiongetRateThirdMethod() externalviewreturns (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 =newaddress[](1); poolsPath[0] = poolAddresses[0];// return amountsreturn dmmRouter.getAmountsIn(1e20,// 100 DAI poolPath, tokensPath ); }}