UNPKG

@gnosis.pm/dex-contracts

Version:

Contracts for dFusion multi-token batch auction exchange

90 lines (89 loc) 4 kB
import BN from "bn.js"; const MAXU32 = new BN(2).pow(new BN(32)).sub(new BN(1)); /** * Used to recover relevant {@link TokenInfo | TokenInfo} by ID from the exchange such as number of decimals or name. * @param exchange - An instance of deployed Batch Exchange Contract * @param tokenIds - An array of token ids as listed on the Batch Exchange. * @param artifacts - A context-like object providing a gateway to Truffle contract ABIs. * @returns A mapping of TokenInfo objects fetched from the exchange. * Note that nullish TokenInfo objects are returned in places where the requested token ID failed to fetch. */ export async function fetchTokenInfoFromExchange(exchange, tokenIds, artifacts) { const ERC20 = artifacts.require("ERC20Detailed"); // Fetching token data from EVM const tokenObjects = new Map(); await Promise.all(tokenIds.map(async (id) => { const tokenAddress = await exchange.tokenIdToAddressMap(id); let tokenInfo; try { const tokenInstance = await ERC20.at(tokenAddress); const [symbol, decimals] = await Promise.all([ tokenInstance.symbol(), tokenInstance.decimals(), ]); tokenInfo = { id: id, symbol: symbol, decimals: decimals.toNumber(), address: tokenAddress, }; } catch (err) { // This generic try-catch is essentially a TokenNotFoundError // Could occur when the given ID slot is not occupied by a registered token on the exhchange // or if the code registered at address occupied by a token slot is not that of and ERC20 token tokenInfo = { id: id, address: tokenAddress, }; } tokenObjects.set(id, tokenInfo); })); return tokenObjects; } /** * A handy function providing fee token liquidity by placing orders selling the fee token * at the specified provision price for each specified token. * @param exchange - BatchExchange Smart Contract * @param tokenIds - An array of token indices as represented on the exchange * @param provisionPrice - Price at which liquidity is to be provided * @param sellAmountOwl - Amount of feeToken to be sold * @param artifacts - A context-like object providing a gateway to Truffle contract ABIs. * @returns Void Promise */ export async function placeFeeTokenLiquidityOrders(exchange, tokenIds, provisionPrice, sellAmountOwl, artifacts) { const minBuyAmounts = []; const validTokenIds = []; const feeToken = await fetchTokenInfoFromExchange(exchange, [0], artifacts); // This is expected to always be OWL which has 18 digits. const feeDigits = feeToken.get(0)?.decimals || 18; const tokenInfo = await fetchTokenInfoFromExchange(exchange, tokenIds, artifacts); for (const tokenId of tokenIds) { const numDigits = tokenInfo.get(tokenId)?.decimals; if (numDigits) { validTokenIds.push(tokenId); if (numDigits < feeDigits) { minBuyAmounts.push(sellAmountOwl .mul(provisionPrice) .div(new BN(10).pow(new BN(feeDigits - numDigits)))); } else { minBuyAmounts.push(sellAmountOwl .mul(provisionPrice) .mul(new BN(10).pow(new BN(numDigits - feeDigits)))); } } } const numOrders = validTokenIds.length; const batchId = (await exchange.getCurrentBatchId()).toNumber(); if (numOrders == 0) { return []; } await exchange.placeValidFromOrders(validTokenIds, // buyTokens Array(numOrders).fill(0), // sellTokens Array(numOrders).fill(batchId + 2), // validFroms (all to begin 2 batches from now) Array(numOrders).fill(MAXU32), // validTos minBuyAmounts, // buyAmounts Array(numOrders).fill(sellAmountOwl)); return validTokenIds; }