UNPKG

@sky-mavis/smart-order-router

Version:
97 lines 10.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TokenValidatorProvider = exports.TokenValidationResult = exports.DEFAULT_ALLOWLIST = void 0; const lodash_1 = __importDefault(require("lodash")); const ITokenValidator__factory_1 = require("../types/other/factories/ITokenValidator__factory"); const util_1 = require("../util"); exports.DEFAULT_ALLOWLIST = new Set([ // RYOSHI. Does not allow transfers between contracts so fails validation. '0x777E2ae845272a2F540ebf6a3D03734A5a8f618e'.toLowerCase(), ]); var TokenValidationResult; (function (TokenValidationResult) { TokenValidationResult[TokenValidationResult["UNKN"] = 0] = "UNKN"; TokenValidationResult[TokenValidationResult["FOT"] = 1] = "FOT"; TokenValidationResult[TokenValidationResult["STF"] = 2] = "STF"; })(TokenValidationResult = exports.TokenValidationResult || (exports.TokenValidationResult = {})); const TOKEN_VALIDATOR_ADDRESS = '0xb5ee1690b7dcc7859771148d0889be838fe108e0'; const AMOUNT_TO_FLASH_BORROW = '1000'; const GAS_LIMIT_PER_VALIDATE = 1000000; class TokenValidatorProvider { constructor(chainId, multicall2Provider, tokenValidationCache, tokenValidatorAddress = TOKEN_VALIDATOR_ADDRESS, gasLimitPerCall = GAS_LIMIT_PER_VALIDATE, amountToFlashBorrow = AMOUNT_TO_FLASH_BORROW, allowList = exports.DEFAULT_ALLOWLIST) { this.chainId = chainId; this.multicall2Provider = multicall2Provider; this.tokenValidationCache = tokenValidationCache; this.tokenValidatorAddress = tokenValidatorAddress; this.gasLimitPerCall = gasLimitPerCall; this.amountToFlashBorrow = amountToFlashBorrow; this.allowList = allowList; this.CACHE_KEY = (chainId, address) => `token-${chainId}-${address}`; this.BASES = [util_1.WRAPPED_NATIVE_CURRENCY[this.chainId].address]; } async validateTokens(tokens, providerConfig) { const tokenAddressToToken = lodash_1.default.keyBy(tokens, 'address'); const addressesRaw = (0, lodash_1.default)(tokens) .map(token => token.address) .uniq() .value(); const addresses = []; const tokenToResult = {}; // Check if we have cached token validation results for any tokens. for (const address of addressesRaw) { if (await this.tokenValidationCache.has(this.CACHE_KEY(this.chainId, address))) { tokenToResult[address.toLowerCase()] = (await this.tokenValidationCache.get(this.CACHE_KEY(this.chainId, address))); util_1.metric.putMetric(`TokenValidatorProviderValidateCacheHitResult${tokenToResult[address.toLowerCase()]}`, 1, util_1.MetricLoggerUnit.Count); } else { addresses.push(address); } } util_1.log.info(`Got token validation results for ${addressesRaw.length - addresses.length} tokens from cache. Getting ${addresses.length} on-chain.`); const functionParams = (0, lodash_1.default)(addresses) .map(address => [address, this.BASES, this.amountToFlashBorrow]) .value(); // We use the validate function instead of batchValidate to avoid poison pill problem. // One token that consumes too much gas could cause the entire batch to fail. const multicallResult = await this.multicall2Provider.callSameFunctionOnContractWithMultipleParams({ address: this.tokenValidatorAddress, contractInterface: ITokenValidator__factory_1.ITokenValidator__factory.createInterface(), functionName: 'validate', functionParams: functionParams, providerConfig, additionalConfig: { gasLimitPerCallOverride: this.gasLimitPerCall, }, }); for (let i = 0; i < multicallResult.results.length; i++) { const resultWrapper = multicallResult.results[i]; const tokenAddress = addresses[i]; const token = tokenAddressToToken[tokenAddress]; if (this.allowList.has(token.address.toLowerCase())) { tokenToResult[token.address.toLowerCase()] = TokenValidationResult.UNKN; await this.tokenValidationCache.set(this.CACHE_KEY(this.chainId, token.address.toLowerCase()), tokenToResult[token.address.toLowerCase()]); continue; } // Could happen if the tokens transfer consumes too much gas so we revert. Just // drop the token in that case. if (!resultWrapper.success) { util_1.metric.putMetric('TokenValidatorProviderValidateFailed', 1, util_1.MetricLoggerUnit.Count); util_1.log.error({ result: resultWrapper }, `Failed to validate token ${token.symbol}`); continue; } util_1.metric.putMetric('TokenValidatorProviderValidateSuccess', 1, util_1.MetricLoggerUnit.Count); const validationResult = resultWrapper.result[0]; tokenToResult[token.address.toLowerCase()] = validationResult; await this.tokenValidationCache.set(this.CACHE_KEY(this.chainId, token.address.toLowerCase()), tokenToResult[token.address.toLowerCase()]); util_1.metric.putMetric(`TokenValidatorProviderValidateCacheMissResult${validationResult}`, 1, util_1.MetricLoggerUnit.Count); } return { getValidationByToken: (token) => tokenToResult[token.address.toLowerCase()], }; } } exports.TokenValidatorProvider = TokenValidatorProvider; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tdmFsaWRhdG9yLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy90b2tlbi12YWxpZGF0b3ItcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBRUEsb0RBQXVCO0FBRXZCLGdHQUE2RjtBQUM3RixrQ0FBaUY7QUFLcEUsUUFBQSxpQkFBaUIsR0FBRyxJQUFJLEdBQUcsQ0FBUztJQUMvQywwRUFBMEU7SUFDMUUsNENBQTRDLENBQUMsV0FBVyxFQUFFO0NBQzNELENBQUMsQ0FBQztBQUVILElBQVkscUJBSVg7QUFKRCxXQUFZLHFCQUFxQjtJQUMvQixpRUFBUSxDQUFBO0lBQ1IsK0RBQU8sQ0FBQTtJQUNQLCtEQUFPLENBQUE7QUFDVCxDQUFDLEVBSlcscUJBQXFCLEdBQXJCLDZCQUFxQixLQUFyQiw2QkFBcUIsUUFJaEM7QUFNRCxNQUFNLHVCQUF1QixHQUFHLDRDQUE0QyxDQUFDO0FBQzdFLE1BQU0sc0JBQXNCLEdBQUcsTUFBTSxDQUFDO0FBQ3RDLE1BQU0sc0JBQXNCLEdBQUcsT0FBUyxDQUFDO0FBbUJ6QyxNQUFhLHNCQUFzQjtJQUtqQyxZQUNZLE9BQWdCLEVBQ2hCLGtCQUFzQyxFQUN4QyxvQkFBbUQsRUFDbkQsd0JBQXdCLHVCQUF1QixFQUMvQyxrQkFBa0Isc0JBQXNCLEVBQ3hDLHNCQUFzQixzQkFBc0IsRUFDNUMsWUFBWSx5QkFBaUI7UUFOM0IsWUFBTyxHQUFQLE9BQU8sQ0FBUztRQUNoQix1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW9CO1FBQ3hDLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBK0I7UUFDbkQsMEJBQXFCLEdBQXJCLHFCQUFxQixDQUEwQjtRQUMvQyxvQkFBZSxHQUFmLGVBQWUsQ0FBeUI7UUFDeEMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUF5QjtRQUM1QyxjQUFTLEdBQVQsU0FBUyxDQUFvQjtRQVgvQixjQUFTLEdBQUcsQ0FBQyxP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