From 234ddb495db48dd284b38aeb9f3775a736647295 Mon Sep 17 00:00:00 2001 From: Romain Butteaud Date: Sun, 16 May 2021 19:43:06 -0700 Subject: [PATCH] fix: mStable USD Sampler and Mixin fix (#238) * fix: mStable USD Sampler and Mixin fix * chore: adding mBTC (mStable) pool * fix linter --- .../bridges/mixins/MixinMStable.sol | 3 +++ .../contracts/src/MStableSampler.sol | 3 ++- .../contracts/src/interfaces/IMStable.sol | 2 +- .../bridge_source_utils.ts | 15 ++++++++++- .../utils/market_operation_utils/constants.ts | 26 ++++++++++++++++--- .../sampler_operations.ts | 23 +++++----------- 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinMStable.sol b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinMStable.sol index 6691026006..0252d89ba3 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinMStable.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinMStable.sol @@ -31,6 +31,7 @@ interface IMStable { IERC20TokenV06 sellToken, IERC20TokenV06 buyToken, uint256 sellAmount, + uint256 minBoughtAmount, address recipient ) external @@ -59,6 +60,8 @@ contract MixinMStable { sellToken, buyToken, sellAmount, + // Minimum buy amount. + 1, address(this) ); } diff --git a/packages/asset-swapper/contracts/src/MStableSampler.sol b/packages/asset-swapper/contracts/src/MStableSampler.sol index 32be511fb8..0947bc3767 100644 --- a/packages/asset-swapper/contracts/src/MStableSampler.sol +++ b/packages/asset-swapper/contracts/src/MStableSampler.sol @@ -49,6 +49,7 @@ contract MStableSampler is view returns (uint256[] memory makerTokenAmounts) { + _assertValidPair(makerToken, takerToken); // Initialize array of maker token amounts. uint256 numSamples = takerTokenAmounts.length; makerTokenAmounts = new uint256[](numSamples); @@ -58,7 +59,7 @@ contract MStableSampler is IMStable(router).getSwapOutput {gas: DEFAULT_CALL_GAS} (takerToken, makerToken, takerTokenAmounts[i]) - returns (bool, string memory, uint256 amount) + returns (uint256 amount) { makerTokenAmounts[i] = amount; // Break early if there are 0 amounts diff --git a/packages/asset-swapper/contracts/src/interfaces/IMStable.sol b/packages/asset-swapper/contracts/src/interfaces/IMStable.sol index 634c62f623..cae1bbb99b 100644 --- a/packages/asset-swapper/contracts/src/interfaces/IMStable.sol +++ b/packages/asset-swapper/contracts/src/interfaces/IMStable.sol @@ -29,5 +29,5 @@ interface IMStable { ) external view - returns (bool, string memory, uint256 output); + returns (uint256 swapOutput); } diff --git a/packages/asset-swapper/src/utils/market_operation_utils/bridge_source_utils.ts b/packages/asset-swapper/src/utils/market_operation_utils/bridge_source_utils.ts index 2ce7d36766..c1f13b90b6 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/bridge_source_utils.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/bridge_source_utils.ts @@ -17,6 +17,7 @@ import { KYBER_DMM_ROUTER_BY_CHAIN_ID, MAX_DODOV2_POOLS_QUERIED, MAX_KYBER_RESERVES_QUERIED, + MSTABLE_POOLS_BY_CHAIN_ID, NERVE_BSC_INFOS, NULL_ADDRESS, PANCAKESWAP_ROUTER_BY_CHAIN_ID, @@ -86,6 +87,16 @@ export function getComponentForPair(chainId: ChainId, takerToken: string, makerT .map(i => i.poolAddress); } +// tslint:disable completed-docs +export function getMStableForPair(chainId: ChainId, takerToken: string, makerToken: string): string[] { + if (chainId !== ChainId.Mainnet) { + return []; + } + return Object.values(MSTABLE_POOLS_BY_CHAIN_ID[chainId]) + .filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t))) + .map(i => i.poolAddress); +} + // tslint:disable completed-docs export function getCurveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] { if (chainId !== ChainId.Mainnet) { @@ -221,13 +232,15 @@ export function getShellLikeInfosForPair( chainId: ChainId, takerToken: string, makerToken: string, - source: ERC20BridgeSource.Shell | ERC20BridgeSource.Component, + source: ERC20BridgeSource.Shell | ERC20BridgeSource.Component | ERC20BridgeSource.MStable, ): string[] { switch (source) { case ERC20BridgeSource.Shell: return getShellsForPair(chainId, takerToken, makerToken); case ERC20BridgeSource.Component: return getComponentForPair(chainId, takerToken, makerToken); + case ERC20BridgeSource.MStable: + return getMStableForPair(chainId, takerToken, makerToken); default: throw new Error(`Unknown Shell like source ${source}`); } diff --git a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts index 765f11c793..f9f6214ad4 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -907,11 +907,29 @@ export const LINKSWAP_ROUTER_BY_CHAIN_ID = valueByChainId( NULL_ADDRESS, ); -export const MSTABLE_ROUTER_BY_CHAIN_ID = valueByChainId( +export const MSTABLE_POOLS_BY_CHAIN_ID = valueByChainId( { - [ChainId.Mainnet]: '0xe2f2a5c287993345a840db3b0845fbc70f5935a5', + [ChainId.Mainnet]: { + mUSD: { + poolAddress: '0xe2f2a5c287993345a840db3b0845fbc70f5935a5', + tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT], + }, + mBTC: { + poolAddress: '0x945facb997494cc2570096c74b5f66a3507330a1', + tokens: [MAINNET_TOKENS.WBTC, MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.sBTC], + }, + }, + }, + { + mUSD: { + poolAddress: NULL_ADDRESS, + tokens: [] as string[], + }, + mBTC: { + poolAddress: NULL_ADDRESS, + tokens: [] as string[], + }, }, - NULL_ADDRESS, ); export const OASIS_ROUTER_BY_CHAIN_ID = valueByChainId( @@ -1208,7 +1226,7 @@ export const DEFAULT_GAS_SCHEDULE: Required = { [ERC20BridgeSource.Balancer]: () => 120e3, [ERC20BridgeSource.BalancerV2]: () => 100e3, [ERC20BridgeSource.Cream]: () => 120e3, - [ERC20BridgeSource.MStable]: () => 700e3, + [ERC20BridgeSource.MStable]: () => 200e3, [ERC20BridgeSource.MakerPsm]: (fillData?: FillData) => { const psmFillData = fillData as MakerPsmFillData; return psmFillData.takerToken === psmFillData.gemTokenAddress ? 210e3 : 290e3; diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index 304a609bf3..21f9ae6e63 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -29,7 +29,6 @@ import { MAKER_PSM_INFO_BY_CHAIN_ID, MAX_UINT256, MOONISWAP_REGISTRIES_BY_CHAIN_ID, - MSTABLE_ROUTER_BY_CHAIN_ID, NATIVE_FEE_TOKEN_BY_CHAIN_ID, NULL_ADDRESS, NULL_BYTES, @@ -1204,14 +1203,9 @@ export class SamplerOperations { ), ); case ERC20BridgeSource.MStable: - return isValidAddress(MSTABLE_ROUTER_BY_CHAIN_ID[this.chainId]) - ? this.getMStableSellQuotes( - MSTABLE_ROUTER_BY_CHAIN_ID[this.chainId], - makerToken, - takerToken, - takerFillAmounts, - ) - : []; + return getShellLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool => + this.getMStableSellQuotes(pool, makerToken, takerToken, takerFillAmounts), + ); case ERC20BridgeSource.Mooniswap: return [ ...MOONISWAP_REGISTRIES_BY_CHAIN_ID[this.chainId] @@ -1456,14 +1450,9 @@ export class SamplerOperations { ), ); case ERC20BridgeSource.MStable: - return isValidAddress(MSTABLE_ROUTER_BY_CHAIN_ID[this.chainId]) - ? this.getMStableBuyQuotes( - MSTABLE_ROUTER_BY_CHAIN_ID[this.chainId], - makerToken, - takerToken, - makerFillAmounts, - ) - : []; + return getShellLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool => + this.getMStableBuyQuotes(pool, makerToken, takerToken, makerFillAmounts), + ); case ERC20BridgeSource.Mooniswap: return [ ...MOONISWAP_REGISTRIES_BY_CHAIN_ID[this.chainId]