Compare commits

..

33 Commits

Author SHA1 Message Date
Github Actions
b358559421 Publish
- @0x/contracts-integrations@2.7.60
 - @0x/asset-swapper@16.23.0
2021-07-16 22:11:44 +00:00
Github Actions
df5aad8e8e Updated CHANGELOGS & MD docs 2021-07-16 22:11:39 +00:00
Andreas Andreakis
8dbf79db59 fix: lint (#289) 2021-07-16 12:24:56 -07:00
Andreas Andreakis
1839608e84 feat: ACryptoS StableSwap (#284) 2021-07-15 15:19:40 -07:00
Github Actions
6e3e795b8b Publish
- @0x/contracts-integrations@2.7.59
 - @0x/asset-swapper@16.22.0
2021-07-13 22:19:54 +00:00
Github Actions
d9c410a7e3 Updated CHANGELOGS & MD docs 2021-07-13 22:19:49 +00:00
Romain Butteaud
609727afe8 feat: Saddle alETH, D4 pools (#283) 2021-07-13 14:22:16 -07:00
Romain Butteaud
8a5c74c0b4 feat: IronSwap (#281)
* feat: IronSwap

* feat: IronSwap, changelog

* feat: IronSwap, prettier
2021-07-13 14:07:45 -07:00
Github Actions
cd93f3b07e Publish
- @0x/contracts-integrations@2.7.58
 - @0x/asset-swapper@16.21.0
2021-07-10 08:00:34 +00:00
Github Actions
8397b12de6 Updated CHANGELOGS & MD docs 2021-07-10 08:00:29 +00:00
Romain Butteaud
3f85acec3a feat: JetSwap (#280)
* feat: JetSwap

* feat: JetSwap, changelog
2021-07-10 00:18:29 -07:00
phil-ociraptor
d6a9e3d600 fix: uncaught type error while logging (#277) 2021-07-07 14:28:42 -05:00
phil-ociraptor
361569ac2f chore: emit a log when a quote is returned that is between 99-100% of quote (#275) 2021-07-06 17:19:41 -05:00
Github Actions
719664c145 Publish
- @0x/contracts-integrations@2.7.57
 - @0x/asset-swapper@16.20.0
2021-07-06 21:34:44 +00:00
Github Actions
f800d6c24c Updated CHANGELOGS & MD docs 2021-07-06 21:34:39 +00:00
Romain Butteaud
a9a81bcafb feat: ShibaSwap (#276) 2021-07-06 13:53:39 -07:00
Github Actions
4280307a15 Publish
- @0x/contracts-integrations@2.7.56
 - @0x/asset-swapper@16.19.1
2021-07-06 04:03:16 +00:00
Github Actions
7b57d3ae51 Updated CHANGELOGS & MD docs 2021-07-06 04:03:11 +00:00
Romain Butteaud
8a8a5bbda0 fix: adding MultiHop for Polygon (#271) 2021-07-06 13:33:41 +10:00
Jacob Evans
76987c8db1 fix: PLP fallback (#272)
* fix: PLP fallback

* CHANGELOG
2021-07-06 13:32:34 +10:00
Github Actions
6f8971cc42 Publish
- @0x/contracts-integrations@2.7.55
 - @0x/asset-swapper@16.19.0
2021-07-02 01:48:13 +00:00
Github Actions
71ab882143 Updated CHANGELOGS & MD docs 2021-07-02 01:48:08 +00:00
Romain Butteaud
5a4961c8d9 fix: KyberDMM pick best pools, Polygon KyberDMM (#269)
* fix: KyberDMM all pools, Polygon KyberDMM

* fix: KyberDMM, remove getPoolsLength interface and revert if no pools found
2021-07-01 18:07:02 -07:00
mzhu25
4c4fb99d87 Add PLP as a source for Polygon (#270)
* Whitelist PLP as a source for Polygon

* changelog
2021-07-01 17:21:23 -07:00
Github Actions
872abf09e9 Publish
- @0x/contracts-integrations@2.7.54
 - @0x/asset-swapper@6.18.3
2021-06-29 17:20:15 +00:00
Github Actions
f10bfe7d04 Updated CHANGELOGS & MD docs 2021-06-29 17:20:11 +00:00
Romain Butteaud
a74d8deff3 feat: Balancer V2 Polygon (#267) 2021-06-29 09:46:17 -07:00
Github Actions
835ee4e8de Publish
- @0x/contracts-integrations@2.7.53
 - @0x/asset-swapper@6.18.2
2021-06-24 19:25:12 +00:00
Github Actions
63ec42303f Updated CHANGELOGS & MD docs 2021-06-24 19:25:07 +00:00
Romain Butteaud
f789aebddc fix: duplicate SOURCE_FLAGS index (#266) 2021-06-24 11:58:05 -07:00
Github Actions
efd83be779 Publish
- @0x/contracts-integrations@2.7.52
 - @0x/asset-swapper@6.18.1
2021-06-22 23:37:28 +00:00
Github Actions
603bc1d51c Updated CHANGELOGS & MD docs 2021-06-22 23:37:23 +00:00
Romain Butteaud
32a930a7fc feat: FirebirdOneSwap, ApeSwap [TKR-182] [TKR-173] (#265)
* fix: removing TITAN and IRON as intermediate tokens

* feat: FirebirdOneSwap, ApeSwap, intermediate tokens update

* chore: changelog
2021-06-22 16:04:09 -07:00
18 changed files with 596 additions and 48 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-integrations",
"version": "2.7.51",
"version": "2.7.60",
"private": true,
"engines": {
"node": ">=6.12"
@@ -93,7 +93,7 @@
"typescript": "4.2.2"
},
"dependencies": {
"@0x/asset-swapper": "^6.18.0",
"@0x/asset-swapper": "^16.23.0",
"@0x/base-contract": "^6.4.0",
"@0x/contracts-asset-proxy": "^3.7.16",
"@0x/contracts-erc1155": "^2.1.34",

View File

@@ -1,4 +1,92 @@
[
{
"version": "16.23.0",
"changes": [
{
"note": "ACryptoS",
"pr": 284
}
],
"timestamp": 1626473497
},
{
"version": "16.22.0",
"changes": [
{
"note": "IronSwap",
"pr": 281
}
],
"timestamp": 1626214787
},
{
"version": "16.21.0",
"changes": [
{
"note": "JetSwap",
"pr": 280
}
],
"timestamp": 1625904026
},
{
"version": "16.20.0",
"changes": [
{
"note": "ShibaSwap",
"pr": 276
}
],
"timestamp": 1625607277
},
{
"version": "16.19.1",
"changes": [
{
"note": "Fix LiquidityProvider fallback",
"pr": 272
}
],
"timestamp": 1625544188
},
{
"version": "16.19.0",
"changes": [
{
"note": "Add LiquidityProvider to Polygon sources",
"pr": 270
}
],
"timestamp": 1625190486
},
{
"version": "6.18.3",
"changes": [
{
"note": "Polygon Balance V2"
}
],
"timestamp": 1624987208
},
{
"timestamp": 1624562704,
"version": "6.18.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "6.18.1",
"changes": [
{
"note": "FirebirdOneSwap, ApeSwap. New hop tokens: DFYN, BANANA, WEXPOLY",
"pr": 265
}
],
"timestamp": 1624405040
},
{
"version": "6.18.0",
"changes": [

View File

@@ -5,6 +5,42 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v16.23.0 - _July 16, 2021_
* ACryptoS (#284)
## v16.22.0 - _July 13, 2021_
* IronSwap (#281)
## v16.21.0 - _July 10, 2021_
* JetSwap (#280)
## v16.20.0 - _July 6, 2021_
* ShibaSwap (#276)
## v16.19.1 - _July 6, 2021_
* Fix LiquidityProvider fallback (#272)
## v16.19.0 - _July 2, 2021_
* Add LiquidityProvider to Polygon sources (#270)
## v6.18.3 - _June 29, 2021_
* Polygon Balance V2
## v6.18.2 - _June 24, 2021_
* Dependencies updated
## v6.18.1 - _June 22, 2021_
* FirebirdOneSwap, ApeSwap. New hop tokens: DFYN, BANANA, WEXPOLY (#265)
## v6.18.0 - _June 22, 2021_
* Add Lido stETH deposit integration (#260)

View File

@@ -20,12 +20,20 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
interface IKyberDmmFactory {
interface IKyberDmmPool {
function getPoolAtIndex(address token0, address token1, uint256 index)
function totalSupply()
external
view
returns (address);
returns (uint256);
}
interface IKyberDmmFactory {
function getPools(address token0, address token1)
external
view
returns (address[] memory _tokenPools);
}
interface IKyberDmmRouter {
@@ -140,17 +148,26 @@ contract KyberDmmSampler
view
returns (address[] memory pools)
{
pools = new address[](path.length - 1);
IKyberDmmFactory factory = IKyberDmmFactory(IKyberDmmRouter(router).factory());
pools = new address[](path.length - 1);
for (uint256 i = 0; i < pools.length; i++) {
// Currently only supporting the first pool found at the index
// find the best pool
address[] memory allPools;
try
factory.getPoolAtIndex
factory.getPools
{gas: KYBER_DMM_CALL_GAS}
(path[i], path[i + 1], 0)
returns (address pool)
(path[i], path[i + 1])
returns (address[] memory allPools)
{
pools[i] = pool;
uint256 maxSupply = 0;
require(allPools.length >= 1, "KyberDMMSampler/NO_POOLS_FOUND");
for (uint256 j = 0; j < allPools.length; j++) {
uint256 totalSupply = IKyberDmmPool(allPools[j]).totalSupply();
if (totalSupply > maxSupply) {
maxSupply = totalSupply;
pools[i] = allPools[j];
}
}
} catch (bytes memory) {
return new address[](0);
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/asset-swapper",
"version": "6.18.0",
"version": "16.23.0",
"engines": {
"node": ">=6.12"
},

View File

@@ -2,6 +2,7 @@ import { ChainId } from '@0x/contract-addresses';
import { BigNumber, NULL_BYTES } from '@0x/utils';
import {
ACRYPTOS_BSC_INFOS,
APESWAP_ROUTER_BY_CHAIN_ID,
BAKERYSWAP_ROUTER_BY_CHAIN_ID,
BELT_BSC_INFOS,
@@ -16,6 +17,10 @@ import {
CURVE_V2_POLYGON_INFOS,
DFYN_ROUTER_BY_CHAIN_ID,
ELLIPSIS_BSC_INFOS,
FIREBIRDONESWAP_BSC_INFOS,
FIREBIRDONESWAP_POLYGON_INFOS,
IRONSWAP_POLYGON_INFOS,
JETSWAP_ROUTER_BY_CHAIN_ID,
JULSWAP_ROUTER_BY_CHAIN_ID,
KYBER_BANNED_RESERVES,
KYBER_BRIDGED_LIQUIDITY_PREFIX,
@@ -30,13 +35,14 @@ import {
QUICKSWAP_ROUTER_BY_CHAIN_ID,
SADDLE_MAINNET_INFOS,
SHELL_POOLS_BY_CHAIN_ID,
SHIBASWAP_ROUTER_BY_CHAIN_ID,
SMOOTHY_BSC_INFOS,
SMOOTHY_MAINNET_INFOS,
SNOWSWAP_MAINNET_INFOS,
SUSHISWAP_ROUTER_BY_CHAIN_ID,
SWERVE_MAINNET_INFOS,
UNISWAPV2_ROUTER_BY_CHAIN_ID,
WAULT_ROUTER_BY_CHAIN_ID,
WAULTSWAP_ROUTER_BY_CHAIN_ID,
XSIGMA_MAINNET_INFOS,
} from './constants';
import { CurveInfo, ERC20BridgeSource } from './types';
@@ -195,6 +201,30 @@ export function getNerveInfosForPair(chainId: ChainId, takerToken: string, maker
);
}
export function getFirebirdOneSwapInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId === ChainId.BSC) {
return Object.values(FIREBIRDONESWAP_BSC_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaTokens === undefined) ||
(c.tokens.includes(t) &&
[makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
),
);
} else if (chainId === ChainId.Polygon) {
return Object.values(FIREBIRDONESWAP_POLYGON_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaTokens === undefined) ||
(c.tokens.includes(t) &&
[makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
),
);
} else {
return [];
}
}
export function getBeltInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.BSC) {
return [];
@@ -258,6 +288,19 @@ export function getSaddleInfosForPair(chainId: ChainId, takerToken: string, make
);
}
export function getIronSwapInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.Polygon) {
return [];
}
return Object.values(IRONSWAP_POLYGON_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaTokens === undefined) ||
(c.tokens.includes(t) && [makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
),
);
}
export function getXSigmaInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.Mainnet) {
return [];
@@ -271,6 +314,19 @@ export function getXSigmaInfosForPair(chainId: ChainId, takerToken: string, make
);
}
export function getAcryptosInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.BSC) {
return [];
}
return Object.values(ACRYPTOS_BSC_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaTokens === undefined) ||
(c.tokens.includes(t) && [makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
),
);
}
export function getShellLikeInfosForPair(
chainId: ChainId,
takerToken: string,
@@ -308,7 +364,10 @@ export function getCurveLikeInfosForPair(
| ERC20BridgeSource.Ellipsis
| ERC20BridgeSource.Smoothy
| ERC20BridgeSource.Saddle
| ERC20BridgeSource.XSigma,
| ERC20BridgeSource.IronSwap
| ERC20BridgeSource.XSigma
| ERC20BridgeSource.FirebirdOneSwap
| ERC20BridgeSource.ACryptos,
): CurveDetailedInfo[] {
let pools: CurveInfo[] = [];
switch (source) {
@@ -342,6 +401,15 @@ export function getCurveLikeInfosForPair(
case ERC20BridgeSource.XSigma:
pools = getXSigmaInfosForPair(chainId, takerToken, makerToken);
break;
case ERC20BridgeSource.FirebirdOneSwap:
pools = getFirebirdOneSwapInfosForPair(chainId, takerToken, makerToken);
break;
case ERC20BridgeSource.IronSwap:
pools = getIronSwapInfosForPair(chainId, takerToken, makerToken);
break;
case ERC20BridgeSource.ACryptos:
pools = getAcryptosInfosForPair(chainId, takerToken, makerToken);
break;
default:
throw new Error(`Unknown Curve like source ${source}`);
}
@@ -369,7 +437,9 @@ export function uniswapV2LikeRouterAddress(
| ERC20BridgeSource.ComethSwap
| ERC20BridgeSource.Dfyn
| ERC20BridgeSource.WaultSwap
| ERC20BridgeSource.Polydex,
| ERC20BridgeSource.Polydex
| ERC20BridgeSource.ShibaSwap
| ERC20BridgeSource.JetSwap,
): string {
switch (source) {
case ERC20BridgeSource.UniswapV2:
@@ -399,9 +469,13 @@ export function uniswapV2LikeRouterAddress(
case ERC20BridgeSource.Dfyn:
return DFYN_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.WaultSwap:
return WAULT_ROUTER_BY_CHAIN_ID[chainId];
return WAULTSWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.Polydex:
return POLYDEX_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.ShibaSwap:
return SHIBASWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.JetSwap:
return JETSWAP_ROUTER_BY_CHAIN_ID[chainId];
default:
throw new Error(`Unknown UniswapV2 like source ${source}`);
}

View File

@@ -97,6 +97,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.XSigma,
ERC20BridgeSource.UniswapV3,
ERC20BridgeSource.CurveV2,
ERC20BridgeSource.ShibaSwap,
]),
[ChainId.Ropsten]: new SourceFilters([
ERC20BridgeSource.Kyber,
@@ -130,6 +131,9 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.JulSwap,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.WaultSwap,
ERC20BridgeSource.FirebirdOneSwap,
ERC20BridgeSource.JetSwap,
ERC20BridgeSource.ACryptos,
]),
[ChainId.Polygon]: new SourceFilters([
ERC20BridgeSource.SushiSwap,
@@ -143,6 +147,14 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.CurveV2,
ERC20BridgeSource.WaultSwap,
ERC20BridgeSource.Polydex,
ERC20BridgeSource.ApeSwap,
ERC20BridgeSource.FirebirdOneSwap,
ERC20BridgeSource.BalancerV2,
ERC20BridgeSource.KyberDmm,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.MultiHop,
ERC20BridgeSource.JetSwap,
ERC20BridgeSource.IronSwap,
]),
},
new SourceFilters([]),
@@ -185,6 +197,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.XSigma,
ERC20BridgeSource.UniswapV3,
ERC20BridgeSource.CurveV2,
ERC20BridgeSource.ShibaSwap,
]),
[ChainId.Ropsten]: new SourceFilters([
ERC20BridgeSource.Kyber,
@@ -218,6 +231,9 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.JulSwap,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.WaultSwap,
ERC20BridgeSource.FirebirdOneSwap,
ERC20BridgeSource.JetSwap,
ERC20BridgeSource.ACryptos,
]),
[ChainId.Polygon]: new SourceFilters([
ERC20BridgeSource.SushiSwap,
@@ -231,6 +247,14 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.CurveV2,
ERC20BridgeSource.WaultSwap,
ERC20BridgeSource.Polydex,
ERC20BridgeSource.ApeSwap,
ERC20BridgeSource.FirebirdOneSwap,
ERC20BridgeSource.BalancerV2,
ERC20BridgeSource.KyberDmm,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.MultiHop,
ERC20BridgeSource.JetSwap,
ERC20BridgeSource.IronSwap,
]),
},
new SourceFilters([]),
@@ -256,13 +280,13 @@ export const FEE_QUOTE_SOURCES_BY_CHAIN_ID = valueByChainId<ERC20BridgeSource[]>
// HACK(mzhu25): Limit and RFQ orders need to be treated as different sources
// when computing the exchange proxy gas overhead.
export const SOURCE_FLAGS: { [key in ERC20BridgeSource]: number } & {
RfqOrder: number;
LimitOrder: number;
export const SOURCE_FLAGS: { [key in ERC20BridgeSource]: bigint } & {
RfqOrder: bigint;
LimitOrder: bigint;
} = Object.assign(
{},
...['RfqOrder', 'LimitOrder', ...Object.values(ERC20BridgeSource)].map((source, index) => ({
[source]: source === ERC20BridgeSource.Native ? 0 : 1 << index,
[source]: source === ERC20BridgeSource.Native ? BigInt(0) : BigInt(1) << BigInt(index),
})),
);
@@ -337,6 +361,7 @@ export const MAINNET_TOKENS = {
crETH: '0xcbc1065255cbc3ab41a6868c22d1f1c573ab89fd',
ankrETH: '0xe95a203b1a91a908f9b9ce46459d101078c2c3cb',
vETH: '0x898bad2774eb97cf6b94605677f43b41871410b1',
alETH: '0x0100546f2cd4c9d97f798ffc9755e47865ff7ee6',
HT: '0x6f259637dcD74C767781E37Bc6133cd6A68aa161',
// Mirror Protocol
UST: '0xa47c8bf37f92abed4a126bda807a7b7498661acd',
@@ -347,15 +372,23 @@ export const MAINNET_TOKENS = {
alUSD: '0xbc6da0fe9ad5f3b0d58160288917aa56653660e9',
FRAX: '0x853d955acef822db058eb8505911ed77f175b99e',
LUSD: '0x5f98805a4e8be255a32880fdec7f6728c6568ba0',
FEI: '0x956f47f50a910163d8bf957cf5846d573e7f87ca',
};
export const BSC_TOKENS = {
WBNB: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c',
BUSD: '0xe9e7cea3dedca5984780bafc599bd69add087d56',
USDT: '0x55d398326f99059ff775485246999027b3197955',
USDC: '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d',
DAI: '0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3',
PAX: '0xb7f8cd00c5a06c0537e2abff0b58033d02e5e094',
UST: '0x23396cf899ca06c4472205fc903bdb4de249d6fc',
VAI: '0x4bd17003473389a42daf6a0a729f6fdb328bbbd7',
WEX: '0xa9c41a46a6b3531d28d5c32f6633dd2ff05dfb90',
WETH: '0x2170ed0880ac9a755fd29b2688956bd959f933f8',
BTCB: '0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c',
renBTC: '0xfce146bf3146100cfe5db4129cf6c82b0ef4ad8c',
pBTC: '0xed28a457a5a76596ac48d87c0f577020f6ea1c4c',
};
export const POLYGON_TOKENS = {
@@ -370,8 +403,9 @@ export const POLYGON_TOKENS = {
WETH: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
renBTC: '0xdbf31df14b66535af65aac99c32e9ea844e14501',
QUICK: '0x831753dd7087cac61ab5644b308642cc1c33dc13',
TITAN: '0xaaa5b9e6c589642f98a1cda99b9d024b8407285a',
IRON: '0xd86b5923f3ad7b585ed81b448170ae026c65ae9a',
DFYN: '0xc168e40227e4ebd8c1cae80f7a55a4f0e6d66c97',
BANANA: '0x5d47baba0d66083c52009271faf3f50dcc01023c',
WEXPOLY: '0x4c4bf319237d98a30a929a96112effa8da3510eb',
};
export const CURVE_POOLS = {
@@ -451,6 +485,12 @@ export const SMOOTHY_POOLS = {
export const SADDLE_POOLS = {
stables: '0x3911f80530595fbd01ab1516ab61255d75aeb066',
bitcoins: '0x4f6a43ad7cba042606decaca730d4ce0a57ac62e',
alETH: '0xa6018520eaacc06c30ff2e1b3ee2c7c22e64196a',
d4: '0xc69ddcd4dfef25d8a793241834d4cc4b3668ead6',
};
export const IRONSWAP_POOLS = {
is3usd: '0x837503e8a8753ae17fb8c8151b8e6f586defcb57',
};
export const NERVE_POOLS = {
@@ -469,6 +509,21 @@ export const XSIGMA_POOLS = {
stable: '0x3333333ACdEdBbC9Ad7bda0876e60714195681c5',
};
export const FIREBIRDONESWAP_BSC_POOLS = {
oneswap: '0x01c9475dbd36e46d1961572c8de24b74616bae9e',
};
export const FIREBIRDONESWAP_POLYGON_POOLS = {
oneswap: '0x01c9475dbd36e46d1961572c8de24b74616bae9e',
};
export const ACRYPTOS_POOLS = {
acs4usd: '0xb3f0c9ea1f05e312093fdb031e789a756659b0ac',
acs4vai: '0x191409d5a4effe25b0f4240557ba2192d18a191e',
acs4ust: '0x99c92765efc472a9709ced86310d64c4573c4b77',
acs3btc: '0xbe7caa236544d1b9a0e7f91e94b9f5bfd3b5ca81',
};
export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
{
[ChainId.Mainnet]: [
@@ -479,12 +534,13 @@ export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
MAINNET_TOKENS.WBTC,
],
[ChainId.BSC]: [
'0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', // WBNB
'0xe9e7cea3dedca5984780bafc599bd69add087d56', // BUSD
'0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3', // DAI
'0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', // USDC
'0x2170ed0880ac9a755fd29b2688956bd959f933f8', // ETH
'0x55d398326f99059ff775485246999027b3197955', // BUSD-T
BSC_TOKENS.WBNB,
BSC_TOKENS.BUSD,
BSC_TOKENS.DAI,
BSC_TOKENS.USDC,
BSC_TOKENS.WETH,
BSC_TOKENS.USDT,
BSC_TOKENS.WEX,
],
[ChainId.Ropsten]: [
getContractAddressesForChainOrThrow(ChainId.Ropsten).etherToken,
@@ -498,9 +554,6 @@ export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
POLYGON_TOKENS.DAI,
POLYGON_TOKENS.USDT,
POLYGON_TOKENS.WBTC,
POLYGON_TOKENS.QUICK,
POLYGON_TOKENS.TITAN,
POLYGON_TOKENS.IRON,
],
},
[],
@@ -886,7 +939,7 @@ export const XSIGMA_MAINNET_INFOS: { [name: string]: CurveInfo } = {
}),
};
// Curve pools like using custom selectors
// Curve-like sources using custom selectors
export const SADDLE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
[SADDLE_POOLS.stables]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
@@ -906,6 +959,36 @@ export const SADDLE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
metaTokens: undefined,
gasSchedule: 150e3,
},
[SADDLE_POOLS.alETH]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: SADDLE_POOLS.alETH,
tokens: [MAINNET_TOKENS.WETH, MAINNET_TOKENS.alETH, MAINNET_TOKENS.sETH],
metaTokens: undefined,
gasSchedule: 200e3,
},
[SADDLE_POOLS.d4]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: SADDLE_POOLS.d4,
tokens: [MAINNET_TOKENS.alUSD, MAINNET_TOKENS.FEI, MAINNET_TOKENS.FRAX, MAINNET_TOKENS.LUSD],
metaTokens: undefined,
gasSchedule: 150e3,
},
};
export const IRONSWAP_POLYGON_INFOS: { [name: string]: CurveInfo } = {
[IRONSWAP_POOLS.is3usd]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: IRONSWAP_POOLS.is3usd,
tokens: [POLYGON_TOKENS.USDC, POLYGON_TOKENS.USDT, POLYGON_TOKENS.DAI],
metaTokens: undefined,
gasSchedule: 150e3,
},
};
export const SMOOTHY_MAINNET_INFOS: { [name: string]: CurveInfo } = {
@@ -953,6 +1036,68 @@ export const NERVE_BSC_INFOS: { [name: string]: CurveInfo } = {
},
};
export const FIREBIRDONESWAP_BSC_INFOS: { [name: string]: CurveInfo } = {
[FIREBIRDONESWAP_BSC_POOLS.oneswap]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: FIREBIRDONESWAP_BSC_POOLS.oneswap,
tokens: [BSC_TOKENS.BUSD, BSC_TOKENS.USDT, BSC_TOKENS.DAI, BSC_TOKENS.USDC],
metaTokens: undefined,
gasSchedule: 100e3,
},
};
export const FIREBIRDONESWAP_POLYGON_INFOS: { [name: string]: CurveInfo } = {
[FIREBIRDONESWAP_POLYGON_POOLS.oneswap]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: FIREBIRDONESWAP_POLYGON_POOLS.oneswap,
tokens: [POLYGON_TOKENS.DAI, POLYGON_TOKENS.USDC, POLYGON_TOKENS.USDT],
metaTokens: undefined,
gasSchedule: 100e3,
},
};
const ACRYPTOS_ACS4USD_POOL_BSC_TOKENS = [BSC_TOKENS.BUSD, BSC_TOKENS.USDT, BSC_TOKENS.DAI, BSC_TOKENS.USDC];
const createAcryptosMetaUsdPool = (info: { tokens: string[]; pool: string; gasSchedule: number }) => ({
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
tokens: [...info.tokens, ...ACRYPTOS_ACS4USD_POOL_BSC_TOKENS],
metaTokens: info.tokens,
poolAddress: info.pool,
gasSchedule: info.gasSchedule,
});
export const ACRYPTOS_BSC_INFOS: { [name: string]: CurveInfo } = {
[ACRYPTOS_POOLS.acs4usd]: createCurveExchangePool({
tokens: ACRYPTOS_ACS4USD_POOL_BSC_TOKENS,
pool: ACRYPTOS_POOLS.acs4usd,
gasSchedule: 145e3,
}),
[ACRYPTOS_POOLS.acs4vai]: createAcryptosMetaUsdPool({
tokens: [BSC_TOKENS.VAI],
pool: ACRYPTOS_POOLS.acs4vai,
gasSchedule: 300e3,
}),
[ACRYPTOS_POOLS.acs4ust]: createAcryptosMetaUsdPool({
tokens: [BSC_TOKENS.UST],
pool: ACRYPTOS_POOLS.acs4ust,
gasSchedule: 300e3,
}),
[ACRYPTOS_POOLS.acs3btc]: createCurveExchangePool({
tokens: [BSC_TOKENS.BTCB, BSC_TOKENS.renBTC, BSC_TOKENS.pBTC],
pool: ACRYPTOS_POOLS.acs3btc,
gasSchedule: 145e3,
}),
};
/**
* Kyber reserve prefixes
* 0xff Fed price reserve
@@ -1046,6 +1191,13 @@ export const LINKSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
NULL_ADDRESS,
);
export const SHIBASWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.Mainnet]: '0x03f7724180aa6b939894b5ca4314783b0b36b329',
},
NULL_ADDRESS,
);
export const MSTABLE_POOLS_BY_CHAIN_ID = valueByChainId(
{
[ChainId.Mainnet]: {
@@ -1091,6 +1243,7 @@ export const OASIS_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
export const KYBER_DMM_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.Mainnet]: '0x1c87257f5e8609940bc751a07bb085bb7f8cdbe6',
[ChainId.Polygon]: '0x546c79662e028b661dfb4767664d0273184e4dd1',
},
NULL_ADDRESS,
);
@@ -1239,6 +1392,7 @@ export const COMPONENT_POOLS_BY_CHAIN_ID = valueByChainId(
export const BALANCER_V2_VAULT_ADDRESS_BY_CHAIN = valueByChainId<string>(
{
[ChainId.Mainnet]: '0xba12222222228d8ba445958a75a0704d566bf2c8',
[ChainId.Polygon]: '0xba12222222228d8ba445958a75a0704d566bf2c8',
},
NULL_ADDRESS,
);
@@ -1259,7 +1413,13 @@ export const LIDO_INFO_BY_CHAIN = valueByChainId<LidoInfo>(
export const BALANCER_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer';
export const BALANCER_TOP_POOLS_FETCHED = 250;
export const BALANCER_MAX_POOLS_FETCHED = 3;
export const BALANCER_V2_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2';
export const BALANCER_V2_SUBGRAPH_URL_BY_CHAIN = valueByChainId<string>(
{
[ChainId.Polygon]: 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-polygon-v2',
},
'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2',
);
export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId(
{
@@ -1302,6 +1462,7 @@ export const BAKERYSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
export const APESWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0xc0788a3ad43d79aa53b09c2eacc313a787d1d607',
[ChainId.Polygon]: '0xc0788a3ad43d79aa53b09c2eacc313a787d1d607',
},
NULL_ADDRESS,
);
@@ -1351,7 +1512,7 @@ export const DFYN_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
NULL_ADDRESS,
);
export const WAULT_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
export const WAULTSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0xd48745e39bbed146eec15b79cbf964884f9877c2',
[ChainId.Polygon]: '0x3a1d87f206d12415f5b0a33e786967680aab4f6d',
@@ -1366,6 +1527,14 @@ export const POLYDEX_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
NULL_ADDRESS,
);
export const JETSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0xbe65b8f75b9f20f4c522e0067a3887fada714800',
[ChainId.Polygon]: '0x5c6ec38fb0e2609672bdf628b1fd605a523e5923',
},
NULL_ADDRESS,
);
const uniswapV2CloneGasSchedule = (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
let gas = 90e3;
@@ -1408,12 +1577,15 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.Ellipsis]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.Smoothy]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.Saddle]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.IronSwap]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.XSigma]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.FirebirdOneSwap]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.MultiBridge]: () => 350e3,
[ERC20BridgeSource.UniswapV2]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.SushiSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.CryptoCom]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.Linkswap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.ShibaSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.Balancer]: () => 120e3,
[ERC20BridgeSource.BalancerV2]: () => 100e3,
[ERC20BridgeSource.Cream]: () => 120e3,
@@ -1480,6 +1652,7 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.CheeseSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.JulSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.WaultSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.ACryptos]: fillData => (fillData as CurveFillData).pool.gasSchedule,
//
// Polygon
@@ -1488,6 +1661,7 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.ComethSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.Dfyn]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.Polydex]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.JetSwap]: uniswapV2CloneGasSchedule,
};
export const DEFAULT_FEE_SCHEDULE: Required<FeeSchedule> = { ...DEFAULT_GAS_SCHEDULE };

View File

@@ -523,7 +523,7 @@ export class MarketOperationUtils {
const sturdyFills = fills.filter(p => p.length > 0 && !fragileSources.includes(p[0].source));
const sturdyOptimalPath = await findOptimalPathAsync(side, sturdyFills, inputAmount, opts.runLimit, {
...penaltyOpts,
exchangeProxyOverhead: (sourceFlags: number) =>
exchangeProxyOverhead: (sourceFlags: bigint) =>
// tslint:disable-next-line: no-bitwise
penaltyOpts.exchangeProxyOverhead(sourceFlags | optimalPath.sourceFlags),
});

View File

@@ -168,8 +168,18 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'WaultSwap');
case ERC20BridgeSource.Polydex:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'Polydex');
case ERC20BridgeSource.FirebirdOneSwap:
return encodeBridgeSourceId(BridgeProtocol.Nerve, 'FirebirdOneSwap');
case ERC20BridgeSource.Lido:
return encodeBridgeSourceId(BridgeProtocol.Lido, 'Lido');
case ERC20BridgeSource.ShibaSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'ShibaSwap');
case ERC20BridgeSource.JetSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'JetSwap');
case ERC20BridgeSource.IronSwap:
return encodeBridgeSourceId(BridgeProtocol.Nerve, 'IronSwap');
case ERC20BridgeSource.ACryptos:
return encodeBridgeSourceId(BridgeProtocol.Curve, 'ACryptoS');
default:
throw new Error(AggregationError.NoBridgeForSource);
}
@@ -201,6 +211,9 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
case ERC20BridgeSource.Smoothy:
case ERC20BridgeSource.Saddle:
case ERC20BridgeSource.XSigma:
case ERC20BridgeSource.FirebirdOneSwap:
case ERC20BridgeSource.IronSwap:
case ERC20BridgeSource.ACryptos:
const curveFillData = (order as OptimizedMarketBridgeOrder<CurveFillData>).fillData;
bridgeData = encoder.encode([
curveFillData.pool.poolAddress,
@@ -239,6 +252,8 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
case ERC20BridgeSource.Dfyn:
case ERC20BridgeSource.WaultSwap:
case ERC20BridgeSource.Polydex:
case ERC20BridgeSource.ShibaSwap:
case ERC20BridgeSource.JetSwap:
const uniswapV2FillData = (order as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]);
break;
@@ -417,12 +432,16 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.Smoothy]: curveEncoder,
[ERC20BridgeSource.Saddle]: curveEncoder,
[ERC20BridgeSource.XSigma]: curveEncoder,
[ERC20BridgeSource.FirebirdOneSwap]: curveEncoder,
[ERC20BridgeSource.IronSwap]: curveEncoder,
[ERC20BridgeSource.ACryptos]: curveEncoder,
// UniswapV2 like, (router, address[])
[ERC20BridgeSource.Bancor]: routerAddressPathEncoder,
[ERC20BridgeSource.UniswapV2]: routerAddressPathEncoder,
[ERC20BridgeSource.SushiSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder,
[ERC20BridgeSource.Linkswap]: routerAddressPathEncoder,
[ERC20BridgeSource.ShibaSwap]: routerAddressPathEncoder,
// BSC
[ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder,
@@ -437,6 +456,7 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.ComethSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.Dfyn]: routerAddressPathEncoder,
[ERC20BridgeSource.Polydex]: routerAddressPathEncoder,
[ERC20BridgeSource.JetSwap]: routerAddressPathEncoder,
// Generic pools
[ERC20BridgeSource.Shell]: poolEncoder,
[ERC20BridgeSource.Component]: poolEncoder,

View File

@@ -36,7 +36,7 @@ export const DEFAULT_PATH_PENALTY_OPTS: PathPenaltyOpts = {
export class Path {
public collapsedFills?: ReadonlyArray<CollapsedFill>;
public orders?: OptimizedMarketOrder[];
public sourceFlags: number = 0;
public sourceFlags: bigint = BigInt(0);
protected _size: PathSize = { input: ZERO_AMOUNT, output: ZERO_AMOUNT };
protected _adjustedSize: PathSize = { input: ZERO_AMOUNT, output: ZERO_AMOUNT };
@@ -78,6 +78,11 @@ export class Path {
return this;
}
/**
* Add a fallback path to the current path
* Fallback must contain exclusive fills that are
* not present in this path
*/
public addFallback(fallback: Path): this {
// If the last fill is Native and penultimate is not, then the intention was to partial fill
// In this case we drop it entirely as we can't handle a failure at the end and we don't
@@ -93,9 +98,18 @@ export class Path {
// an additional protocol fee. I.e [Uniswap,Native,Kyber] becomes [Native,Uniswap,Kyber]
// In the previous step we dropped any hanging Native partial fills, as to not fully fill
const nativeFills = this.fills.filter(f => f.source === ERC20BridgeSource.Native);
this.fills = [...nativeFills.filter(f => f !== lastNativeFillIfExists), ...fallback.fills];
const otherFills = this.fills.filter(f => f.source !== ERC20BridgeSource.Native);
const otherSourcePathIds = otherFills.map(f => f.sourcePathId);
this.fills = [
// Append all of the native fills first
...nativeFills.filter(f => f !== lastNativeFillIfExists),
// Add the other fills that are not native in the optimal path
...otherFills,
// Add the fallbacks to the end that aren't already included
...fallback.fills.filter(f => !otherSourcePathIds.includes(f.sourcePathId)),
];
// Recompute the source flags
this.sourceFlags = this.fills.reduce((flags, fill) => flags | fill.flags, 0);
this.sourceFlags = this.fills.reduce((flags, fill) => flags | fill.flags, BigInt(0));
return this;
}

View File

@@ -1,3 +1,4 @@
import { ChainId } from '@0x/contract-addresses';
import { BigNumber } from '@0x/utils';
// import { parsePoolData } from '@balancer-labs'; // TODO - upgrade to v2
import { Pool } from '@balancer-labs/sor/dist/types';
@@ -5,7 +6,11 @@ import { gql, request } from 'graphql-request';
import { DEFAULT_WARNING_LOGGER } from '../../../constants';
import { LogFunction } from '../../../types';
import { BALANCER_MAX_POOLS_FETCHED, BALANCER_TOP_POOLS_FETCHED, BALANCER_V2_SUBGRAPH_URL } from '../constants';
import {
BALANCER_MAX_POOLS_FETCHED,
BALANCER_TOP_POOLS_FETCHED,
BALANCER_V2_SUBGRAPH_URL_BY_CHAIN,
} from '../constants';
import { parsePoolData } from './balancer_sor_v2';
import { CacheValue, PoolsCache } from './pools_cache';
@@ -45,7 +50,8 @@ export class BalancerV2PoolsCache extends PoolsCache {
}
constructor(
private readonly subgraphUrl: string = BALANCER_V2_SUBGRAPH_URL,
chainId: ChainId,
private readonly subgraphUrl: string = BALANCER_V2_SUBGRAPH_URL_BY_CHAIN[chainId],
private readonly maxPoolsFetched: number = BALANCER_MAX_POOLS_FETCHED,
private readonly _topPoolsFetched: number = BALANCER_TOP_POOLS_FETCHED,
private readonly _warningLogger: LogFunction = DEFAULT_WARNING_LOGGER,

View File

@@ -122,7 +122,7 @@ export class SamplerOperations {
this.poolsCaches = poolsCaches
? poolsCaches
: {
[ERC20BridgeSource.BalancerV2]: new BalancerV2PoolsCache(),
[ERC20BridgeSource.BalancerV2]: new BalancerV2PoolsCache(chainId),
[ERC20BridgeSource.Balancer]: new BalancerPoolsCache(),
[ERC20BridgeSource.Cream]: new CreamPoolsCache(),
};
@@ -1229,6 +1229,8 @@ export class SamplerOperations {
case ERC20BridgeSource.Dfyn:
case ERC20BridgeSource.WaultSwap:
case ERC20BridgeSource.Polydex:
case ERC20BridgeSource.ShibaSwap:
case ERC20BridgeSource.JetSwap:
const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source);
if (!isValidAddress(uniLikeRouter)) {
return [];
@@ -1262,6 +1264,9 @@ export class SamplerOperations {
case ERC20BridgeSource.Ellipsis:
case ERC20BridgeSource.Saddle:
case ERC20BridgeSource.XSigma:
case ERC20BridgeSource.FirebirdOneSwap:
case ERC20BridgeSource.IronSwap:
case ERC20BridgeSource.ACryptos:
return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getCurveSellQuotes(
pool,
@@ -1498,6 +1503,8 @@ export class SamplerOperations {
case ERC20BridgeSource.Dfyn:
case ERC20BridgeSource.WaultSwap:
case ERC20BridgeSource.Polydex:
case ERC20BridgeSource.ShibaSwap:
case ERC20BridgeSource.JetSwap:
const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source);
if (!isValidAddress(uniLikeRouter)) {
return [];
@@ -1531,6 +1538,9 @@ export class SamplerOperations {
case ERC20BridgeSource.Ellipsis:
case ERC20BridgeSource.Saddle:
case ERC20BridgeSource.XSigma:
case ERC20BridgeSource.FirebirdOneSwap:
case ERC20BridgeSource.IronSwap:
case ERC20BridgeSource.ACryptos:
return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
this.getCurveBuyQuotes(
pool,

View File

@@ -68,6 +68,7 @@ export enum ERC20BridgeSource {
UniswapV3 = 'Uniswap_V3',
CurveV2 = 'Curve_V2',
Lido = 'Lido',
ShibaSwap = 'ShibaSwap',
// BSC only
PancakeSwap = 'PancakeSwap',
PancakeSwapV2 = 'PancakeSwap_V2',
@@ -79,12 +80,16 @@ export enum ERC20BridgeSource {
CafeSwap = 'CafeSwap',
CheeseSwap = 'CheeseSwap',
JulSwap = 'JulSwap',
ACryptos = 'ACryptoS',
// Polygon only
QuickSwap = 'QuickSwap',
ComethSwap = 'ComethSwap',
Dfyn = 'Dfyn',
WaultSwap = 'WaultSwap',
Polydex = 'Polydex',
FirebirdOneSwap = 'FirebirdOneSwap',
JetSwap = 'JetSwap',
IronSwap = 'IronSwap',
}
export type SourcesWithPoolsCache = ERC20BridgeSource.Balancer | ERC20BridgeSource.BalancerV2 | ERC20BridgeSource.Cream;
@@ -273,7 +278,7 @@ export interface Fill<TFillData extends FillData = FillData> {
// paths that have the same `source` IDs but are distinct (e.g., Curves).
sourcePathId: string;
// See `SOURCE_FLAGS`.
flags: number;
flags: bigint;
// Input fill amount (taker asset amount in a sell, maker asset amount in a buy).
input: BigNumber;
// Output fill amount (maker asset amount in a sell, taker asset amount in a buy).
@@ -362,7 +367,7 @@ export interface GetMarketOrdersRfqOpts extends RfqRequestOpts {
export type FeeEstimate = (fillData: FillData) => number | BigNumber;
export type FeeSchedule = Partial<{ [key in ERC20BridgeSource]: FeeEstimate }>;
export type ExchangeProxyOverhead = (sourceFlags: number) => BigNumber;
export type ExchangeProxyOverhead = (sourceFlags: bigint) => BigNumber;
/**
* Options for `getMarketSellOrdersAsync()` and `getMarketBuyOrdersAsync()`.
@@ -464,7 +469,7 @@ export interface SourceQuoteOperation<TFillData extends FillData = FillData> ext
export interface OptimizerResult {
optimizedOrders: OptimizedMarketOrder[];
sourceFlags: number;
sourceFlags: bigint;
liquidityDelivered: CollapsedFill[] | DexSample<MultiHopFillData>;
marketSideLiquidity: MarketSideLiquidity;
adjustedRate: BigNumber;

View File

@@ -29,6 +29,7 @@ import { RfqMakerBlacklist } from './rfq_maker_blacklist';
const MAKER_TIMEOUT_STREAK_LENGTH = 10;
const MAKER_TIMEOUT_BLACKLIST_DURATION_MINUTES = 10;
const FILL_RATIO_WARNING_LEVEL = 0.99;
const rfqMakerBlacklist = new RfqMakerBlacklist(MAKER_TIMEOUT_STREAK_LENGTH, MAKER_TIMEOUT_BLACKLIST_DURATION_MINUTES);
interface RfqQuote<T> {
@@ -563,6 +564,22 @@ export class QuoteRequestor {
this._warningLogger(order, 'Expiry too soon in RFQ-T firm quote, filtering out');
return false;
} else {
const takerAmount = new BigNumber(order.takerAmount);
const fillRatio = takerAmount.div(assetFillAmount);
if (fillRatio.lt(1) && fillRatio.gte(FILL_RATIO_WARNING_LEVEL)) {
this._warningLogger(
{
makerUri: result.makerUri,
fillRatio,
assetFillAmount,
takerToken,
makerToken,
takerAmount: order.takerAmount,
makerAmount: order.makerAmount,
},
'Fill ratio in warning range',
);
}
return true;
}
});

View File

@@ -39,7 +39,7 @@ const feeSchedule = {
[ERC20BridgeSource.Native]: _.constant(GAS_PRICE.times(NATIVE_ORDER_FEE)),
};
const exchangeProxyOverhead = (sourceFlags: number) => {
const exchangeProxyOverhead = (sourceFlags: bigint) => {
if ([SOURCE_FLAGS.RfqOrder].includes(sourceFlags)) {
return new BigNumber(20e3).times(GAS_PRICE);
} else {

View File

@@ -1280,7 +1280,7 @@ describe('MarketOperationUtils tests', () => {
});
const optimizer = new MarketOperationUtils(MOCK_SAMPLER, contractAddresses, ORDER_DOMAIN);
const gasPrice = 100e9; // 100 gwei
const exchangeProxyOverhead = (sourceFlags: number) =>
const exchangeProxyOverhead = (sourceFlags: bigint) =>
sourceFlags === SOURCE_FLAGS.LiquidityProvider
? constants.ZERO_AMOUNT
: new BigNumber(1.3e5).times(gasPrice);
@@ -1663,7 +1663,7 @@ describe('MarketOperationUtils tests', () => {
});
const optimizer = new MarketOperationUtils(MOCK_SAMPLER, contractAddresses, ORDER_DOMAIN);
const gasPrice = 100e9; // 100 gwei
const exchangeProxyOverhead = (sourceFlags: number) =>
const exchangeProxyOverhead = (sourceFlags: bigint) =>
sourceFlags === SOURCE_FLAGS.LiquidityProvider
? constants.ZERO_AMOUNT
: new BigNumber(1.3e5).times(gasPrice);

View File

@@ -0,0 +1,86 @@
import { expect } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { MarketOperation } from '../src/types';
import { Path } from '../src/utils/market_operation_utils/path';
import { ERC20BridgeSource, Fill } from '../src/utils/market_operation_utils/types';
const createFill = (
source: ERC20BridgeSource,
input: BigNumber = new BigNumber(100),
output: BigNumber = new BigNumber(100),
): Fill =>
// tslint:disable-next-line: no-object-literal-type-assertion
({
source,
input,
output,
adjustedOutput: output,
flags: BigInt(0),
sourcePathId: source,
} as Fill);
describe('Path', () => {
it('Adds a fallback', () => {
const targetInput = new BigNumber(100);
const path = Path.create(
MarketOperation.Sell,
[createFill(ERC20BridgeSource.Native), createFill(ERC20BridgeSource.Native)],
targetInput,
);
const fallback = Path.create(MarketOperation.Sell, [createFill(ERC20BridgeSource.Uniswap)], targetInput);
path.addFallback(fallback);
const sources = path.fills.map(f => f.source);
expect(sources).to.deep.eq([ERC20BridgeSource.Native, ERC20BridgeSource.Native, ERC20BridgeSource.Uniswap]);
});
it('Adds a fallback with LiquidityProvider', () => {
const targetInput = new BigNumber(100);
const path = Path.create(
MarketOperation.Sell,
[createFill(ERC20BridgeSource.Native), createFill(ERC20BridgeSource.LiquidityProvider)],
targetInput,
);
const fallback = Path.create(MarketOperation.Sell, [createFill(ERC20BridgeSource.Uniswap)], targetInput);
path.addFallback(fallback);
const sources = path.fills.map(f => f.source);
expect(sources).to.deep.eq([
ERC20BridgeSource.Native,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.Uniswap,
]);
});
it('Removes partial Native orders', () => {
const targetInput = new BigNumber(100);
const path = Path.create(
MarketOperation.Sell,
[
createFill(ERC20BridgeSource.Uniswap),
createFill(ERC20BridgeSource.LiquidityProvider),
createFill(ERC20BridgeSource.Native),
],
targetInput,
);
const fallback = Path.create(MarketOperation.Sell, [createFill(ERC20BridgeSource.Kyber)], targetInput);
path.addFallback(fallback);
const sources = path.fills.map(f => f.source);
expect(sources).to.deep.eq([
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.Kyber,
]);
});
it('Handles duplicates', () => {
const targetInput = new BigNumber(100);
const path = Path.create(
MarketOperation.Sell,
[createFill(ERC20BridgeSource.Uniswap), createFill(ERC20BridgeSource.LiquidityProvider)],
targetInput,
);
const fallback = Path.create(MarketOperation.Sell, [createFill(ERC20BridgeSource.Uniswap)], targetInput);
path.addFallback(fallback);
const sources = path.fills.map(f => f.source);
expect(sources).to.deep.eq([ERC20BridgeSource.Uniswap, ERC20BridgeSource.LiquidityProvider]);
});
});

View File

@@ -1,3 +1,4 @@
import { ChainId } from '@0x/contract-addresses';
import * as chai from 'chai';
import 'mocha';
@@ -49,7 +50,7 @@ describe('Pools Caches for Balancer-based sampling', () => {
});
describe('BalancerV2PoolsCache', () => {
const cache = new BalancerV2PoolsCache();
const cache = new BalancerV2PoolsCache(ChainId.Mainnet);
it('fetches pools', async () => {
const pairs = [
[wethAddress, wbtcAddress],