From f1782a83ba40972b976264f4e6b55bd1b13f4702 Mon Sep 17 00:00:00 2001 From: Romain Butteaud Date: Fri, 30 Apr 2021 15:48:10 -0700 Subject: [PATCH] chore: BSC PancakeSwap forks VIP, PancakeSwapV2, Saddle BTC pool, Curve gas schedule [TKR-41] [TKR-11] [TKR-79] [TKR-86] (#208) * chore: popular BSC Uniswap clones, Curve gas schedule update, Saddle BTC pool * chore: adding PancakeSwapV2 VIP * fix: yarn prettier --- contracts/zero-ex/CHANGELOG.json | 4 + .../src/features/PancakeSwapFeature.sol | 51 ++++- .../interfaces/IPancakeSwapFeature.sol | 11 +- packages/asset-swapper/CHANGELOG.json | 4 + .../exchange_proxy_swap_quote_consumer.ts | 18 +- .../bridge_source_utils.ts | 24 ++- .../utils/market_operation_utils/constants.ts | 179 ++++++++++++------ .../utils/market_operation_utils/orders.ts | 30 ++- .../sampler_operations.ts | 12 +- .../src/utils/market_operation_utils/types.ts | 6 +- 10 files changed, 265 insertions(+), 74 deletions(-) diff --git a/contracts/zero-ex/CHANGELOG.json b/contracts/zero-ex/CHANGELOG.json index 6c414cebfa..38b78cc7c5 100644 --- a/contracts/zero-ex/CHANGELOG.json +++ b/contracts/zero-ex/CHANGELOG.json @@ -25,6 +25,10 @@ "changes": [ { "note": "Dependencies updated" + }, + { + "note": "BSC Uniswap clones (ApeSwap, CafeSwap, CheeseSwap, JulSwap)", + "pr": 208 } ] }, diff --git a/contracts/zero-ex/contracts/src/features/PancakeSwapFeature.sol b/contracts/zero-ex/contracts/src/features/PancakeSwapFeature.sol index c38f5444ca..6c92c0b645 100644 --- a/contracts/zero-ex/contracts/src/features/PancakeSwapFeature.sol +++ b/contracts/zero-ex/contracts/src/features/PancakeSwapFeature.sol @@ -37,22 +37,44 @@ contract PancakeSwapFeature is /// @dev Name of this feature. string public constant override FEATURE_NAME = "PancakeSwapFeature"; /// @dev Version of this feature. - uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1); + uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 2); /// @dev WBNB contract. IEtherTokenV06 private immutable WBNB; // 0xFF + address of the PancakeSwap factory contract. uint256 constant private FF_PANCAKESWAP_FACTORY = 0xffbcfccbde45ce874adcb698cc183debcf179528120000000000000000000000; + // 0xFF + address of the PancakeSwapV2 factory contract. + uint256 constant private FF_PANCAKESWAPV2_FACTORY = 0xffca143ce32fe78f1f7019d7d551a6402fc5350c730000000000000000000000; // 0xFF + address of the BakerySwap factory contract. uint256 constant private FF_BAKERYSWAP_FACTORY = 0xff01bf7c66c6bd861915cdaae475042d3c4bae16a70000000000000000000000; // 0xFF + address of the SushiSwap factory contract. uint256 constant private FF_SUSHISWAP_FACTORY = 0xffc35DADB65012eC5796536bD9864eD8773aBc74C40000000000000000000000; + // 0xFF + address of the ApeSwap factory contract. + uint256 constant private FF_APESWAP_FACTORY = 0xff0841bd0b734e4f5853f0dd8d7ea041c241fb0da60000000000000000000000; + // 0xFF + address of the CafeSwap factory contract. + uint256 constant private FF_CAFESWAP_FACTORY = 0xff3e708fdbe3ada63fc94f8f61811196f1302137ad0000000000000000000000; + // 0xFF + address of the CheeseSwap factory contract. + uint256 constant private FF_CHEESESWAP_FACTORY = 0xffdd538e4fd1b69b7863e1f741213276a6cf1efb3b0000000000000000000000; + // 0xFF + address of the JulSwap factory contract. + uint256 constant private FF_JULSWAP_FACTORY = 0xff553990f2cba90272390f62c5bdb1681ffc8996750000000000000000000000; + // Init code hash of the PancakeSwap pair contract. uint256 constant private PANCAKESWAP_PAIR_INIT_CODE_HASH = 0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66; + // Init code hash of the PancakeSwapV2 pair contract. + uint256 constant private PANCAKESWAPV2_PAIR_INIT_CODE_HASH = 0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5; // Init code hash of the BakerySwap pair contract. uint256 constant private BAKERYSWAP_PAIR_INIT_CODE_HASH = 0xe2e87433120e32c4738a7d8f3271f3d872cbe16241d67537139158d90bac61d3; // Init code hash of the SushiSwap pair contract. uint256 constant private SUSHISWAP_PAIR_INIT_CODE_HASH = 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303; + // Init code hash of the ApeSwap pair contract. + uint256 constant private APESWAP_PAIR_INIT_CODE_HASH = 0xf4ccce374816856d11f00e4069e7cada164065686fbef53c6167a63ec2fd8c5b; + // Init code hash of the CafeSwap pair contract. + uint256 constant private CAFESWAP_PAIR_INIT_CODE_HASH = 0x90bcdb5d0bf0e8db3852b0b7d7e05cc8f7c6eb6d511213c5ba02d1d1dbeda8d3; + // Init code hash of the CheeseSwap pair contract. + uint256 constant private CHEESESWAP_PAIR_INIT_CODE_HASH = 0xf52c5189a89e7ca2ef4f19f2798e3900fba7a316de7cef6c5a9446621ba86286; + // Init code hash of the JulSwap pair contract. + uint256 constant private JULSWAP_PAIR_INIT_CODE_HASH = 0xb1e98e21a5335633815a8cfb3b580071c2e4561c50afd57a8746def9ed890b18; + // Mask of the lower 20 bytes of a bytes32. uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff; // BNB pseudo-token address. @@ -352,15 +374,40 @@ contract PancakeSwapFeature is mstore(0xB35, PANCAKESWAP_PAIR_INIT_CODE_HASH) } case 1 { + mstore(0xB00, FF_PANCAKESWAPV2_FACTORY) + mstore(0xB15, salt) + mstore(0xB35, PANCAKESWAPV2_PAIR_INIT_CODE_HASH) + } + case 2 { mstore(0xB00, FF_BAKERYSWAP_FACTORY) mstore(0xB15, salt) mstore(0xB35, BAKERYSWAP_PAIR_INIT_CODE_HASH) } - default { + case 3 { mstore(0xB00, FF_SUSHISWAP_FACTORY) mstore(0xB15, salt) mstore(0xB35, SUSHISWAP_PAIR_INIT_CODE_HASH) } + case 4 { + mstore(0xB00, FF_APESWAP_FACTORY) + mstore(0xB15, salt) + mstore(0xB35, APESWAP_PAIR_INIT_CODE_HASH) + } + case 5 { + mstore(0xB00, FF_CAFESWAP_FACTORY) + mstore(0xB15, salt) + mstore(0xB35, CAFESWAP_PAIR_INIT_CODE_HASH) + } + case 6 { + mstore(0xB00, FF_CHEESESWAP_FACTORY) + mstore(0xB15, salt) + mstore(0xB35, CHEESESWAP_PAIR_INIT_CODE_HASH) + } + default { + mstore(0xB00, FF_JULSWAP_FACTORY) + mstore(0xB15, salt) + mstore(0xB35, JULSWAP_PAIR_INIT_CODE_HASH) + } pair := and(ADDRESS_MASK, keccak256(0xB00, 0x55)) } diff --git a/contracts/zero-ex/contracts/src/features/interfaces/IPancakeSwapFeature.sol b/contracts/zero-ex/contracts/src/features/interfaces/IPancakeSwapFeature.sol index 611cf0fb57..ce906d73fc 100644 --- a/contracts/zero-ex/contracts/src/features/interfaces/IPancakeSwapFeature.sol +++ b/contracts/zero-ex/contracts/src/features/interfaces/IPancakeSwapFeature.sol @@ -23,16 +23,21 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; -/// @dev VIP PancakeSwap/BakerySwap/SushiSwap fill functions. +/// @dev VIP PancakeSwap (and forks) fill functions. interface IPancakeSwapFeature { enum ProtocolFork { PancakeSwap, + PancakeSwapV2, BakerySwap, - SushiSwap + SushiSwap, + ApeSwap, + CafeSwap, + CheeseSwap, + JulSwap } - /// @dev Efficiently sell directly to PancakeSwap/BakerySwap/Sushiswap. + /// @dev Efficiently sell directly to PancakeSwap (and forks). /// @param tokens Sell path. /// @param sellAmount of `tokens[0]` Amount to sell. /// @param minBuyAmount Minimum amount of `tokens[-1]` to buy. diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json index 0237bcd9b8..1ecdb8c19b 100644 --- a/packages/asset-swapper/CHANGELOG.json +++ b/packages/asset-swapper/CHANGELOG.json @@ -47,6 +47,10 @@ { "note": "Support `Ropsten` network", "pr": 203 + }, + { + "note": "BSC Uniswap clones (ApeSwap, CafeSwap, CheeseSwap, JulSwap), Saddle BTC pool, Curve gas schedule", + "pr": 208 } ], "timestamp": 1618592834 diff --git a/packages/asset-swapper/src/quote_consumers/exchange_proxy_swap_quote_consumer.ts b/packages/asset-swapper/src/quote_consumers/exchange_proxy_swap_quote_consumer.ts index ecfe27b054..7f1454e7aa 100644 --- a/packages/asset-swapper/src/quote_consumers/exchange_proxy_swap_quote_consumer.ts +++ b/packages/asset-swapper/src/quote_consumers/exchange_proxy_swap_quote_consumer.ts @@ -65,7 +65,18 @@ import { // tslint:disable-next-line:custom-no-magic-numbers const MAX_UINT256 = new BigNumber(2).pow(256).minus(1); const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants; -const PANCAKE_SWAP_FORKS = [ERC20BridgeSource.PancakeSwap, ERC20BridgeSource.BakerySwap, ERC20BridgeSource.SushiSwap]; + +// use the same order in IPancakeSwapFeature.sol +const PANCAKE_SWAP_FORKS = [ + ERC20BridgeSource.PancakeSwap, + ERC20BridgeSource.PancakeSwapV2, + ERC20BridgeSource.BakerySwap, + ERC20BridgeSource.SushiSwap, + ERC20BridgeSource.ApeSwap, + ERC20BridgeSource.CafeSwap, + ERC20BridgeSource.CheeseSwap, + ERC20BridgeSource.JulSwap, +]; const DUMMY_WETH_CONTRACT = new WETH9Contract(NULL_ADDRESS, { sendAsync(): void { return; @@ -186,8 +197,13 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase { this.chainId === ChainId.BSC && isDirectSwapCompatible(quote, optsWithDefaults, [ ERC20BridgeSource.PancakeSwap, + ERC20BridgeSource.PancakeSwapV2, ERC20BridgeSource.BakerySwap, ERC20BridgeSource.SushiSwap, + ERC20BridgeSource.ApeSwap, + ERC20BridgeSource.CafeSwap, + ERC20BridgeSource.CheeseSwap, + ERC20BridgeSource.JulSwap, ]) ) { const source = slippedOrders[0].source; 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 367871aa59..b4473a3634 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 @@ -2,12 +2,16 @@ import { ChainId } from '@0x/contract-addresses'; import { BigNumber, NULL_BYTES } from '@0x/utils'; import { + APESWAP_ROUTER_BY_CHAIN_ID, BAKERYSWAP_ROUTER_BY_CHAIN_ID, BELT_BSC_INFOS, + CAFESWAP_ROUTER_BY_CHAIN_ID, + CHEESESWAP_ROUTER_BY_CHAIN_ID, COMPONENT_POOLS_BY_CHAIN_ID, CRYPTO_COM_ROUTER_BY_CHAIN_ID, CURVE_MAINNET_INFOS, ELLIPSIS_BSC_INFOS, + JULSWAP_ROUTER_BY_CHAIN_ID, KYBER_BANNED_RESERVES, KYBER_BRIDGED_LIQUIDITY_PREFIX, KYBER_DMM_ROUTER_BY_CHAIN_ID, @@ -16,7 +20,7 @@ import { NERVE_BSC_INFOS, NULL_ADDRESS, PANCAKESWAP_ROUTER_BY_CHAIN_ID, - PANCAKESWAP_V2_ROUTER_BY_CHAIN_ID, + PANCAKESWAPV2_ROUTER_BY_CHAIN_ID, SADDLE_MAINNET_INFOS, SHELL_POOLS_BY_CHAIN_ID, SMOOTHY_BSC_INFOS, @@ -258,9 +262,13 @@ export function uniswapV2LikeRouterAddress( | ERC20BridgeSource.SushiSwap | ERC20BridgeSource.CryptoCom | ERC20BridgeSource.PancakeSwap + | ERC20BridgeSource.PancakeSwapV2 | ERC20BridgeSource.BakerySwap | ERC20BridgeSource.KyberDmm - | ERC20BridgeSource.PancakeSwapV2, + | ERC20BridgeSource.ApeSwap + | ERC20BridgeSource.CafeSwap + | ERC20BridgeSource.CheeseSwap + | ERC20BridgeSource.JulSwap, ): string { switch (source) { case ERC20BridgeSource.UniswapV2: @@ -271,12 +279,20 @@ export function uniswapV2LikeRouterAddress( return CRYPTO_COM_ROUTER_BY_CHAIN_ID[chainId]; case ERC20BridgeSource.PancakeSwap: return PANCAKESWAP_ROUTER_BY_CHAIN_ID[chainId]; + case ERC20BridgeSource.PancakeSwapV2: + return PANCAKESWAPV2_ROUTER_BY_CHAIN_ID[chainId]; case ERC20BridgeSource.BakerySwap: return BAKERYSWAP_ROUTER_BY_CHAIN_ID[chainId]; case ERC20BridgeSource.KyberDmm: return KYBER_DMM_ROUTER_BY_CHAIN_ID[chainId]; - case ERC20BridgeSource.PancakeSwapV2: - return PANCAKESWAP_V2_ROUTER_BY_CHAIN_ID[chainId]; + case ERC20BridgeSource.ApeSwap: + return APESWAP_ROUTER_BY_CHAIN_ID[chainId]; + case ERC20BridgeSource.CafeSwap: + return CAFESWAP_ROUTER_BY_CHAIN_ID[chainId]; + case ERC20BridgeSource.CheeseSwap: + return CHEESESWAP_ROUTER_BY_CHAIN_ID[chainId]; + case ERC20BridgeSource.JulSwap: + return JULSWAP_ROUTER_BY_CHAIN_ID[chainId]; default: throw new Error(`Unknown UniswapV2 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 451298a5ac..afb4cb3a12 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -107,9 +107,13 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId( ERC20BridgeSource.MultiHop, ERC20BridgeSource.Nerve, ERC20BridgeSource.PancakeSwap, + ERC20BridgeSource.PancakeSwapV2, ERC20BridgeSource.SushiSwap, ERC20BridgeSource.Smoothy, - ERC20BridgeSource.PancakeSwapV2, + ERC20BridgeSource.ApeSwap, + ERC20BridgeSource.CafeSwap, + ERC20BridgeSource.CheeseSwap, + ERC20BridgeSource.JulSwap, ]), }, @@ -169,9 +173,13 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId( ERC20BridgeSource.MultiHop, ERC20BridgeSource.Nerve, ERC20BridgeSource.PancakeSwap, + ERC20BridgeSource.PancakeSwapV2, ERC20BridgeSource.SushiSwap, ERC20BridgeSource.Smoothy, - ERC20BridgeSource.PancakeSwapV2, + ERC20BridgeSource.ApeSwap, + ERC20BridgeSource.CafeSwap, + ERC20BridgeSource.CheeseSwap, + ERC20BridgeSource.JulSwap, ]), }, new SourceFilters([]), @@ -478,147 +486,147 @@ export const CURVE_MAINNET_INFOS: { [name: string]: CurveInfo } = { [CURVE_POOLS.compound]: createCurveExchangeUnderlyingPool({ tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC], pool: CURVE_POOLS.compound, - gasSchedule: 597e3, + gasSchedule: 587e3, }), [CURVE_POOLS.PAX]: createCurveExchangeUnderlyingPool({ tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT, MAINNET_TOKENS.PAX], pool: CURVE_POOLS.PAX, - gasSchedule: 752e3, + gasSchedule: 742e3, }), [CURVE_POOLS.sUSD]: createCurveExchangeUnderlyingPool({ tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT, MAINNET_TOKENS.sUSD], pool: CURVE_POOLS.sUSD, - gasSchedule: 312e3, + gasSchedule: 302e3, }), [CURVE_POOLS.renBTC]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.WBTC], pool: CURVE_POOLS.renBTC, - gasSchedule: 181e3, + gasSchedule: 171e3, }), [CURVE_POOLS.sBTC]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.WBTC, MAINNET_TOKENS.sBTC], pool: CURVE_POOLS.sBTC, - gasSchedule: 337e3, + gasSchedule: 327e3, }), [CURVE_POOLS.HBTC]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.hBTC, MAINNET_TOKENS.WBTC], pool: CURVE_POOLS.HBTC, - gasSchedule: 220e3, + gasSchedule: 210e3, }), [CURVE_POOLS.TRI]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT], pool: CURVE_POOLS.TRI, - gasSchedule: 186e3, + gasSchedule: 176e3, }), [CURVE_POOLS.GUSD]: createCurveMetaTriPool({ token: MAINNET_TOKENS.GUSD, pool: CURVE_POOLS.GUSD, - gasSchedule: 421e3, + gasSchedule: 411e3, }), [CURVE_POOLS.HUSD]: createCurveMetaTriPool({ token: MAINNET_TOKENS.HUSD, pool: CURVE_POOLS.HUSD, - gasSchedule: 406e3, + gasSchedule: 396e3, }), [CURVE_POOLS.USDN]: createCurveMetaTriPool({ token: MAINNET_TOKENS.USDN, pool: CURVE_POOLS.USDN, - gasSchedule: 408e3, + gasSchedule: 398e3, }), [CURVE_POOLS.mUSD]: createCurveMetaTriPool({ token: MAINNET_TOKENS.mUSD, pool: CURVE_POOLS.mUSD, - gasSchedule: 395e3, + gasSchedule: 385e3, }), [CURVE_POOLS.dUSD]: createCurveMetaTriPool({ token: MAINNET_TOKENS.dUSD, pool: CURVE_POOLS.dUSD, - gasSchedule: 381e3, + gasSchedule: 371e3, }), [CURVE_POOLS.tBTC]: createCurveMetaTriBtcPool({ token: MAINNET_TOKENS.tBTC, pool: CURVE_POOLS.tBTC, - gasSchedule: 492e3, + gasSchedule: 482e3, }), [CURVE_POOLS.pBTC]: createCurveMetaTriBtcPool({ token: MAINNET_TOKENS.pBTC, pool: CURVE_POOLS.pBTC, - gasSchedule: 513e3, + gasSchedule: 503e3, }), [CURVE_POOLS.bBTC]: createCurveMetaTriBtcPool({ token: MAINNET_TOKENS.bBTC, pool: CURVE_POOLS.bBTC, - gasSchedule: 507e3, + gasSchedule: 497e3, }), [CURVE_POOLS.oBTC]: createCurveMetaTriBtcPool({ token: MAINNET_TOKENS.oBTC, pool: CURVE_POOLS.oBTC, - gasSchedule: 498e3, + gasSchedule: 488e3, }), [CURVE_POOLS.UST]: createCurveMetaTriPool({ token: MAINNET_TOKENS.UST, pool: CURVE_POOLS.UST, - gasSchedule: 350e3, + gasSchedule: 340e3, }), [CURVE_POOLS.eurs]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.EURS, MAINNET_TOKENS.sEUR], pool: CURVE_POOLS.eurs, - gasSchedule: 330e3, + gasSchedule: 320e3, }), [CURVE_POOLS.aave]: createCurveExchangeUnderlyingPool({ tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT], pool: CURVE_POOLS.aave, - gasSchedule: 590e3, + gasSchedule: 580e3, }), [CURVE_POOLS.aave]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.aDAI, MAINNET_TOKENS.aUSDC, MAINNET_TOKENS.aUSDT], pool: CURVE_POOLS.aave, - gasSchedule: 590e3, + gasSchedule: 580e3, }), [CURVE_POOLS.saave]: createCurveExchangeUnderlyingPool({ tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.sUSD], pool: CURVE_POOLS.saave, - gasSchedule: 590e3, + gasSchedule: 580e3, }), [CURVE_POOLS.saave]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.aDAI, MAINNET_TOKENS.aSUSD], pool: CURVE_POOLS.saave, - gasSchedule: 590e3, + gasSchedule: 580e3, }), [CURVE_POOLS.USDP]: createCurveMetaTriPool({ token: MAINNET_TOKENS.USDP, pool: CURVE_POOLS.USDP, - gasSchedule: 384e3, + gasSchedule: 374e3, }), [CURVE_POOLS.ib]: createCurveExchangeUnderlyingPool({ tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT], pool: CURVE_POOLS.ib, - gasSchedule: 656e3, + gasSchedule: 646e3, }), [CURVE_POOLS.link]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.LINK, MAINNET_TOKENS.sLINK], pool: CURVE_POOLS.link, - gasSchedule: 329e3, + gasSchedule: 319e3, }), [CURVE_POOLS.TUSD]: createCurveMetaTriPool({ token: MAINNET_TOKENS.TUSD, pool: CURVE_POOLS.TUSD, - gasSchedule: 414e3, + gasSchedule: 404e3, }), [CURVE_POOLS.STABLEx]: createCurveMetaTriPool({ token: MAINNET_TOKENS.STABLEx, pool: CURVE_POOLS.STABLEx, - gasSchedule: 407e3, + gasSchedule: 397e3, }), [CURVE_POOLS.alUSD]: createCurveMetaTriPool({ token: MAINNET_TOKENS.alUSD, pool: CURVE_POOLS.alUSD, - gasSchedule: 397e3, + gasSchedule: 387e3, }), [CURVE_POOLS.FRAX]: createCurveMetaTriPool({ token: MAINNET_TOKENS.FRAX, pool: CURVE_POOLS.FRAX, - gasSchedule: 397e3, + gasSchedule: 387e3, }), }; @@ -626,7 +634,7 @@ export const SWERVE_MAINNET_INFOS: { [name: string]: CurveInfo } = { [SWERVE_POOLS.y]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT, MAINNET_TOKENS.TUSD], pool: SWERVE_POOLS.y, - gasSchedule: 150e3, + gasSchedule: 140e3, }), }; @@ -634,22 +642,22 @@ export const SNOWSWAP_MAINNET_INFOS: { [name: string]: CurveInfo } = { [SNOWSWAP_POOLS.yUSD]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.yUSD, MAINNET_TOKENS.ybCRV], pool: SNOWSWAP_POOLS.yUSD, - gasSchedule: 1000e3, + gasSchedule: 990e3, }), [SNOWSWAP_POOLS.yUSD]: createCurveExchangeUnderlyingPool({ tokens: [MAINNET_TOKENS.yCRV, MAINNET_TOKENS.bCRV], pool: SNOWSWAP_POOLS.yUSD, - gasSchedule: 1000e3, + gasSchedule: 990e3, }), [SNOWSWAP_POOLS.yVault]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.yDAI, MAINNET_TOKENS.yUSDC, MAINNET_TOKENS.yUSDT, MAINNET_TOKENS.yTUSD], pool: SNOWSWAP_POOLS.yVault, - gasSchedule: 1500e3, + gasSchedule: 1490e3, }), [SNOWSWAP_POOLS.eth]: createCurveExchangePool({ tokens: [MAINNET_TOKENS.WETH, MAINNET_TOKENS.vETH, MAINNET_TOKENS.ankrETH, MAINNET_TOKENS.crETH], pool: SNOWSWAP_POOLS.eth, - gasSchedule: 1000e3, + gasSchedule: 990e3, }), }; @@ -657,7 +665,7 @@ export const BELT_BSC_INFOS: { [name: string]: CurveInfo } = { [BELT_POOLS.vPool]: createCurveExchangeUnderlyingPool({ tokens: [BSC_TOKENS.DAI, BSC_TOKENS.USDC, BSC_TOKENS.USDT, BSC_TOKENS.BUSD], pool: BELT_POOLS.vPool, - gasSchedule: 4500e3, + gasSchedule: 4490e3, }), }; @@ -665,7 +673,7 @@ export const ELLIPSIS_BSC_INFOS: { [name: string]: CurveInfo } = { [ELLIPSIS_POOLS.threePool]: createCurveExchangePool({ tokens: [BSC_TOKENS.BUSD, BSC_TOKENS.USDC, BSC_TOKENS.USDT], pool: ELLIPSIS_POOLS.threePool, - gasSchedule: 150e3, + gasSchedule: 140e3, }), }; @@ -678,18 +686,17 @@ export const SADDLE_MAINNET_INFOS: { [name: string]: CurveInfo } = { poolAddress: SADDLE_POOLS.stables, tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT], metaToken: undefined, - gasSchedule: 220e3, + gasSchedule: 150e3, + }, + [SADDLE_POOLS.bitcoins]: { + exchangeFunctionSelector: CurveFunctionSelectors.swap, + sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap, + buyQuoteFunctionSelector: CurveFunctionSelectors.None, + poolAddress: SADDLE_POOLS.bitcoins, + tokens: [MAINNET_TOKENS.tBTC, MAINNET_TOKENS.WBTC, MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.sBTC], + metaToken: undefined, + gasSchedule: 150e3, }, - // TODO:Romain having "Cannot swap more than you own" error when running simbot - // [SADDLE_POOLS.bitcoins]: { - // exchangeFunctionSelector: CurveFunctionSelectors.swap, - // sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap, - // buyQuoteFunctionSelector: CurveFunctionSelectors.None, - // poolAddress: SADDLE_POOLS.stables, - // tokens: [MAINNET_TOKENS.tBTC, MAINNET_TOKENS.WBTC, MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.sBTC], - // metaToken: undefined, - // gasSchedule: 220e3, - // }, }; export const SMOOTHY_MAINNET_INFOS: { [name: string]: CurveInfo } = { @@ -709,7 +716,7 @@ export const SMOOTHY_MAINNET_INFOS: { [name: string]: CurveInfo } = { MAINNET_TOKENS.GUSD, ], metaToken: undefined, - gasSchedule: 200e3, + gasSchedule: 190e3, }, }; @@ -721,7 +728,7 @@ export const SMOOTHY_BSC_INFOS: { [name: string]: CurveInfo } = { poolAddress: SMOOTHY_POOLS.syUSD, tokens: [BSC_TOKENS.BUSD, BSC_TOKENS.USDT, BSC_TOKENS.USDC, BSC_TOKENS.DAI, BSC_TOKENS.PAX, BSC_TOKENS.UST], metaToken: undefined, - gasSchedule: 100e3, + gasSchedule: 90e3, }, }; @@ -733,7 +740,7 @@ export const NERVE_BSC_INFOS: { [name: string]: CurveInfo } = { poolAddress: NERVE_POOLS.threePool, tokens: [BSC_TOKENS.BUSD, BSC_TOKENS.USDT, BSC_TOKENS.USDC], metaToken: undefined, - gasSchedule: 150e3, + gasSchedule: 140e3, }, }; @@ -993,7 +1000,7 @@ export const PANCAKESWAP_ROUTER_BY_CHAIN_ID = valueByChainId( NULL_ADDRESS, ); -export const PANCAKESWAP_V2_ROUTER_BY_CHAIN_ID = valueByChainId( +export const PANCAKESWAPV2_ROUTER_BY_CHAIN_ID = valueByChainId( { [ChainId.BSC]: '0x10ed43c718714eb63d5aa57b78b54704e256024e', }, @@ -1007,6 +1014,34 @@ export const BAKERYSWAP_ROUTER_BY_CHAIN_ID = valueByChainId( NULL_ADDRESS, ); +export const APESWAP_ROUTER_BY_CHAIN_ID = valueByChainId( + { + [ChainId.BSC]: '0xc0788a3ad43d79aa53b09c2eacc313a787d1d607', + }, + NULL_ADDRESS, +); + +export const CAFESWAP_ROUTER_BY_CHAIN_ID = valueByChainId( + { + [ChainId.BSC]: '0x933daea3a5995fb94b14a7696a5f3ffd7b1e385a', + }, + NULL_ADDRESS, +); + +export const CHEESESWAP_ROUTER_BY_CHAIN_ID = valueByChainId( + { + [ChainId.BSC]: '0x3047799262d8d2ef41ed2a222205968bc9b0d895', + }, + NULL_ADDRESS, +); + +export const JULSWAP_ROUTER_BY_CHAIN_ID = valueByChainId( + { + [ChainId.BSC]: '0xbd67d157502a23309db761c41965600c2ec788b2', + }, + NULL_ADDRESS, +); + /** * Calculated gross gas cost of the underlying exchange. * The cost of switching from one source to another, assuming @@ -1137,6 +1172,15 @@ export const DEFAULT_GAS_SCHEDULE: Required = { } return gas; }, + [ERC20BridgeSource.PancakeSwapV2]: (fillData?: FillData) => { + // TODO: Different base cost if to/from ETH. + let gas = 90e3; + const path = (fillData as UniswapV2FillData).tokenAddressPath; + if (path.length > 2) { + gas += (path.length - 2) * 60e3; // +60k for each hop. + } + return gas; + }, [ERC20BridgeSource.BakerySwap]: (fillData?: FillData) => { // TODO: Different base cost if to/from ETH. let gas = 90e3; @@ -1146,7 +1190,34 @@ export const DEFAULT_GAS_SCHEDULE: Required = { } return gas; }, - [ERC20BridgeSource.PancakeSwapV2]: (fillData?: FillData) => { + [ERC20BridgeSource.ApeSwap]: (fillData?: FillData) => { + // TODO: Different base cost if to/from ETH. + let gas = 90e3; + const path = (fillData as UniswapV2FillData).tokenAddressPath; + if (path.length > 2) { + gas += (path.length - 2) * 60e3; // +60k for each hop. + } + return gas; + }, + [ERC20BridgeSource.CafeSwap]: (fillData?: FillData) => { + // TODO: Different base cost if to/from ETH. + let gas = 90e3; + const path = (fillData as UniswapV2FillData).tokenAddressPath; + if (path.length > 2) { + gas += (path.length - 2) * 60e3; // +60k for each hop. + } + return gas; + }, + [ERC20BridgeSource.CheeseSwap]: (fillData?: FillData) => { + // TODO: Different base cost if to/from ETH. + let gas = 90e3; + const path = (fillData as UniswapV2FillData).tokenAddressPath; + if (path.length > 2) { + gas += (path.length - 2) * 60e3; // +60k for each hop. + } + return gas; + }, + [ERC20BridgeSource.JulSwap]: (fillData?: FillData) => { // TODO: Different base cost if to/from ETH. let gas = 90e3; const path = (fillData as UniswapV2FillData).tokenAddressPath; diff --git a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts index 7c54b3f024..fe9049b161 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -120,6 +120,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'Linkswap'); case ERC20BridgeSource.PancakeSwap: return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwap'); + case ERC20BridgeSource.PancakeSwapV2: + return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwapV2'); case ERC20BridgeSource.BakerySwap: return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'BakerySwap'); case ERC20BridgeSource.Nerve: @@ -134,8 +136,14 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s return encodeBridgeSourceId(BridgeProtocol.Curve, 'Smoothy'); case ERC20BridgeSource.Saddle: return encodeBridgeSourceId(BridgeProtocol.Nerve, 'Saddle'); - case ERC20BridgeSource.PancakeSwapV2: - return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwapV2'); + case ERC20BridgeSource.ApeSwap: + return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'ApeSwap'); + case ERC20BridgeSource.CafeSwap: + return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'CafeSwap'); + case ERC20BridgeSource.CheeseSwap: + return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'CheeseSwap'); + case ERC20BridgeSource.JulSwap: + return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'JulSwap'); default: throw new Error(AggregationError.NoBridgeForSource); } @@ -187,9 +195,13 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder case ERC20BridgeSource.CryptoCom: case ERC20BridgeSource.Linkswap: case ERC20BridgeSource.PancakeSwap: + case ERC20BridgeSource.PancakeSwapV2: case ERC20BridgeSource.BakerySwap: case ERC20BridgeSource.KyberDmm: - case ERC20BridgeSource.PancakeSwapV2: + case ERC20BridgeSource.ApeSwap: + case ERC20BridgeSource.CafeSwap: + case ERC20BridgeSource.CheeseSwap: + case ERC20BridgeSource.JulSwap: const uniswapV2FillData = (order as OptimizedMarketBridgeOrder).fillData; bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]); break; @@ -323,6 +335,14 @@ export const BRIDGE_ENCODERS: { [ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder, [ERC20BridgeSource.Linkswap]: routerAddressPathEncoder, [ERC20BridgeSource.KyberDmm]: routerAddressPathEncoder, + // BSC + [ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder, + [ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder, + [ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder, + [ERC20BridgeSource.ApeSwap]: routerAddressPathEncoder, + [ERC20BridgeSource.CafeSwap]: routerAddressPathEncoder, + [ERC20BridgeSource.CheeseSwap]: routerAddressPathEncoder, + [ERC20BridgeSource.JulSwap]: routerAddressPathEncoder, // Generic pools [ERC20BridgeSource.Shell]: poolEncoder, [ERC20BridgeSource.Component]: poolEncoder, @@ -334,10 +354,6 @@ export const BRIDGE_ENCODERS: { [ERC20BridgeSource.Uniswap]: poolEncoder, // Custom integrations [ERC20BridgeSource.MakerPsm]: makerPsmEncoder, - // BSC - [ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder, - [ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder, - [ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder, }; function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] { 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 2f02604ee2..efd25e8edf 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 @@ -1100,9 +1100,13 @@ export class SamplerOperations { case ERC20BridgeSource.SushiSwap: case ERC20BridgeSource.CryptoCom: case ERC20BridgeSource.PancakeSwap: + case ERC20BridgeSource.PancakeSwapV2: case ERC20BridgeSource.BakerySwap: case ERC20BridgeSource.KyberDmm: - case ERC20BridgeSource.PancakeSwapV2: + case ERC20BridgeSource.ApeSwap: + case ERC20BridgeSource.CafeSwap: + case ERC20BridgeSource.CheeseSwap: + case ERC20BridgeSource.JulSwap: const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); if (!isValidAddress(uniLikeRouter)) { return []; @@ -1310,9 +1314,13 @@ export class SamplerOperations { case ERC20BridgeSource.SushiSwap: case ERC20BridgeSource.CryptoCom: case ERC20BridgeSource.PancakeSwap: + case ERC20BridgeSource.PancakeSwapV2: case ERC20BridgeSource.BakerySwap: case ERC20BridgeSource.KyberDmm: - case ERC20BridgeSource.PancakeSwapV2: + case ERC20BridgeSource.ApeSwap: + case ERC20BridgeSource.CafeSwap: + case ERC20BridgeSource.CheeseSwap: + case ERC20BridgeSource.JulSwap: const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); if (!isValidAddress(uniLikeRouter)) { return []; diff --git a/packages/asset-swapper/src/utils/market_operation_utils/types.ts b/packages/asset-swapper/src/utils/market_operation_utils/types.ts index 1aa1ad1058..e9e2f30599 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/types.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/types.ts @@ -65,11 +65,15 @@ export enum ERC20BridgeSource { Saddle = 'Saddle', // BSC only PancakeSwap = 'PancakeSwap', + PancakeSwapV2 = 'PancakeSwap_V2', BakerySwap = 'BakerySwap', Nerve = 'Nerve', Belt = 'Belt', Ellipsis = 'Ellipsis', - PancakeSwapV2 = 'PancakeSwap_V2', + ApeSwap = 'ApeSwap', + CafeSwap = 'CafeSwap', + CheeseSwap = 'CheeseSwap', + JulSwap = 'JulSwap', } // tslint:disable: enum-naming