Compare commits
	
		
			6 Commits
		
	
	
		
			@0x/contra
			...
			feat/Redac
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 9b9c47ef56 | ||
|  | dfcde47ab3 | ||
|  | 424066c1a2 | ||
|  | d8a489843e | ||
|  | 914449025c | ||
|  | 49f129aa30 | 
| @@ -4,7 +4,7 @@ jobs: | ||||
|     build: | ||||
|         resource_class: xlarge | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         environment: | ||||
|             NODE_OPTIONS: '--max-old-space-size=16384' | ||||
|         working_directory: ~/repo | ||||
| @@ -19,6 +19,7 @@ jobs: | ||||
|                   command: yarn --frozen-lockfile --ignore-engines install || yarn --frozen-lockfile --ignore-engines install | ||||
|             - setup_remote_docker | ||||
|             - run: yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci | ||||
|             - run: yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts | ||||
|             - save_cache: | ||||
|                   key: repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|                   paths: | ||||
| @@ -30,7 +31,7 @@ jobs: | ||||
|     test-exchange-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
| @@ -40,7 +41,7 @@ jobs: | ||||
|     test-integrations-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
| @@ -50,7 +51,7 @@ jobs: | ||||
|     test-contracts-staking-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
| @@ -60,7 +61,7 @@ jobs: | ||||
|     test-contracts-extra-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
| @@ -70,7 +71,7 @@ jobs: | ||||
|     test-contracts-rest-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
| @@ -82,7 +83,7 @@ jobs: | ||||
|         environment: | ||||
|             NODE_OPTIONS: '--max-old-space-size=6442' | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|             - image: 0xorg/verdaccio | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
| @@ -96,7 +97,7 @@ jobs: | ||||
|                   path: ~/.npm/_logs | ||||
|     test-doc-generation: | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
| @@ -107,10 +108,8 @@ jobs: | ||||
|                   no_output_timeout: 1200 | ||||
|     test-rest: | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         environment: | ||||
|             RUST_ROUTER: 'true' | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
| @@ -118,6 +117,7 @@ jobs: | ||||
|             - run: yarn wsrun -p @0x/contracts-test-utils -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/contract-artifacts -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/contract-wrappers-test -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/migrations -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/order-utils -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/asset-swapper -m --serial -c test:circleci | ||||
|             - save_cache: | ||||
| @@ -136,7 +136,7 @@ jobs: | ||||
|         resource_class: large | ||||
|         working_directory: ~/repo | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
| @@ -147,7 +147,7 @@ jobs: | ||||
|             - run: yarn diff_md_docs:ci | ||||
|     submit-coverage: | ||||
|         docker: | ||||
|             - image: node:16 | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|   | ||||
							
								
								
									
										1
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| python: ['python-packages'] | ||||
| contracts: ['contracts'] | ||||
| @0x/contract-addresses: ['packages/contract-addresses'] | ||||
| @0x/migrations: ['packages/migrations'] | ||||
| @0x/order-utils: ['packages/order-utils'] | ||||
| @0x/contract-artifacts: ['packages/contract-artifacts'] | ||||
| @0x/contract-wrappers: ['packages/contract-wrappers'] | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
								
							| @@ -28,7 +28,7 @@ jobs: | ||||
|                 fetch-depth: 0 | ||||
|             - uses: actions/setup-node@v1 | ||||
|               with: | ||||
|                 node-version: 16 | ||||
|                 node-version: 10 | ||||
|             - uses: actions/setup-python@v2 | ||||
|             - name: 'configure git' | ||||
|               run: | | ||||
|   | ||||
| @@ -38,6 +38,7 @@ These packages are all under development. See [/contracts/README.md](/contracts/ | ||||
| | [`@0x/protocol-utils`](/packages/protocol-utils)         | [](https://www.npmjs.com/package/@0x/protocol-utils)         | A set of utilities for generating, parsing, signing and validating 0x orders                   | | ||||
| | [`@0x/contract-addresses`](/packages/contract-addresses) | [](https://www.npmjs.com/package/@0x/contract-addresses) | A tiny utility library for getting known deployed contract addresses for a particular network. | | ||||
| | [`@0x/contract-wrappers`](/packages/contract-wrappers)   | [](https://www.npmjs.com/package/@0x/contract-wrappers)   | JS/TS wrappers for interacting with the 0x smart contracts                                     | | ||||
| | [`@0x/migrations`](/packages/migrations)                 | [](https://www.npmjs.com/package/@0x/migrations)                 | Migration tool for deploying 0x smart contracts on private testnets                            | | ||||
| | [`@0x/contract-artifacts`](/packages/contract-artifacts) | [](https://www.npmjs.com/package/@0x/contract-artifacts) | 0x smart contract compilation artifacts                                                        |  | | ||||
|  | ||||
| ## Usage | ||||
|   | ||||
| @@ -1,58 +1,4 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1655244958, | ||||
|         "version": "3.3.32", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1654284040, | ||||
|         "version": "3.3.31", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1652919697, | ||||
|         "version": "3.3.30", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1650611093, | ||||
|         "version": "3.3.29", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1648739346, | ||||
|         "version": "3.3.28", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1646225739, | ||||
|         "version": "3.3.27", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1645569128, | ||||
|         "version": "3.3.26", | ||||
|   | ||||
| @@ -5,30 +5,6 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v3.3.32 - _June 14, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.3.31 - _June 3, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.3.30 - _May 19, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.3.29 - _April 22, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.3.28 - _March 31, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.3.27 - _March 2, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.3.26 - _February 22, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-erc20", | ||||
|     "version": "3.3.32", | ||||
|     "version": "3.3.26", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -51,18 +51,18 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.8.0", | ||||
|         "@0x/contracts-gen": "^2.0.46", | ||||
|         "@0x/contracts-test-utils": "^5.4.23", | ||||
|         "@0x/contracts-utils": "^4.8.13", | ||||
|         "@0x/dev-utils": "^4.2.14", | ||||
|         "@0x/sol-compiler": "^4.8.1", | ||||
|         "@0x/abi-gen": "^5.7.2", | ||||
|         "@0x/contracts-gen": "^2.0.43", | ||||
|         "@0x/contracts-test-utils": "^5.4.17", | ||||
|         "@0x/contracts-utils": "^4.8.7", | ||||
|         "@0x/dev-utils": "^4.2.11", | ||||
|         "@0x/sol-compiler": "^4.7.8", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.4", | ||||
|         "@0x/types": "^3.3.6", | ||||
|         "@0x/typescript-typings": "^5.3.1", | ||||
|         "@0x/utils": "^6.5.3", | ||||
|         "@0x/web3-wrapper": "^7.6.5", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|         "@0x/utils": "^6.5.0", | ||||
|         "@0x/web3-wrapper": "^7.6.2", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "@types/mocha": "^5.2.7", | ||||
|         "@types/node": "12.12.54", | ||||
| @@ -70,7 +70,7 @@ | ||||
|         "chai-as-promised": "^7.1.0", | ||||
|         "chai-bignumber": "^3.0.0", | ||||
|         "dirty-chai": "^2.0.1", | ||||
|         "ethereum-types": "^3.7.0", | ||||
|         "ethereum-types": "^3.6.0", | ||||
|         "lodash": "^4.17.11", | ||||
|         "make-promises-safe": "^1.1.0", | ||||
|         "mocha": "^6.2.0", | ||||
| @@ -79,10 +79,10 @@ | ||||
|         "solhint": "^1.4.1", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.6.3" | ||||
|         "typescript": "4.2.2" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.5.0", | ||||
|         "@0x/base-contract": "^6.4.5", | ||||
|         "ethers": "~4.0.4" | ||||
|     }, | ||||
|     "publishConfig": { | ||||
|   | ||||
| @@ -1,58 +1,4 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1655244958, | ||||
|         "version": "5.4.23", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1654284040, | ||||
|         "version": "5.4.22", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1652919697, | ||||
|         "version": "5.4.21", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1650611093, | ||||
|         "version": "5.4.20", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1648739346, | ||||
|         "version": "5.4.19", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1646225739, | ||||
|         "version": "5.4.18", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1645569128, | ||||
|         "version": "5.4.17", | ||||
|   | ||||
| @@ -5,30 +5,6 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v5.4.23 - _June 14, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v5.4.22 - _June 3, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v5.4.21 - _May 19, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v5.4.20 - _April 22, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v5.4.19 - _March 31, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v5.4.18 - _March 2, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v5.4.17 - _February 22, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-test-utils", | ||||
|     "version": "5.4.23", | ||||
|     "version": "5.4.17", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -34,28 +34,28 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/test-utils", | ||||
|     "devDependencies": { | ||||
|         "@0x/sol-compiler": "^4.8.1", | ||||
|         "@0x/sol-compiler": "^4.7.8", | ||||
|         "@0x/tslint-config": "^4.1.4", | ||||
|         "npm-run-all": "^4.1.2", | ||||
|         "shx": "^0.2.2", | ||||
|         "tslint": "5.11.0", | ||||
|         "typescript": "4.6.3" | ||||
|         "typescript": "4.2.2" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/assert": "^3.0.34", | ||||
|         "@0x/base-contract": "^6.5.0", | ||||
|         "@0x/contract-addresses": "^6.16.0", | ||||
|         "@0x/dev-utils": "^4.2.14", | ||||
|         "@0x/json-schemas": "^6.4.4", | ||||
|         "@0x/assert": "^3.0.31", | ||||
|         "@0x/base-contract": "^6.4.5", | ||||
|         "@0x/contract-addresses": "^6.11.0", | ||||
|         "@0x/dev-utils": "^4.2.11", | ||||
|         "@0x/json-schemas": "^6.4.1", | ||||
|         "@0x/order-utils": "^10.4.28", | ||||
|         "@0x/sol-coverage": "^4.0.45", | ||||
|         "@0x/sol-profiler": "^4.1.35", | ||||
|         "@0x/sol-trace": "^3.0.45", | ||||
|         "@0x/subproviders": "^6.6.5", | ||||
|         "@0x/types": "^3.3.6", | ||||
|         "@0x/typescript-typings": "^5.3.1", | ||||
|         "@0x/utils": "^6.5.3", | ||||
|         "@0x/web3-wrapper": "^7.6.5", | ||||
|         "@0x/sol-coverage": "^4.0.42", | ||||
|         "@0x/sol-profiler": "^4.1.32", | ||||
|         "@0x/sol-trace": "^3.0.42", | ||||
|         "@0x/subproviders": "^6.6.2", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|         "@0x/utils": "^6.5.0", | ||||
|         "@0x/web3-wrapper": "^7.6.2", | ||||
|         "@types/bn.js": "^4.11.0", | ||||
|         "@types/js-combinatorics": "^0.5.29", | ||||
|         "@types/lodash": "4.14.104", | ||||
| @@ -67,7 +67,7 @@ | ||||
|         "chai-bignumber": "^3.0.0", | ||||
|         "decimal.js": "^10.2.0", | ||||
|         "dirty-chai": "^2.0.1", | ||||
|         "ethereum-types": "^3.7.0", | ||||
|         "ethereum-types": "^3.6.0", | ||||
|         "ethereumjs-util": "^7.0.10", | ||||
|         "ethers": "~4.0.4", | ||||
|         "js-combinatorics": "^0.5.3", | ||||
|   | ||||
| @@ -1,58 +1,4 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1655244958, | ||||
|         "version": "1.4.15", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1654284040, | ||||
|         "version": "1.4.14", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1652919697, | ||||
|         "version": "1.4.13", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1650611093, | ||||
|         "version": "1.4.12", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1648739346, | ||||
|         "version": "1.4.11", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1646225739, | ||||
|         "version": "1.4.10", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1645569128, | ||||
|         "version": "1.4.9", | ||||
|   | ||||
| @@ -5,30 +5,6 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.4.15 - _June 14, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.4.14 - _June 3, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.4.13 - _May 19, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.4.12 - _April 22, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.4.11 - _March 31, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.4.10 - _March 2, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.4.9 - _February 22, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-treasury", | ||||
|     "version": "1.4.15", | ||||
|     "version": "1.4.9", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -46,14 +46,14 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.8.0", | ||||
|         "@0x/contract-addresses": "^6.16.0", | ||||
|         "@0x/abi-gen": "^5.7.2", | ||||
|         "@0x/contract-addresses": "^6.11.0", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.19", | ||||
|         "@0x/contracts-erc20": "^3.3.32", | ||||
|         "@0x/contracts-gen": "^2.0.46", | ||||
|         "@0x/contracts-erc20": "^3.3.26", | ||||
|         "@0x/contracts-gen": "^2.0.43", | ||||
|         "@0x/contracts-staking": "^2.0.45", | ||||
|         "@0x/contracts-test-utils": "^5.4.23", | ||||
|         "@0x/sol-compiler": "^4.8.1", | ||||
|         "@0x/contracts-test-utils": "^5.4.17", | ||||
|         "@0x/sol-compiler": "^4.7.8", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.4", | ||||
|         "@types/isomorphic-fetch": "^0.0.35", | ||||
| @@ -69,17 +69,17 @@ | ||||
|         "solhint": "^1.4.1", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.6.3" | ||||
|         "typescript": "4.2.2" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.5.0", | ||||
|         "@0x/protocol-utils": "^11.15.0", | ||||
|         "@0x/subproviders": "^6.6.5", | ||||
|         "@0x/types": "^3.3.6", | ||||
|         "@0x/typescript-typings": "^5.3.1", | ||||
|         "@0x/utils": "^6.5.3", | ||||
|         "@0x/web3-wrapper": "^7.6.5", | ||||
|         "ethereum-types": "^3.7.0", | ||||
|         "@0x/base-contract": "^6.4.5", | ||||
|         "@0x/protocol-utils": "^1.11.0", | ||||
|         "@0x/subproviders": "^6.6.2", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|         "@0x/utils": "^6.5.0", | ||||
|         "@0x/web3-wrapper": "^7.6.2", | ||||
|         "ethereum-types": "^3.6.0", | ||||
|         "ethereumjs-util": "^7.0.10" | ||||
|     }, | ||||
|     "publishConfig": { | ||||
|   | ||||
| @@ -1,58 +1,4 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1655244958, | ||||
|         "version": "4.8.13", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1654284040, | ||||
|         "version": "4.8.12", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1652919697, | ||||
|         "version": "4.8.11", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1650611093, | ||||
|         "version": "4.8.10", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1648739346, | ||||
|         "version": "4.8.9", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1646225739, | ||||
|         "version": "4.8.8", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1645569128, | ||||
|         "version": "4.8.7", | ||||
|   | ||||
| @@ -5,30 +5,6 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v4.8.13 - _June 14, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.8.12 - _June 3, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.8.11 - _May 19, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.8.10 - _April 22, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.8.9 - _March 31, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.8.8 - _March 2, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.8.7 - _February 22, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-utils", | ||||
|     "version": "4.8.13", | ||||
|     "version": "4.8.7", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -50,15 +50,15 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/utils", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.8.0", | ||||
|         "@0x/contracts-gen": "^2.0.46", | ||||
|         "@0x/contracts-test-utils": "^5.4.23", | ||||
|         "@0x/dev-utils": "^4.2.14", | ||||
|         "@0x/abi-gen": "^5.7.2", | ||||
|         "@0x/contracts-gen": "^2.0.43", | ||||
|         "@0x/contracts-test-utils": "^5.4.17", | ||||
|         "@0x/dev-utils": "^4.2.11", | ||||
|         "@0x/order-utils": "^10.4.28", | ||||
|         "@0x/sol-compiler": "^4.8.1", | ||||
|         "@0x/sol-compiler": "^4.7.8", | ||||
|         "@0x/tslint-config": "^4.1.4", | ||||
|         "@0x/types": "^3.3.6", | ||||
|         "@0x/web3-wrapper": "^7.6.5", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/web3-wrapper": "^7.6.2", | ||||
|         "@types/bn.js": "^4.11.0", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "@types/mocha": "^5.2.7", | ||||
| @@ -76,14 +76,14 @@ | ||||
|         "solhint": "^1.4.1", | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typescript": "4.6.3" | ||||
|         "typescript": "4.2.2" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.5.0", | ||||
|         "@0x/typescript-typings": "^5.3.1", | ||||
|         "@0x/utils": "^6.5.3", | ||||
|         "@0x/base-contract": "^6.4.5", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|         "@0x/utils": "^6.5.0", | ||||
|         "bn.js": "^4.11.8", | ||||
|         "ethereum-types": "^3.7.0" | ||||
|         "ethereum-types": "^3.6.0" | ||||
|     }, | ||||
|     "publishConfig": { | ||||
|         "access": "public" | ||||
|   | ||||
| @@ -1,70 +1,4 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "0.35.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Adds support for Velodrome OptimismBridgeAdapter", | ||||
|                 "pr": 494 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1655244958 | ||||
|     }, | ||||
|     { | ||||
|         "version": "0.34.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Splits BridgeAdapter up by chain", | ||||
|                 "pr": 487 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add stETH wrap/unwrap support", | ||||
|                 "pr": 476 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Adds support for BancorV3 to EthereumBridgeAdapter", | ||||
|                 "pr": 492 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1654284040 | ||||
|     }, | ||||
|     { | ||||
|         "version": "0.33.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add support for GMX and Platypus to bridge adapter", | ||||
|                 "pr": 478 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1652919697 | ||||
|     }, | ||||
|     { | ||||
|         "version": "0.32.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add support for `BalancerV2Batch` fills in FQT", | ||||
|                 "pr": 462 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1650611093 | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1648739346, | ||||
|         "version": "0.31.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1646225739, | ||||
|         "version": "0.31.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "0.31.0", | ||||
|         "changes": [ | ||||
|   | ||||
| @@ -5,32 +5,6 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v0.35.0 - _June 14, 2022_ | ||||
|  | ||||
|     * Adds support for Velodrome OptimismBridgeAdapter (#494) | ||||
|  | ||||
| ## v0.34.0 - _June 3, 2022_ | ||||
|  | ||||
|     * Splits BridgeAdapter up by chain (#487) | ||||
|     * Add stETH wrap/unwrap support (#476) | ||||
|     * Adds support for BancorV3 to EthereumBridgeAdapter (#492) | ||||
|  | ||||
| ## v0.33.0 - _May 19, 2022_ | ||||
|  | ||||
|     * Add support for GMX and Platypus to bridge adapter (#478) | ||||
|  | ||||
| ## v0.32.0 - _April 22, 2022_ | ||||
|  | ||||
|     * Add support for `BalancerV2Batch` fills in FQT (#462) | ||||
|  | ||||
| ## v0.31.2 - _March 31, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v0.31.1 - _March 2, 2022_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v0.31.0 - _February 22, 2022_ | ||||
|  | ||||
|     * Add ERC721OrdersFeature, ERC1155OrdersFeature, and ERC165Feature (#429) | ||||
|   | ||||
| @@ -1,88 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./IBridgeAdapter.sol"; | ||||
|  | ||||
| abstract contract AbstractBridgeAdapter is IBridgeAdapter { | ||||
|  | ||||
|     constructor( | ||||
|         uint256 expectedChainId,  | ||||
|         string memory expectedChainName | ||||
|     ) | ||||
|         public | ||||
|     { | ||||
|         uint256 chainId; | ||||
|         assembly { chainId := chainid() } | ||||
|         // Allow testing on Ganache | ||||
|         if (chainId != expectedChainId && chainId != 1337) { | ||||
|             revert(string(abi.encodePacked(expectedChainName, "BridgeAdapter.constructor: wrong chain ID"))); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function isSupportedSource(bytes32 source) | ||||
|         external | ||||
|         override | ||||
|         returns (bool isSupported) | ||||
|     { | ||||
|         BridgeOrder memory placeholderOrder; | ||||
|         placeholderOrder.source = source; | ||||
|         IERC20TokenV06 placeholderToken = IERC20TokenV06(address(0)); | ||||
|          | ||||
|         (, isSupported) = _trade( | ||||
|             placeholderOrder, | ||||
|             placeholderToken, | ||||
|             placeholderToken, | ||||
|             0, | ||||
|             true | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount | ||||
|     ) | ||||
|         public | ||||
|         override | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         (boughtAmount, ) = _trade( | ||||
|             order, | ||||
|             sellToken, | ||||
|             buyToken, | ||||
|             sellAmount, | ||||
|             false | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function _trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bool dryRun | ||||
|     ) | ||||
|         internal | ||||
|         virtual | ||||
|         returns (uint256 boughtAmount, bool supportedSource); | ||||
| } | ||||
| @@ -1,141 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./AbstractBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./mixins/MixinCurve.sol"; | ||||
| import "./mixins/MixinCurveV2.sol"; | ||||
| import "./mixins/MixinGMX.sol"; | ||||
| import "./mixins/MixinKyberDmm.sol"; | ||||
| import "./mixins/MixinAaveV2.sol"; | ||||
| import "./mixins/MixinNerve.sol"; | ||||
| import "./mixins/MixinPlatypus.sol"; | ||||
| import "./mixins/MixinUniswapV2.sol"; | ||||
| import "./mixins/MixinZeroExBridge.sol"; | ||||
|  | ||||
| contract AvalancheBridgeAdapter is | ||||
|     AbstractBridgeAdapter(43114, "Avalanche"), | ||||
|     MixinCurve, | ||||
|     MixinCurveV2, | ||||
|     MixinGMX, | ||||
|     MixinKyberDmm, | ||||
|     MixinAaveV2, | ||||
|     MixinNerve, | ||||
|     MixinPlatypus, | ||||
|     MixinUniswapV2, | ||||
|     MixinZeroExBridge | ||||
| { | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|         MixinCurve(weth) | ||||
|     {} | ||||
|  | ||||
|     function _trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bool dryRun | ||||
|     ) | ||||
|         internal | ||||
|         override | ||||
|         returns (uint256 boughtAmount, bool supportedSource) | ||||
|     { | ||||
|         uint128 protocolId = uint128(uint256(order.source) >> 128); | ||||
|         if (protocolId == BridgeProtocols.CURVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurve( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.CURVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV2( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.NERVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeNerve( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.KYBERDMM) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeKyberDmm( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.AAVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeAaveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.GMX) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeGMX( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.PLATYPUS) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradePlatypus( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNKNOWN) { | ||||
|             if (dryRun) { return (0, true); }             | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         emit BridgeFill( | ||||
|             order.source, | ||||
|             sellToken, | ||||
|             buyToken, | ||||
|             sellAmount, | ||||
|             boughtAmount | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -1,132 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./AbstractBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./mixins/MixinCurve.sol"; | ||||
| import "./mixins/MixinDodo.sol"; | ||||
| import "./mixins/MixinDodoV2.sol"; | ||||
| import "./mixins/MixinKyberDmm.sol"; | ||||
| import "./mixins/MixinMooniswap.sol"; | ||||
| import "./mixins/MixinNerve.sol"; | ||||
| import "./mixins/MixinUniswapV2.sol"; | ||||
| import "./mixins/MixinZeroExBridge.sol"; | ||||
|  | ||||
| contract BSCBridgeAdapter is | ||||
|     AbstractBridgeAdapter(56, "BSC"), | ||||
|     MixinCurve, | ||||
|     MixinDodo, | ||||
|     MixinDodoV2, | ||||
|     MixinKyberDmm, | ||||
|     MixinMooniswap, | ||||
|     MixinNerve, | ||||
|     MixinUniswapV2, | ||||
|     MixinZeroExBridge | ||||
| { | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|         MixinCurve(weth) | ||||
|         MixinMooniswap(weth) | ||||
|     {} | ||||
|  | ||||
|     function _trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bool dryRun | ||||
|     ) | ||||
|         internal | ||||
|         override | ||||
|         returns (uint256 boughtAmount, bool supportedSource) | ||||
|     { | ||||
|         uint128 protocolId = uint128(uint256(order.source) >> 128); | ||||
|         if (protocolId == BridgeProtocols.CURVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurve( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV2( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.MOONISWAP) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeMooniswap( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.DODO) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeDodo( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.DODOV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeDodoV2( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.NERVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeNerve( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.KYBERDMM) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeKyberDmm( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNKNOWN) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         emit BridgeFill( | ||||
|             order.source, | ||||
|             sellToken, | ||||
|             buyToken, | ||||
|             sellAmount, | ||||
|             boughtAmount | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
| 
 | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|   Copyright 2021 ZeroEx Intl. | ||||
| 
 | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -20,52 +20,54 @@ | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
| 
 | ||||
| import "./AbstractBridgeAdapter.sol"; | ||||
| import "./IBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./mixins/MixinAaveV2.sol"; | ||||
| import "./mixins/MixinBalancer.sol"; | ||||
| import "./mixins/MixinBalancerV2.sol"; | ||||
| import "./mixins/MixinBalancerV2Batch.sol"; | ||||
| import "./mixins/MixinBancor.sol"; | ||||
| import "./mixins/MixinBancorV3.sol"; | ||||
| import "./mixins/MixinCoFiX.sol"; | ||||
| import "./mixins/MixinCompound.sol"; | ||||
| import "./mixins/MixinCurve.sol"; | ||||
| import "./mixins/MixinCurveV2.sol"; | ||||
| import "./mixins/MixinCryptoCom.sol"; | ||||
| import "./mixins/MixinDodo.sol"; | ||||
| import "./mixins/MixinDodoV2.sol"; | ||||
| import "./mixins/MixinKyber.sol"; | ||||
| import "./mixins/MixinKyberDmm.sol"; | ||||
| import "./mixins/MixinLido.sol"; | ||||
| import "./mixins/MixinMakerPSM.sol"; | ||||
| import "./mixins/MixinMooniswap.sol"; | ||||
| import "./mixins/MixinMStable.sol"; | ||||
| import "./mixins/MixinNerve.sol"; | ||||
| import "./mixins/MixinOasis.sol"; | ||||
| import "./mixins/MixinShell.sol"; | ||||
| import "./mixins/MixinUniswap.sol"; | ||||
| import "./mixins/MixinUniswapV2.sol"; | ||||
| import "./mixins/MixinUniswapV3.sol"; | ||||
| import "./mixins/MixinZeroExBridge.sol"; | ||||
| 
 | ||||
| contract EthereumBridgeAdapter is | ||||
|     AbstractBridgeAdapter(1, "Ethereum"), | ||||
| contract BridgeAdapter is | ||||
|     IBridgeAdapter, | ||||
|     MixinAaveV2, | ||||
|     MixinBalancer, | ||||
|     MixinBalancerV2, | ||||
|     MixinBalancerV2Batch, | ||||
|     MixinBancor, | ||||
|     MixinBancorV3, | ||||
|     MixinCoFiX, | ||||
|     MixinCompound, | ||||
|     MixinCurve, | ||||
|     MixinCurveV2, | ||||
|     MixinCryptoCom, | ||||
|     MixinDodo, | ||||
|     MixinDodoV2, | ||||
|     MixinKyber, | ||||
|     MixinKyberDmm, | ||||
|     MixinLido, | ||||
|     MixinMakerPSM, | ||||
|     MixinMooniswap, | ||||
|     MixinMStable, | ||||
|     MixinNerve, | ||||
|     MixinOasis, | ||||
|     MixinShell, | ||||
|     MixinUniswap, | ||||
|     MixinUniswapV2, | ||||
| @@ -74,29 +76,43 @@ contract EthereumBridgeAdapter is | ||||
| { | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|         MixinAaveV2() | ||||
|         MixinBalancer() | ||||
|         MixinBalancerV2() | ||||
|         MixinBancor(weth) | ||||
|         MixinBancorV3(weth) | ||||
|         MixinCoFiX() | ||||
|         MixinCompound(weth) | ||||
|         MixinCurve(weth) | ||||
|         MixinCurveV2() | ||||
|         MixinCryptoCom() | ||||
|         MixinDodo() | ||||
|         MixinDodoV2() | ||||
|         MixinKyber(weth) | ||||
|         MixinLido(weth) | ||||
|         MixinMakerPSM() | ||||
|         MixinMooniswap(weth) | ||||
|         MixinMStable() | ||||
|         MixinNerve() | ||||
|         MixinOasis() | ||||
|         MixinShell() | ||||
|         MixinUniswap(weth) | ||||
|         MixinUniswapV2() | ||||
|         MixinUniswapV3() | ||||
|         MixinZeroExBridge() | ||||
|     {} | ||||
| 
 | ||||
|     function _trade( | ||||
|     function trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bool dryRun | ||||
|         uint256 sellAmount | ||||
|     ) | ||||
|         internal | ||||
|         public | ||||
|         override | ||||
|         returns (uint256 boughtAmount, bool supportedSource) | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         uint128 protocolId = uint128(uint256(order.source) >> 128); | ||||
|         if (protocolId == BridgeProtocols.CURVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurve( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -104,7 +120,6 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.CURVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -112,21 +127,18 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV3) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV3( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV2( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAP) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswap( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -134,7 +146,6 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BALANCER) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeBalancer( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -142,21 +153,20 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BALANCERV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeBalancerV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BALANCERV2BATCH) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeBalancerV2Batch( | ||||
|         } else if (protocolId == BridgeProtocols.KYBER) { | ||||
|             boughtAmount = _tradeKyber( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.MAKERPSM) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeMakerPsm( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -164,7 +174,6 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.MOONISWAP) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeMooniswap( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -172,15 +181,20 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.MSTABLE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeMStable( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.OASIS) { | ||||
|             boughtAmount = _tradeOasis( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.SHELL) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeShell( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -188,49 +202,49 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.DODO) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeDodo( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.DODOV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeDodoV2( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.CRYPTOCOM) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCryptoCom( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BANCOR) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeBancor( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.COFIX) { | ||||
|             boughtAmount = _tradeCoFiX( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.NERVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeNerve( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.KYBERDMM) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeKyberDmm( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.LIDO) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeLido( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -238,7 +252,6 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.AAVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeAaveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -246,22 +259,13 @@ contract EthereumBridgeAdapter is | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.COMPOUND) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCompound( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BANCORV3) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeBancorV3( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNKNOWN) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|         } else { | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
| @@ -27,34 +27,29 @@ library BridgeProtocols { | ||||
|     // A incrementally increasing, append-only list of protocol IDs. | ||||
|     // We don't use an enum so solidity doesn't throw when we pass in a | ||||
|     // new protocol ID that hasn't been rolled up yet. | ||||
|     uint128 internal constant UNKNOWN         = 0; | ||||
|     uint128 internal constant CURVE           = 1; | ||||
|     uint128 internal constant UNISWAPV2       = 2; | ||||
|     uint128 internal constant UNISWAP         = 3; | ||||
|     uint128 internal constant BALANCER        = 4; | ||||
|     uint128 internal constant KYBER           = 5;  // Not used: deprecated. | ||||
|     uint128 internal constant MOONISWAP       = 6; | ||||
|     uint128 internal constant MSTABLE         = 7; | ||||
|     uint128 internal constant OASIS           = 8;  // Not used: deprecated. | ||||
|     uint128 internal constant SHELL           = 9; | ||||
|     uint128 internal constant DODO            = 10; | ||||
|     uint128 internal constant DODOV2          = 11; | ||||
|     uint128 internal constant CRYPTOCOM       = 12; | ||||
|     uint128 internal constant BANCOR          = 13; | ||||
|     uint128 internal constant COFIX           = 14; // Not used: deprecated. | ||||
|     uint128 internal constant NERVE           = 15; | ||||
|     uint128 internal constant MAKERPSM        = 16; | ||||
|     uint128 internal constant BALANCERV2      = 17; | ||||
|     uint128 internal constant UNISWAPV3       = 18; | ||||
|     uint128 internal constant KYBERDMM        = 19; | ||||
|     uint128 internal constant CURVEV2         = 20; | ||||
|     uint128 internal constant LIDO            = 21; | ||||
|     uint128 internal constant CLIPPER         = 22; // Not used: Clipper is now using PLP interface | ||||
|     uint128 internal constant AAVEV2          = 23; | ||||
|     uint128 internal constant COMPOUND        = 24; | ||||
|     uint128 internal constant BALANCERV2BATCH = 25; | ||||
|     uint128 internal constant GMX             = 26; | ||||
|     uint128 internal constant PLATYPUS        = 27; | ||||
|     uint128 internal constant BANCORV3        = 28; | ||||
|     uint128 internal constant VELODROME       = 29; | ||||
|     uint128 internal constant UNKNOWN     = 0; | ||||
|     uint128 internal constant CURVE       = 1; | ||||
|     uint128 internal constant UNISWAPV2   = 2; | ||||
|     uint128 internal constant UNISWAP     = 3; | ||||
|     uint128 internal constant BALANCER    = 4; | ||||
|     uint128 internal constant KYBER       = 5; | ||||
|     uint128 internal constant MOONISWAP   = 6; | ||||
|     uint128 internal constant MSTABLE     = 7; | ||||
|     uint128 internal constant OASIS       = 8; | ||||
|     uint128 internal constant SHELL       = 9; | ||||
|     uint128 internal constant DODO        = 10; | ||||
|     uint128 internal constant DODOV2      = 11; | ||||
|     uint128 internal constant CRYPTOCOM   = 12; | ||||
|     uint128 internal constant BANCOR      = 13; | ||||
|     uint128 internal constant COFIX       = 14; | ||||
|     uint128 internal constant NERVE       = 15; | ||||
|     uint128 internal constant MAKERPSM    = 16; | ||||
|     uint128 internal constant BALANCERV2  = 17; | ||||
|     uint128 internal constant UNISWAPV3   = 18; | ||||
|     uint128 internal constant KYBERDMM    = 19; | ||||
|     uint128 internal constant CURVEV2     = 20; | ||||
|     uint128 internal constant LIDO        = 21; | ||||
|     uint128 internal constant CLIPPER     = 22; // Not used: Clipper is now using PLP interface | ||||
|     uint128 internal constant AAVEV2      = 23; | ||||
|     uint128 internal constant COMPOUND    = 24; | ||||
| } | ||||
|   | ||||
| @@ -1,84 +0,0 @@ | ||||
|  | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./AbstractBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./mixins/MixinNerve.sol"; | ||||
| import "./mixins/MixinUniswapV2.sol"; | ||||
| import "./mixins/MixinZeroExBridge.sol"; | ||||
|  | ||||
| contract CeloBridgeAdapter is | ||||
|     AbstractBridgeAdapter(42220, "Celo"), | ||||
|     MixinNerve, | ||||
|     MixinUniswapV2, | ||||
|     MixinZeroExBridge | ||||
| { | ||||
|     constructor(address _weth) | ||||
|         public | ||||
|     {} | ||||
|  | ||||
|     function _trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bool dryRun | ||||
|     ) | ||||
|         internal | ||||
|         override | ||||
|         returns (uint256 boughtAmount, bool supportedSource) | ||||
|     { | ||||
|         uint128 protocolId = uint128(uint256(order.source) >> 128); | ||||
|         if (protocolId == BridgeProtocols.UNISWAPV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV2( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.NERVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeNerve( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNKNOWN) { | ||||
|             if (dryRun) { return (0, true); }             | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         emit BridgeFill( | ||||
|             order.source, | ||||
|             sellToken, | ||||
|             buyToken, | ||||
|             sellAmount, | ||||
|             boughtAmount | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -1,124 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./AbstractBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./mixins/MixinAaveV2.sol"; | ||||
| import "./mixins/MixinBalancerV2.sol"; | ||||
| import "./mixins/MixinCurve.sol"; | ||||
| import "./mixins/MixinCurveV2.sol"; | ||||
| import "./mixins/MixinNerve.sol"; | ||||
| import "./mixins/MixinUniswapV2.sol"; | ||||
| import "./mixins/MixinZeroExBridge.sol"; | ||||
|  | ||||
| contract FantomBridgeAdapter is | ||||
|     AbstractBridgeAdapter(250, "Fantom"), | ||||
|     MixinAaveV2, | ||||
|     MixinBalancerV2, | ||||
|     MixinCurve, | ||||
|     MixinCurveV2, | ||||
|     MixinNerve, | ||||
|     MixinUniswapV2, | ||||
|     MixinZeroExBridge | ||||
| { | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|         MixinCurve(weth) | ||||
|     {} | ||||
|  | ||||
|     function _trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bool dryRun | ||||
|     ) | ||||
|         internal | ||||
|         override | ||||
|         returns (uint256 boughtAmount, bool supportedSource) | ||||
|     { | ||||
|         uint128 protocolId = uint128(uint256(order.source) >> 128); | ||||
|         if (protocolId == BridgeProtocols.CURVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurve( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.CURVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV2( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BALANCERV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeBalancerV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.NERVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeNerve( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.AAVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeAaveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNKNOWN) { | ||||
|             if (dryRun) { return (0, true); }             | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         emit BridgeFill( | ||||
|             order.source, | ||||
|             sellToken, | ||||
|             buyToken, | ||||
|             sellAmount, | ||||
|             boughtAmount | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -50,10 +50,6 @@ interface IBridgeAdapter { | ||||
|         uint256 outputTokenAmount | ||||
|     ); | ||||
|  | ||||
|     function isSupportedSource(bytes32 source) | ||||
|         external | ||||
|         returns (bool isSupported); | ||||
|  | ||||
|     function trade( | ||||
|         BridgeOrder calldata order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|   | ||||
| @@ -1,114 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./AbstractBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./mixins/MixinCurve.sol"; | ||||
| import "./mixins/MixinCurveV2.sol"; | ||||
| import "./mixins/MixinNerve.sol"; | ||||
| import "./mixins/MixinUniswapV3.sol"; | ||||
| import "./mixins/MixinVelodrome.sol"; | ||||
| import "./mixins/MixinZeroExBridge.sol"; | ||||
|  | ||||
| contract OptimismBridgeAdapter is | ||||
|     AbstractBridgeAdapter(10, "Optimism"), | ||||
|     MixinCurve, | ||||
|     MixinCurveV2, | ||||
|     MixinNerve, | ||||
|     MixinUniswapV3, | ||||
|     MixinVelodrome, | ||||
|     MixinZeroExBridge | ||||
| { | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|         MixinCurve(weth) | ||||
|     {} | ||||
|  | ||||
|     function _trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bool dryRun | ||||
|     ) | ||||
|         internal | ||||
|         override | ||||
|         returns (uint256 boughtAmount, bool supportedSource) | ||||
|     { | ||||
|         uint128 protocolId = uint128(uint256(order.source) >> 128); | ||||
|         if (protocolId == BridgeProtocols.CURVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurve( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.CURVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV3) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV3( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.NERVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeNerve( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.VELODROME) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeVelodrome( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNKNOWN) { | ||||
|             if (dryRun) { return (0, true); }             | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         emit BridgeFill( | ||||
|             order.source, | ||||
|             sellToken, | ||||
|             buyToken, | ||||
|             sellAmount, | ||||
|             boughtAmount | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -1,178 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./AbstractBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./mixins/MixinAaveV2.sol"; | ||||
| import "./mixins/MixinBalancerV2.sol"; | ||||
| import "./mixins/MixinBalancerV2Batch.sol"; | ||||
| import "./mixins/MixinCurve.sol"; | ||||
| import "./mixins/MixinCurveV2.sol"; | ||||
| import "./mixins/MixinDodo.sol"; | ||||
| import "./mixins/MixinDodoV2.sol"; | ||||
| import "./mixins/MixinKyberDmm.sol"; | ||||
| import "./mixins/MixinMStable.sol"; | ||||
| import "./mixins/MixinNerve.sol"; | ||||
| import "./mixins/MixinUniswapV2.sol"; | ||||
| import "./mixins/MixinUniswapV3.sol"; | ||||
| import "./mixins/MixinZeroExBridge.sol"; | ||||
|  | ||||
| contract PolygonBridgeAdapter is | ||||
|     AbstractBridgeAdapter(137, "Polygon"), | ||||
|     MixinAaveV2, | ||||
|     MixinBalancerV2, | ||||
|     MixinBalancerV2Batch, | ||||
|     MixinCurve, | ||||
|     MixinCurveV2, | ||||
|     MixinDodo, | ||||
|     MixinDodoV2, | ||||
|     MixinKyberDmm, | ||||
|     MixinMStable, | ||||
|     MixinNerve, | ||||
|     MixinUniswapV2, | ||||
|     MixinUniswapV3, | ||||
|     MixinZeroExBridge | ||||
| { | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|         MixinCurve(weth) | ||||
|     {} | ||||
|  | ||||
|     function _trade( | ||||
|         BridgeOrder memory order, | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bool dryRun | ||||
|     ) | ||||
|         internal | ||||
|         override | ||||
|         returns (uint256 boughtAmount, bool supportedSource) | ||||
|     { | ||||
|         uint128 protocolId = uint128(uint256(order.source) >> 128); | ||||
|         if (protocolId == BridgeProtocols.CURVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurve( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.CURVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeCurveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV3) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV3( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeUniswapV2( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BALANCERV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeBalancerV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BALANCERV2BATCH) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeBalancerV2Batch( | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.MSTABLE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeMStable( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.DODO) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeDodo( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.DODOV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeDodoV2( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.NERVE) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeNerve( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.KYBERDMM) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeKyberDmm( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.AAVEV2) { | ||||
|             if (dryRun) { return (0, true); } | ||||
|             boughtAmount = _tradeAaveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNKNOWN) { | ||||
|             if (dryRun) { return (0, true); }             | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         emit BridgeFill( | ||||
|             order.source, | ||||
|             sellToken, | ||||
|             buyToken, | ||||
|             sellAmount, | ||||
|             boughtAmount | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -1,107 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
|  | ||||
|  | ||||
| interface IBalancerV2BatchSwapVault { | ||||
|  | ||||
|     enum SwapKind { GIVEN_IN, GIVEN_OUT } | ||||
|  | ||||
|     struct BatchSwapStep { | ||||
|         bytes32 poolId; | ||||
|         uint256 assetInIndex; | ||||
|         uint256 assetOutIndex; | ||||
|         uint256 amount; | ||||
|         bytes userData; | ||||
|     } | ||||
|  | ||||
|     struct FundManagement { | ||||
|         address sender; | ||||
|         bool fromInternalBalance; | ||||
|         address payable recipient; | ||||
|         bool toInternalBalance; | ||||
|     } | ||||
|  | ||||
|     function batchSwap( | ||||
|         SwapKind kind, | ||||
|         BatchSwapStep[] calldata swaps, | ||||
|         IERC20TokenV06[] calldata assets, | ||||
|         FundManagement calldata funds, | ||||
|         int256[] calldata limits, | ||||
|         uint256 deadline | ||||
|     ) external returns (int256[] memory amounts); | ||||
| } | ||||
|  | ||||
| contract MixinBalancerV2Batch { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|  | ||||
|     struct BalancerV2BatchBridgeData { | ||||
|         IBalancerV2BatchSwapVault vault; | ||||
|         IBalancerV2BatchSwapVault.BatchSwapStep[] swapSteps; | ||||
|         IERC20TokenV06[] assets; | ||||
|     } | ||||
|  | ||||
|     function _tradeBalancerV2Batch( | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         // Decode the bridge data. | ||||
|         ( | ||||
|             IBalancerV2BatchSwapVault vault, | ||||
|             IBalancerV2BatchSwapVault.BatchSwapStep[] memory swapSteps, | ||||
|             address[] memory assets_ | ||||
|         ) = abi.decode(bridgeData, (IBalancerV2BatchSwapVault, IBalancerV2BatchSwapVault.BatchSwapStep[], address[])); | ||||
|         IERC20TokenV06[] memory assets; | ||||
|         assembly { assets := assets_ } | ||||
|  | ||||
|         // Grant an allowance to the exchange to spend `fromTokenAddress` token. | ||||
|         assets[0].approveIfBelow(address(vault), sellAmount); | ||||
|  | ||||
|         swapSteps[0].amount = sellAmount; | ||||
|         int256[] memory limits = new int256[](assets.length); | ||||
|         for (uint256 i = 0; i < limits.length; ++i) { | ||||
|             limits[i] = type(int256).max; | ||||
|         } | ||||
|  | ||||
|         int256[] memory amounts = vault.batchSwap( | ||||
|             IBalancerV2BatchSwapVault.SwapKind.GIVEN_IN, | ||||
|             swapSteps, | ||||
|             assets, | ||||
|             IBalancerV2BatchSwapVault.FundManagement({ | ||||
|                 sender: address(this), | ||||
|                 fromInternalBalance: false, | ||||
|                 recipient: payable(address(this)), | ||||
|                 toInternalBalance: false | ||||
|             }), | ||||
|             limits, | ||||
|             block.timestamp + 1 | ||||
|         ); | ||||
|         require(amounts[amounts.length - 1] <= 0, 'Unexpected BalancerV2Batch output'); | ||||
|         return uint256(amounts[amounts.length - 1] * -1); | ||||
|     } | ||||
| } | ||||
| @@ -1,128 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
|  | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; | ||||
|  | ||||
|  | ||||
| /* | ||||
|     BancorV3 | ||||
| */ | ||||
| interface IBancorV3 { | ||||
|     /** | ||||
|      * @dev performs a trade by providing the source amount and returns the target amount and the associated fee | ||||
|      * | ||||
|      * requirements: | ||||
|      * | ||||
|      * - the caller must be the network contract | ||||
|      */ | ||||
|     function tradeBySourceAmount( | ||||
|         address sourceToken, | ||||
|         address targetToken, | ||||
|         uint256 sourceAmount, | ||||
|         uint256 minReturnAmount, | ||||
|         uint256 deadline, | ||||
|         address beneficiary | ||||
|     ) external payable returns (uint256 amount); | ||||
| } | ||||
|  | ||||
| contract MixinBancorV3 { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|  | ||||
|     IERC20TokenV06 constant public BANCORV3_ETH_ADDRESS = | ||||
|         IERC20TokenV06(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); | ||||
|     IEtherTokenV06 private immutable WETH; | ||||
|  | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|     { | ||||
|         WETH = weth; | ||||
|     } | ||||
|  | ||||
|     function _tradeBancorV3( | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 amountOut) | ||||
|  | ||||
|     { | ||||
|         IBancorV3 router; | ||||
|         IERC20TokenV06[] memory path; | ||||
|         address[] memory _path; | ||||
|         uint256 payableAmount = 0; | ||||
|  | ||||
|         { | ||||
|             (router, _path) = abi.decode(bridgeData, (IBancorV3, address[])); | ||||
|             // To get around `abi.decode()` not supporting interface array types. | ||||
|             assembly { path := _path } | ||||
|         } | ||||
|  | ||||
|         require(path.length >= 2, "MixinBancorV3/PATH_LENGTH_MUST_BE_AT_LEAST_TWO"); | ||||
|         require( | ||||
|             path[path.length - 1] == buyToken, | ||||
|             "MixinBancorV3/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN" | ||||
|         ); | ||||
|  | ||||
|         //swap WETH->ETH as Bancor only deals in ETH | ||||
|         if(_path[0] == address(WETH)) { | ||||
|             //withdraw the sell amount of WETH for ETH | ||||
|             WETH.withdraw(sellAmount); | ||||
|             payableAmount = sellAmount; | ||||
|             // set _path[0] to the ETH address if WETH is our buy token | ||||
|             _path[0] = address(BANCORV3_ETH_ADDRESS); | ||||
|         } else { | ||||
|             // Grant the BancorV3 router an allowance to sell the first token. | ||||
|             path[0].approveIfBelow(address(router), sellAmount); | ||||
|         } | ||||
|  | ||||
|         // if we are buying WETH we need to swap to ETH and deposit into WETH after the swap | ||||
|         if(_path[1] == address(WETH)){ | ||||
|             _path[1] = address(BANCORV3_ETH_ADDRESS); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         uint256 amountOut = router.tradeBySourceAmount{value: payableAmount}( | ||||
|             _path[0], | ||||
|             _path[1], | ||||
|              // Sell all tokens we hold. | ||||
|             sellAmount, | ||||
|              // Minimum buy amount. | ||||
|             1, | ||||
|             //deadline | ||||
|             block.timestamp + 1, | ||||
|             // address of the mixin | ||||
|             address(this) | ||||
|         ); | ||||
|  | ||||
|         // if we want to return WETH deposit the ETH amount we sold | ||||
|         if(buyToken == WETH){ | ||||
|             WETH.deposit{value: amountOut}(); | ||||
|         } | ||||
|  | ||||
|         return amountOut; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,92 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; | ||||
|  | ||||
|  | ||||
| interface ICoFiXRouter { | ||||
|     // msg.value = fee | ||||
|     function swapExactTokensForETH( | ||||
|         address token, | ||||
|         uint amountIn, | ||||
|         uint amountOutMin, | ||||
|         address to, | ||||
|         address rewardTo, | ||||
|         uint deadline | ||||
|     ) external payable returns (uint _amountIn, uint _amountOut); | ||||
|  | ||||
|     // msg.value = amountIn + fee | ||||
|     function swapExactETHForTokens( | ||||
|         address token, | ||||
|         uint amountIn, | ||||
|         uint amountOutMin, | ||||
|         address to, | ||||
|         address rewardTo, | ||||
|         uint deadline | ||||
|     ) external payable returns (uint _amountIn, uint _amountOut); | ||||
| } | ||||
|  | ||||
| interface ICoFiXPair { | ||||
|  | ||||
|     function swapWithExact(address outToken, address to) | ||||
|         external | ||||
|         payable | ||||
|         returns ( | ||||
|             uint amountIn, | ||||
|             uint amountOut, | ||||
|             uint oracleFeeChange, | ||||
|             uint256[4] memory tradeInfo | ||||
|         ); | ||||
| } | ||||
|  | ||||
| contract MixinCoFiX { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|  | ||||
|     function _tradeCoFiX( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         (uint256 fee, ICoFiXPair pool) = abi.decode(bridgeData, (uint256, ICoFiXPair)); | ||||
|         // Transfer tokens into the pool | ||||
|         LibERC20TokenV06.compatTransfer( | ||||
|             sellToken, | ||||
|             address(pool), | ||||
|             sellAmount | ||||
|         ); | ||||
|         // Call the swap exact with the tokens now in the pool | ||||
|         // pay the NEST Oracle fee with ETH | ||||
|         (/* In */, boughtAmount, , ) = pool.swapWithExact{value: fee}( | ||||
|             address(buyToken), | ||||
|             address(this) | ||||
|         ); | ||||
|  | ||||
|         return boughtAmount; | ||||
|     } | ||||
| } | ||||
| @@ -1,98 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
|  | ||||
| /* | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; | ||||
| import "../IBridgeAdapter.sol"; | ||||
|  | ||||
| /* | ||||
|     UniswapV2 | ||||
| */ | ||||
| interface IGmxRouter { | ||||
|  | ||||
|     // /// @dev Swaps an exact amount of input tokens for as many output tokens as possible, along the route determined by the path. | ||||
|     // ///      The first element of path is the input token, the last is the output token, and any intermediate elements represent | ||||
|     // ///      intermediate pairs to trade through (if, for example, a direct pair does not exist). | ||||
|     // /// @param _path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity. | ||||
|     // /// @param _amountIn The amount of input tokens to send. | ||||
|     // /// @param _minOut The minimum amount of output tokens that must be received for the transaction not to revert. | ||||
|     // /// @param _reciever Recipient of the output tokens. | ||||
|     function swap( | ||||
|        address[] calldata _path, uint256 _amountIn, uint256 _minOut, address _receiver | ||||
|     ) external; | ||||
| } | ||||
|  | ||||
| contract MixinGMX { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|     using LibSafeMathV06 for uint256; | ||||
|  | ||||
|     function _tradeGMX( | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         public | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         address _router; | ||||
|         address reader; | ||||
|         address vault; | ||||
|         address[] memory _path; | ||||
|         IGmxRouter router; | ||||
|         IERC20TokenV06[] memory path; | ||||
|  | ||||
|         { | ||||
|             //decode the bridge data | ||||
|             (_router, reader, vault, _path) = abi.decode(bridgeData, (address, address, address, address[])); | ||||
|             // To get around `abi.decode()` not supporting interface array types. | ||||
|             assembly { path := _path } | ||||
|         } | ||||
|  | ||||
|         require(path.length >= 2, "MixinGMX/PATH_LENGTH_MUST_BE_AT_LEAST_TWO"); | ||||
|         require( | ||||
|             path[path.length - 1] == buyToken, | ||||
|             "MixinGMX/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN" | ||||
|         ); | ||||
|  | ||||
|         //connect to the GMX router | ||||
|         router = IGmxRouter(_router); | ||||
|  | ||||
|         // Grant the GMX router an allowance to sell the first token. | ||||
|         path[0].approveIfBelow(address(router), sellAmount); | ||||
|  | ||||
|         //track the balance to know how much we bought | ||||
|         uint256 beforeBalance = buyToken.balanceOf(address(this)); | ||||
|         router.swap( | ||||
|             // Convert to `buyToken` along this path. | ||||
|             _path, | ||||
|              // Sell all tokens we hold. | ||||
|             sellAmount, | ||||
|              // Minimum buy amount. | ||||
|             0, | ||||
|             // Recipient is `this`. | ||||
|             address(this) | ||||
|         ); | ||||
|  | ||||
|         //calculate the difference in balance from preswap->postswap to find how many tokens out | ||||
|         boughtAmount = buyToken.balanceOf(address(this)).safeSub(beforeBalance); | ||||
|  | ||||
|         return boughtAmount; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,124 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; | ||||
| import "../IBridgeAdapter.sol"; | ||||
|  | ||||
| interface IKyberNetworkProxy { | ||||
|  | ||||
|     /// @dev Sells `sellTokenAddress` tokens for `buyTokenAddress` tokens | ||||
|     /// using a hint for the reserve. | ||||
|     /// @param sellToken Token to sell. | ||||
|     /// @param sellAmount Amount of tokens to sell. | ||||
|     /// @param buyToken Token to buy. | ||||
|     /// @param recipientAddress Address to send bought tokens to. | ||||
|     /// @param maxBuyTokenAmount A limit on the amount of tokens to buy. | ||||
|     /// @param minConversionRate The minimal conversion rate. If actual rate | ||||
|     ///        is lower, trade is canceled. | ||||
|     /// @param walletId The wallet ID to send part of the fees | ||||
|     /// @param hint The hint for the selective inclusion (or exclusion) of reserves | ||||
|     /// @return boughtAmount Amount of tokens bought. | ||||
|     function tradeWithHint( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         uint256 sellAmount, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         address payable recipientAddress, | ||||
|         uint256 maxBuyTokenAmount, | ||||
|         uint256 minConversionRate, | ||||
|         address payable walletId, | ||||
|         bytes calldata hint | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|         returns (uint256 boughtAmount); | ||||
| } | ||||
|  | ||||
| contract MixinKyber { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|  | ||||
|     /// @dev Address indicating the trade is using ETH | ||||
|     IERC20TokenV06 private immutable KYBER_ETH_ADDRESS = | ||||
|         IERC20TokenV06(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); | ||||
|     /// @dev Mainnet address of the WETH contract. | ||||
|     IEtherTokenV06 private immutable WETH; | ||||
|  | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|     { | ||||
|         WETH = weth; | ||||
|     } | ||||
|  | ||||
|     function _tradeKyber( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         (IKyberNetworkProxy kyber, bytes memory hint) = | ||||
|             abi.decode(bridgeData, (IKyberNetworkProxy, bytes)); | ||||
|  | ||||
|         uint256 payableAmount = 0; | ||||
|         if (sellToken != WETH) { | ||||
|             // If the input token is not WETH, grant an allowance to the exchange | ||||
|             // to spend them. | ||||
|             sellToken.approveIfBelow( | ||||
|                 address(kyber), | ||||
|                 sellAmount | ||||
|             ); | ||||
|         } else { | ||||
|             // If the input token is WETH, unwrap it and attach it to the call. | ||||
|             payableAmount = sellAmount; | ||||
|             WETH.withdraw(payableAmount); | ||||
|         } | ||||
|  | ||||
|         // Try to sell all of this contract's input token balance through | ||||
|         // `KyberNetworkProxy.trade()`. | ||||
|         boughtAmount = kyber.tradeWithHint{ value: payableAmount }( | ||||
|             // Input token. | ||||
|             sellToken == WETH ? KYBER_ETH_ADDRESS : sellToken, | ||||
|             // Sell amount. | ||||
|             sellAmount, | ||||
|             // Output token. | ||||
|             buyToken == WETH ? KYBER_ETH_ADDRESS : buyToken, | ||||
|             // Transfer to this contract | ||||
|             address(uint160(address(this))), | ||||
|             // Buy as much as possible. | ||||
|             uint256(-1), | ||||
|             // Lowest minimum conversion rate | ||||
|             1, | ||||
|             // No affiliate address. | ||||
|             address(0), | ||||
|             hint | ||||
|         ); | ||||
|         // If receving ETH, wrap it to WETH. | ||||
|         if (buyToken == WETH) { | ||||
|             WETH.deposit{ value: boughtAmount }(); | ||||
|         } | ||||
|         return boughtAmount; | ||||
|     } | ||||
| } | ||||
| @@ -26,7 +26,7 @@ import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev Minimal interface for minting StETH | ||||
| interface IStETH { | ||||
| interface ILido { | ||||
|     /// @dev Adds eth to the pool | ||||
|     /// @param _referral optional address for referrals | ||||
|     /// @return StETH Amount of shares generated | ||||
| @@ -37,33 +37,6 @@ interface IStETH { | ||||
|     function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256); | ||||
| } | ||||
|  | ||||
| /// @dev Minimal interface for wrapping/unwrapping stETH. | ||||
| interface IWstETH { | ||||
|  | ||||
|     /** | ||||
|      * @notice Exchanges stETH to wstETH | ||||
|      * @param _stETHAmount amount of stETH to wrap in exchange for wstETH | ||||
|      * @dev Requirements: | ||||
|      *  - `_stETHAmount` must be non-zero | ||||
|      *  - msg.sender must approve at least `_stETHAmount` stETH to this | ||||
|      *    contract. | ||||
|      *  - msg.sender must have at least `_stETHAmount` of stETH. | ||||
|      * User should first approve _stETHAmount to the WstETH contract | ||||
|      * @return Amount of wstETH user receives after wrap | ||||
|      */ | ||||
|     function wrap(uint256 _stETHAmount) external returns (uint256); | ||||
|  | ||||
|     /** | ||||
|      * @notice Exchanges wstETH to stETH | ||||
|      * @param _wstETHAmount amount of wstETH to uwrap in exchange for stETH | ||||
|      * @dev Requirements: | ||||
|      *  - `_wstETHAmount` must be non-zero | ||||
|      *  - msg.sender must have at least `_wstETHAmount` wstETH. | ||||
|      * @return Amount of stETH user receives after unwrap | ||||
|      */ | ||||
|     function unwrap(uint256 _wstETHAmount) external returns (uint256); | ||||
| } | ||||
|  | ||||
|  | ||||
| contract MixinLido { | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
| @@ -86,43 +59,12 @@ contract MixinLido { | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         if (address(sellToken) == address(WETH)) { | ||||
|             return _tradeStETH(buyToken, sellAmount, bridgeData); | ||||
|         }  | ||||
|  | ||||
|         return _tradeWstETH(sellToken, buyToken, sellAmount, bridgeData); | ||||
|     } | ||||
|  | ||||
|     function _tradeStETH( | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) private returns (uint256 boughtAmount) { | ||||
|         (IStETH stETH) = abi.decode(bridgeData, (IStETH)); | ||||
|         if (address(buyToken) == address(stETH)) { | ||||
|         (ILido lido) = abi.decode(bridgeData, (ILido)); | ||||
|         if (address(sellToken) == address(WETH) && address(buyToken) == address(lido)) { | ||||
|             WETH.withdraw(sellAmount); | ||||
|             return stETH.getPooledEthByShares(stETH.submit{ value: sellAmount}(address(0))); | ||||
|             boughtAmount = lido.getPooledEthByShares(lido.submit{ value: sellAmount}(address(0))); | ||||
|         } else { | ||||
|             revert("MixinLido/UNSUPPORTED_TOKEN_PAIR"); | ||||
|         } | ||||
|  | ||||
|         revert("MixinLido/UNSUPPORTED_TOKEN_PAIR"); | ||||
|     } | ||||
|  | ||||
|     function _tradeWstETH( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|  | ||||
|     ) private returns(uint256 boughtAmount){ | ||||
|         (IEtherTokenV06 stETH, IWstETH wstETH) = abi.decode(bridgeData, (IEtherTokenV06, IWstETH)); | ||||
|         if (address(sellToken) == address(stETH) && address(buyToken) == address(wstETH) ) { | ||||
|             sellToken.approveIfBelow(address(wstETH), sellAmount); | ||||
|             return wstETH.wrap(sellAmount); | ||||
|         } | ||||
|         if (address(sellToken) == address(wstETH) && address(buyToken) == address(stETH) ) { | ||||
|             return wstETH.unwrap(sellAmount); | ||||
|         } | ||||
|  | ||||
|         revert("MixinLido/UNSUPPORTED_TOKEN_PAIR"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,76 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "../IBridgeAdapter.sol"; | ||||
|  | ||||
| interface IOasis { | ||||
|  | ||||
|     /// @dev Sell `sellAmount` of `sellToken` token and receive `buyToken` token. | ||||
|     /// @param sellToken The token being sold. | ||||
|     /// @param sellAmount The amount of `sellToken` token being sold. | ||||
|     /// @param buyToken The token being bought. | ||||
|     /// @param minBoughtAmount Minimum amount of `buyToken` token to buy. | ||||
|     /// @return boughtAmount Amount of `buyToken` bought. | ||||
|     function sellAllAmount( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         uint256 sellAmount, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 minBoughtAmount | ||||
|     ) | ||||
|         external | ||||
|         returns (uint256 boughtAmount); | ||||
| } | ||||
|  | ||||
| contract MixinOasis { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|  | ||||
|     function _tradeOasis( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|  | ||||
|         (IOasis oasis) = abi.decode(bridgeData, (IOasis)); | ||||
|  | ||||
|         // Grant an allowance to the exchange to spend `sellToken` token. | ||||
|         sellToken.approveIfBelow( | ||||
|             address(oasis), | ||||
|             sellAmount | ||||
|         ); | ||||
|         // Try to sell all of this contract's `sellToken` token balance. | ||||
|         boughtAmount = oasis.sellAllAmount( | ||||
|             sellToken, | ||||
|             sellAmount, | ||||
|             buyToken, | ||||
|             // min fill amount | ||||
|             1 | ||||
|         ); | ||||
|         return boughtAmount; | ||||
|     } | ||||
| } | ||||
| @@ -1,98 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; | ||||
|  | ||||
|  | ||||
| interface IPlatypusRouter { | ||||
|  | ||||
|     function swapTokensForTokens( | ||||
|         address[] calldata tokenPath, | ||||
|         address[] calldata poolPath, | ||||
|         uint256 fromAmount, | ||||
|         uint256 minimumToAmount, | ||||
|         address to, | ||||
|         uint256 deadline | ||||
|     ) external returns (uint256 amountOut, uint256 haircut); | ||||
| } | ||||
|  | ||||
| contract MixinPlatypus { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|     using LibSafeMathV06 for uint256; | ||||
|  | ||||
|     function _tradePlatypus( | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         public | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         IPlatypusRouter router; | ||||
|         address _router; | ||||
|         address[] memory _pool; | ||||
|         IERC20TokenV06[] memory path; | ||||
|         address[] memory _path; | ||||
|  | ||||
|         { | ||||
|             (_router, _pool, _path) = abi.decode(bridgeData, (address, address[], address[])); | ||||
|  | ||||
|             // To get around `abi.decode()` not supporting interface array types. | ||||
|             assembly { path := _path } | ||||
|         } | ||||
|  | ||||
|         //connect to the ptp router | ||||
|         router = IPlatypusRouter(_router); | ||||
|  | ||||
|         require(path.length >= 2, "MixinPlatypus/PATH_LENGTH_MUST_BE_AT_LEAST_TWO"); | ||||
|         require( | ||||
|             path[path.length - 1] == buyToken, | ||||
|             "MixinPlatypus/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN" | ||||
|         ); | ||||
|         // Grant the Platypus router an allowance to sell the first token. | ||||
|         path[0].approveIfBelow(address(router), sellAmount); | ||||
|  | ||||
|         //keep track of the previous balance to confirm amount out | ||||
|         uint256 beforeBalance = buyToken.balanceOf(address(this)); | ||||
|  | ||||
|         router.swapTokensForTokens( | ||||
|             // Convert to `buyToken` along this path. | ||||
|             _path, | ||||
|             // pool to swap on | ||||
|             _pool, | ||||
|              // Sell all tokens we hold. | ||||
|             sellAmount, | ||||
|              // Minimum buy amount. | ||||
|             0, | ||||
|             // Recipient is `this`. | ||||
|             address(this), | ||||
|  | ||||
|             block.timestamp + 1 | ||||
|         ); | ||||
|         //calculate the buy amount from the tokens we recieved | ||||
|         boughtAmount = buyToken.balanceOf(address(this)).safeSub(beforeBalance); | ||||
|         return boughtAmount; | ||||
|     } | ||||
| } | ||||
| @@ -1,64 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
|  | ||||
| interface IVelodromeRouter { | ||||
|     function swapExactTokensForTokensSimple( | ||||
|         uint256 amountIn, | ||||
|         uint256 amountOutMin, | ||||
|         address tokenFrom, | ||||
|         address tokenTo, | ||||
|         bool stable, | ||||
|         address to, | ||||
|         uint256 deadline | ||||
|     ) external returns (uint256[] memory amounts);  | ||||
| } | ||||
|  | ||||
| contract MixinVelodrome { | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|  | ||||
|     function _tradeVelodrome( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|  | ||||
|         (IVelodromeRouter router, bool stable) = abi.decode(bridgeData, (IVelodromeRouter, bool)); | ||||
|         sellToken.approveIfBelow(address(router), sellAmount); | ||||
|  | ||||
|         boughtAmount = router.swapExactTokensForTokensSimple( | ||||
|             sellAmount, | ||||
|             0,  | ||||
|             address(sellToken), | ||||
|             address(buyToken), | ||||
|             stable, | ||||
|             address(this), | ||||
|             block.timestamp + 1 | ||||
|         )[1]; | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-zero-ex", | ||||
|     "version": "0.35.0", | ||||
|     "version": "0.31.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -41,9 +41,9 @@ | ||||
|         "rollback": "node ./lib/scripts/rollback.js" | ||||
|     }, | ||||
|     "config": { | ||||
|         "publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature,AvalancheBridgeAdapter,BSCBridgeAdapter,CeloBridgeAdapter,EthereumBridgeAdapter,FantomBridgeAdapter,OptimismBridgeAdapter,PolygonBridgeAdapter", | ||||
|         "publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature", | ||||
|         "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", | ||||
|         "abis": "./test/generated-artifacts/@(AbstractBridgeAdapter|AffiliateFeeTransformer|AvalancheBridgeAdapter|BSCBridgeAdapter|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeProtocols|CeloBridgeAdapter|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|EthereumBridgeAdapter|FantomBridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2|MixinBalancerV2Batch|MixinBancor|MixinBancorV3|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinGMX|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinPlatypus|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinVelodrome|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OptimismBridgeAdapter|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PolygonBridgeAdapter|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json" | ||||
|         "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2|MixinBancor|MixinCoFiX|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json" | ||||
|     }, | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
| @@ -55,14 +55,14 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.8.0", | ||||
|         "@0x/contract-addresses": "^6.16.0", | ||||
|         "@0x/contracts-erc20": "^3.3.32", | ||||
|         "@0x/contracts-gen": "^2.0.46", | ||||
|         "@0x/contracts-test-utils": "^5.4.23", | ||||
|         "@0x/dev-utils": "^4.2.14", | ||||
|         "@0x/abi-gen": "^5.7.2", | ||||
|         "@0x/contract-addresses": "^6.11.0", | ||||
|         "@0x/contracts-erc20": "^3.3.26", | ||||
|         "@0x/contracts-gen": "^2.0.43", | ||||
|         "@0x/contracts-test-utils": "^5.4.17", | ||||
|         "@0x/dev-utils": "^4.2.11", | ||||
|         "@0x/order-utils": "^10.4.28", | ||||
|         "@0x/sol-compiler": "^4.8.1", | ||||
|         "@0x/sol-compiler": "^4.7.8", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.4", | ||||
|         "@types/isomorphic-fetch": "^0.0.35", | ||||
| @@ -79,17 +79,17 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.6.3" | ||||
|         "typescript": "4.2.2" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.5.0", | ||||
|         "@0x/protocol-utils": "^11.15.0", | ||||
|         "@0x/subproviders": "^6.6.5", | ||||
|         "@0x/types": "^3.3.6", | ||||
|         "@0x/typescript-typings": "^5.3.1", | ||||
|         "@0x/utils": "^6.5.3", | ||||
|         "@0x/web3-wrapper": "^7.6.5", | ||||
|         "ethereum-types": "^3.7.0", | ||||
|         "@0x/base-contract": "^6.4.5", | ||||
|         "@0x/protocol-utils": "^1.11.0", | ||||
|         "@0x/subproviders": "^6.6.2", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|         "@0x/utils": "^6.5.0", | ||||
|         "@0x/web3-wrapper": "^7.6.2", | ||||
|         "ethereum-types": "^3.6.0", | ||||
|         "ethereumjs-util": "^7.0.10", | ||||
|         "ethers": "~4.0.4" | ||||
|     }, | ||||
|   | ||||
| @@ -6,13 +6,9 @@ | ||||
| import { ContractArtifact } from 'ethereum-types'; | ||||
|  | ||||
| import * as AffiliateFeeTransformer from '../generated-artifacts/AffiliateFeeTransformer.json'; | ||||
| import * as AvalancheBridgeAdapter from '../generated-artifacts/AvalancheBridgeAdapter.json'; | ||||
| import * as BatchFillNativeOrdersFeature from '../generated-artifacts/BatchFillNativeOrdersFeature.json'; | ||||
| import * as BSCBridgeAdapter from '../generated-artifacts/BSCBridgeAdapter.json'; | ||||
| import * as CeloBridgeAdapter from '../generated-artifacts/CeloBridgeAdapter.json'; | ||||
| import * as BridgeAdapter from '../generated-artifacts/BridgeAdapter.json'; | ||||
| import * as CurveLiquidityProvider from '../generated-artifacts/CurveLiquidityProvider.json'; | ||||
| import * as EthereumBridgeAdapter from '../generated-artifacts/EthereumBridgeAdapter.json'; | ||||
| import * as FantomBridgeAdapter from '../generated-artifacts/FantomBridgeAdapter.json'; | ||||
| import * as FeeCollector from '../generated-artifacts/FeeCollector.json'; | ||||
| import * as FeeCollectorController from '../generated-artifacts/FeeCollectorController.json'; | ||||
| import * as FillQuoteTransformer from '../generated-artifacts/FillQuoteTransformer.json'; | ||||
| @@ -34,11 +30,9 @@ import * as LogMetadataTransformer from '../generated-artifacts/LogMetadataTrans | ||||
| import * as MetaTransactionsFeature from '../generated-artifacts/MetaTransactionsFeature.json'; | ||||
| import * as MultiplexFeature from '../generated-artifacts/MultiplexFeature.json'; | ||||
| import * as NativeOrdersFeature from '../generated-artifacts/NativeOrdersFeature.json'; | ||||
| import * as OptimismBridgeAdapter from '../generated-artifacts/OptimismBridgeAdapter.json'; | ||||
| import * as OtcOrdersFeature from '../generated-artifacts/OtcOrdersFeature.json'; | ||||
| import * as OwnableFeature from '../generated-artifacts/OwnableFeature.json'; | ||||
| import * as PayTakerTransformer from '../generated-artifacts/PayTakerTransformer.json'; | ||||
| import * as PolygonBridgeAdapter from '../generated-artifacts/PolygonBridgeAdapter.json'; | ||||
| import * as PositiveSlippageFeeTransformer from '../generated-artifacts/PositiveSlippageFeeTransformer.json'; | ||||
| import * as SimpleFunctionRegistryFeature from '../generated-artifacts/SimpleFunctionRegistryFeature.json'; | ||||
| import * as TransformERC20Feature from '../generated-artifacts/TransformERC20Feature.json'; | ||||
| @@ -64,6 +58,7 @@ export const artifacts = { | ||||
|     AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact, | ||||
|     MetaTransactionsFeature: MetaTransactionsFeature as ContractArtifact, | ||||
|     LogMetadataTransformer: LogMetadataTransformer as ContractArtifact, | ||||
|     BridgeAdapter: BridgeAdapter as ContractArtifact, | ||||
|     LiquidityProviderFeature: LiquidityProviderFeature as ContractArtifact, | ||||
|     ILiquidityProviderFeature: ILiquidityProviderFeature as ContractArtifact, | ||||
|     NativeOrdersFeature: NativeOrdersFeature as ContractArtifact, | ||||
| @@ -77,11 +72,4 @@ export const artifacts = { | ||||
|     IMultiplexFeature: IMultiplexFeature as ContractArtifact, | ||||
|     OtcOrdersFeature: OtcOrdersFeature as ContractArtifact, | ||||
|     IOtcOrdersFeature: IOtcOrdersFeature as ContractArtifact, | ||||
|     AvalancheBridgeAdapter: AvalancheBridgeAdapter as ContractArtifact, | ||||
|     BSCBridgeAdapter: BSCBridgeAdapter as ContractArtifact, | ||||
|     CeloBridgeAdapter: CeloBridgeAdapter as ContractArtifact, | ||||
|     EthereumBridgeAdapter: EthereumBridgeAdapter as ContractArtifact, | ||||
|     FantomBridgeAdapter: FantomBridgeAdapter as ContractArtifact, | ||||
|     OptimismBridgeAdapter: OptimismBridgeAdapter as ContractArtifact, | ||||
|     PolygonBridgeAdapter: PolygonBridgeAdapter as ContractArtifact, | ||||
| }; | ||||
|   | ||||
| @@ -35,11 +35,7 @@ export * from './bloom_filter_utils'; | ||||
| export { GREEDY_TOKENS } from './constants'; | ||||
| export { | ||||
|     AffiliateFeeTransformerContract, | ||||
|     AvalancheBridgeAdapterContract, | ||||
|     BSCBridgeAdapterContract, | ||||
|     CeloBridgeAdapterContract, | ||||
|     EthereumBridgeAdapterContract, | ||||
|     FantomBridgeAdapterContract, | ||||
|     BridgeAdapterContract, | ||||
|     FillQuoteTransformerContract, | ||||
|     IOwnableFeatureContract, | ||||
|     IOwnableFeatureEvents, | ||||
| @@ -49,9 +45,7 @@ export { | ||||
|     IZeroExContract, | ||||
|     LogMetadataTransformerContract, | ||||
|     MultiplexFeatureContract, | ||||
|     OptimismBridgeAdapterContract, | ||||
|     PayTakerTransformerContract, | ||||
|     PolygonBridgeAdapterContract, | ||||
|     PositiveSlippageFeeTransformerContract, | ||||
|     TransformERC20FeatureContract, | ||||
|     WethTransformerContract, | ||||
|   | ||||
| @@ -4,13 +4,9 @@ | ||||
|  * ----------------------------------------------------------------------------- | ||||
|  */ | ||||
| export * from '../generated-wrappers/affiliate_fee_transformer'; | ||||
| export * from '../generated-wrappers/avalanche_bridge_adapter'; | ||||
| export * from '../generated-wrappers/b_s_c_bridge_adapter'; | ||||
| export * from '../generated-wrappers/batch_fill_native_orders_feature'; | ||||
| export * from '../generated-wrappers/celo_bridge_adapter'; | ||||
| export * from '../generated-wrappers/bridge_adapter'; | ||||
| export * from '../generated-wrappers/curve_liquidity_provider'; | ||||
| export * from '../generated-wrappers/ethereum_bridge_adapter'; | ||||
| export * from '../generated-wrappers/fantom_bridge_adapter'; | ||||
| export * from '../generated-wrappers/fee_collector'; | ||||
| export * from '../generated-wrappers/fee_collector_controller'; | ||||
| export * from '../generated-wrappers/fill_quote_transformer'; | ||||
| @@ -32,11 +28,9 @@ export * from '../generated-wrappers/log_metadata_transformer'; | ||||
| export * from '../generated-wrappers/meta_transactions_feature'; | ||||
| export * from '../generated-wrappers/multiplex_feature'; | ||||
| export * from '../generated-wrappers/native_orders_feature'; | ||||
| export * from '../generated-wrappers/optimism_bridge_adapter'; | ||||
| export * from '../generated-wrappers/otc_orders_feature'; | ||||
| export * from '../generated-wrappers/ownable_feature'; | ||||
| export * from '../generated-wrappers/pay_taker_transformer'; | ||||
| export * from '../generated-wrappers/polygon_bridge_adapter'; | ||||
| export * from '../generated-wrappers/positive_slippage_fee_transformer'; | ||||
| export * from '../generated-wrappers/simple_function_registry_feature'; | ||||
| export * from '../generated-wrappers/transform_erc20_feature'; | ||||
|   | ||||
| @@ -5,20 +5,15 @@ | ||||
|  */ | ||||
| import { ContractArtifact } from 'ethereum-types'; | ||||
|  | ||||
| import * as AbstractBridgeAdapter from '../test/generated-artifacts/AbstractBridgeAdapter.json'; | ||||
| import * as AffiliateFeeTransformer from '../test/generated-artifacts/AffiliateFeeTransformer.json'; | ||||
| import * as AvalancheBridgeAdapter from '../test/generated-artifacts/AvalancheBridgeAdapter.json'; | ||||
| import * as BatchFillNativeOrdersFeature from '../test/generated-artifacts/BatchFillNativeOrdersFeature.json'; | ||||
| import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json'; | ||||
| import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.json'; | ||||
| import * as BridgeProtocols from '../test/generated-artifacts/BridgeProtocols.json'; | ||||
| import * as BSCBridgeAdapter from '../test/generated-artifacts/BSCBridgeAdapter.json'; | ||||
| import * as CeloBridgeAdapter from '../test/generated-artifacts/CeloBridgeAdapter.json'; | ||||
| import * as CurveLiquidityProvider from '../test/generated-artifacts/CurveLiquidityProvider.json'; | ||||
| import * as ERC1155OrdersFeature from '../test/generated-artifacts/ERC1155OrdersFeature.json'; | ||||
| import * as ERC165Feature from '../test/generated-artifacts/ERC165Feature.json'; | ||||
| import * as ERC721OrdersFeature from '../test/generated-artifacts/ERC721OrdersFeature.json'; | ||||
| import * as EthereumBridgeAdapter from '../test/generated-artifacts/EthereumBridgeAdapter.json'; | ||||
| import * as FantomBridgeAdapter from '../test/generated-artifacts/FantomBridgeAdapter.json'; | ||||
| import * as FeeCollector from '../test/generated-artifacts/FeeCollector.json'; | ||||
| import * as FeeCollectorController from '../test/generated-artifacts/FeeCollectorController.json'; | ||||
| import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json'; | ||||
| @@ -106,28 +101,26 @@ import * as MetaTransactionsFeature from '../test/generated-artifacts/MetaTransa | ||||
| import * as MixinAaveV2 from '../test/generated-artifacts/MixinAaveV2.json'; | ||||
| import * as MixinBalancer from '../test/generated-artifacts/MixinBalancer.json'; | ||||
| import * as MixinBalancerV2 from '../test/generated-artifacts/MixinBalancerV2.json'; | ||||
| import * as MixinBalancerV2Batch from '../test/generated-artifacts/MixinBalancerV2Batch.json'; | ||||
| import * as MixinBancor from '../test/generated-artifacts/MixinBancor.json'; | ||||
| import * as MixinBancorV3 from '../test/generated-artifacts/MixinBancorV3.json'; | ||||
| import * as MixinCoFiX from '../test/generated-artifacts/MixinCoFiX.json'; | ||||
| import * as MixinCompound from '../test/generated-artifacts/MixinCompound.json'; | ||||
| import * as MixinCryptoCom from '../test/generated-artifacts/MixinCryptoCom.json'; | ||||
| import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json'; | ||||
| import * as MixinCurveV2 from '../test/generated-artifacts/MixinCurveV2.json'; | ||||
| import * as MixinDodo from '../test/generated-artifacts/MixinDodo.json'; | ||||
| import * as MixinDodoV2 from '../test/generated-artifacts/MixinDodoV2.json'; | ||||
| import * as MixinGMX from '../test/generated-artifacts/MixinGMX.json'; | ||||
| import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json'; | ||||
| import * as MixinKyberDmm from '../test/generated-artifacts/MixinKyberDmm.json'; | ||||
| import * as MixinLido from '../test/generated-artifacts/MixinLido.json'; | ||||
| import * as MixinMakerPSM from '../test/generated-artifacts/MixinMakerPSM.json'; | ||||
| import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json'; | ||||
| import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json'; | ||||
| import * as MixinNerve from '../test/generated-artifacts/MixinNerve.json'; | ||||
| import * as MixinPlatypus from '../test/generated-artifacts/MixinPlatypus.json'; | ||||
| import * as MixinOasis from '../test/generated-artifacts/MixinOasis.json'; | ||||
| import * as MixinShell from '../test/generated-artifacts/MixinShell.json'; | ||||
| import * as MixinUniswap from '../test/generated-artifacts/MixinUniswap.json'; | ||||
| import * as MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json'; | ||||
| import * as MixinUniswapV3 from '../test/generated-artifacts/MixinUniswapV3.json'; | ||||
| import * as MixinVelodrome from '../test/generated-artifacts/MixinVelodrome.json'; | ||||
| import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json'; | ||||
| import * as MooniswapLiquidityProvider from '../test/generated-artifacts/MooniswapLiquidityProvider.json'; | ||||
| import * as MultiplexFeature from '../test/generated-artifacts/MultiplexFeature.json'; | ||||
| @@ -143,13 +136,11 @@ import * as NativeOrdersInfo from '../test/generated-artifacts/NativeOrdersInfo. | ||||
| import * as NativeOrdersProtocolFees from '../test/generated-artifacts/NativeOrdersProtocolFees.json'; | ||||
| import * as NativeOrdersSettlement from '../test/generated-artifacts/NativeOrdersSettlement.json'; | ||||
| import * as NFTOrders from '../test/generated-artifacts/NFTOrders.json'; | ||||
| import * as OptimismBridgeAdapter from '../test/generated-artifacts/OptimismBridgeAdapter.json'; | ||||
| import * as OtcOrdersFeature from '../test/generated-artifacts/OtcOrdersFeature.json'; | ||||
| import * as OwnableFeature from '../test/generated-artifacts/OwnableFeature.json'; | ||||
| import * as PancakeSwapFeature from '../test/generated-artifacts/PancakeSwapFeature.json'; | ||||
| import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json'; | ||||
| import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/PermissionlessTransformerDeployer.json'; | ||||
| import * as PolygonBridgeAdapter from '../test/generated-artifacts/PolygonBridgeAdapter.json'; | ||||
| import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.json'; | ||||
| import * as SimpleFunctionRegistryFeature from '../test/generated-artifacts/SimpleFunctionRegistryFeature.json'; | ||||
| import * as TestBridge from '../test/generated-artifacts/TestBridge.json'; | ||||
| @@ -316,41 +307,32 @@ export const artifacts = { | ||||
|     PositiveSlippageFeeTransformer: PositiveSlippageFeeTransformer as ContractArtifact, | ||||
|     Transformer: Transformer as ContractArtifact, | ||||
|     WethTransformer: WethTransformer as ContractArtifact, | ||||
|     AbstractBridgeAdapter: AbstractBridgeAdapter as ContractArtifact, | ||||
|     AvalancheBridgeAdapter: AvalancheBridgeAdapter as ContractArtifact, | ||||
|     BSCBridgeAdapter: BSCBridgeAdapter as ContractArtifact, | ||||
|     BridgeAdapter: BridgeAdapter as ContractArtifact, | ||||
|     BridgeProtocols: BridgeProtocols as ContractArtifact, | ||||
|     CeloBridgeAdapter: CeloBridgeAdapter as ContractArtifact, | ||||
|     EthereumBridgeAdapter: EthereumBridgeAdapter as ContractArtifact, | ||||
|     FantomBridgeAdapter: FantomBridgeAdapter as ContractArtifact, | ||||
|     IBridgeAdapter: IBridgeAdapter as ContractArtifact, | ||||
|     OptimismBridgeAdapter: OptimismBridgeAdapter as ContractArtifact, | ||||
|     PolygonBridgeAdapter: PolygonBridgeAdapter as ContractArtifact, | ||||
|     MixinAaveV2: MixinAaveV2 as ContractArtifact, | ||||
|     MixinBalancer: MixinBalancer as ContractArtifact, | ||||
|     MixinBalancerV2: MixinBalancerV2 as ContractArtifact, | ||||
|     MixinBalancerV2Batch: MixinBalancerV2Batch as ContractArtifact, | ||||
|     MixinBancor: MixinBancor as ContractArtifact, | ||||
|     MixinBancorV3: MixinBancorV3 as ContractArtifact, | ||||
|     MixinCoFiX: MixinCoFiX as ContractArtifact, | ||||
|     MixinCompound: MixinCompound as ContractArtifact, | ||||
|     MixinCryptoCom: MixinCryptoCom as ContractArtifact, | ||||
|     MixinCurve: MixinCurve as ContractArtifact, | ||||
|     MixinCurveV2: MixinCurveV2 as ContractArtifact, | ||||
|     MixinDodo: MixinDodo as ContractArtifact, | ||||
|     MixinDodoV2: MixinDodoV2 as ContractArtifact, | ||||
|     MixinGMX: MixinGMX as ContractArtifact, | ||||
|     MixinKyber: MixinKyber as ContractArtifact, | ||||
|     MixinKyberDmm: MixinKyberDmm as ContractArtifact, | ||||
|     MixinLido: MixinLido as ContractArtifact, | ||||
|     MixinMStable: MixinMStable as ContractArtifact, | ||||
|     MixinMakerPSM: MixinMakerPSM as ContractArtifact, | ||||
|     MixinMooniswap: MixinMooniswap as ContractArtifact, | ||||
|     MixinNerve: MixinNerve as ContractArtifact, | ||||
|     MixinPlatypus: MixinPlatypus as ContractArtifact, | ||||
|     MixinOasis: MixinOasis as ContractArtifact, | ||||
|     MixinShell: MixinShell as ContractArtifact, | ||||
|     MixinUniswap: MixinUniswap as ContractArtifact, | ||||
|     MixinUniswapV2: MixinUniswapV2 as ContractArtifact, | ||||
|     MixinUniswapV3: MixinUniswapV3 as ContractArtifact, | ||||
|     MixinVelodrome: MixinVelodrome as ContractArtifact, | ||||
|     MixinZeroExBridge: MixinZeroExBridge as ContractArtifact, | ||||
|     IERC1155Token: IERC1155Token as ContractArtifact, | ||||
|     IERC721Token: IERC721Token as ContractArtifact, | ||||
|   | ||||
| @@ -28,7 +28,7 @@ import { artifacts } from '../artifacts'; | ||||
| import { TestFillQuoteTransformerBridgeContract } from '../generated-wrappers/test_fill_quote_transformer_bridge'; | ||||
| import { getRandomLimitOrder, getRandomRfqOrder } from '../utils/orders'; | ||||
| import { | ||||
|     EthereumBridgeAdapterContract, | ||||
|     BridgeAdapterContract, | ||||
|     FillQuoteTransformerContract, | ||||
|     TestFillQuoteTransformerExchangeContract, | ||||
|     TestFillQuoteTransformerHostContract, | ||||
| @@ -52,8 +52,7 @@ blockchainTests.resets('FillQuoteTransformer', env => { | ||||
|     let singleProtocolFee: BigNumber; | ||||
|  | ||||
|     const GAS_PRICE = 1337; | ||||
|     // Left half is 0, corresponding to BridgeProtocol.Unknown | ||||
|     const TEST_BRIDGE_SOURCE = hexUtils.leftPad(hexUtils.random(16), 32); | ||||
|     const TEST_BRIDGE_SOURCE = hexUtils.random(32); | ||||
|     const HIGH_BIT = new BigNumber(2).pow(255); | ||||
|     const REVERT_AMOUNT = new BigNumber('0xdeadbeef'); | ||||
|  | ||||
| @@ -65,8 +64,8 @@ blockchainTests.resets('FillQuoteTransformer', env => { | ||||
|             env.txDefaults, | ||||
|             artifacts, | ||||
|         ); | ||||
|         const bridgeAdapter = await EthereumBridgeAdapterContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.EthereumBridgeAdapter, | ||||
|         const bridgeAdapter = await BridgeAdapterContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.BridgeAdapter, | ||||
|             env.provider, | ||||
|             env.txDefaults, | ||||
|             artifacts, | ||||
|   | ||||
| @@ -3,20 +3,15 @@ | ||||
|  * Warning: This file is auto-generated by contracts-gen. Don't edit manually. | ||||
|  * ----------------------------------------------------------------------------- | ||||
|  */ | ||||
| export * from '../test/generated-wrappers/abstract_bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/affiliate_fee_transformer'; | ||||
| export * from '../test/generated-wrappers/avalanche_bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/b_s_c_bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/batch_fill_native_orders_feature'; | ||||
| export * from '../test/generated-wrappers/bootstrap_feature'; | ||||
| export * from '../test/generated-wrappers/bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/bridge_protocols'; | ||||
| export * from '../test/generated-wrappers/celo_bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/curve_liquidity_provider'; | ||||
| export * from '../test/generated-wrappers/erc1155_orders_feature'; | ||||
| export * from '../test/generated-wrappers/erc165_feature'; | ||||
| export * from '../test/generated-wrappers/erc721_orders_feature'; | ||||
| export * from '../test/generated-wrappers/ethereum_bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/fantom_bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/fee_collector'; | ||||
| export * from '../test/generated-wrappers/fee_collector_controller'; | ||||
| export * from '../test/generated-wrappers/fill_quote_transformer'; | ||||
| @@ -104,28 +99,26 @@ export * from '../test/generated-wrappers/meta_transactions_feature'; | ||||
| export * from '../test/generated-wrappers/mixin_aave_v2'; | ||||
| export * from '../test/generated-wrappers/mixin_balancer'; | ||||
| export * from '../test/generated-wrappers/mixin_balancer_v2'; | ||||
| export * from '../test/generated-wrappers/mixin_balancer_v2_batch'; | ||||
| export * from '../test/generated-wrappers/mixin_bancor'; | ||||
| export * from '../test/generated-wrappers/mixin_bancor_v3'; | ||||
| export * from '../test/generated-wrappers/mixin_co_fi_x'; | ||||
| export * from '../test/generated-wrappers/mixin_compound'; | ||||
| export * from '../test/generated-wrappers/mixin_crypto_com'; | ||||
| export * from '../test/generated-wrappers/mixin_curve'; | ||||
| export * from '../test/generated-wrappers/mixin_curve_v2'; | ||||
| export * from '../test/generated-wrappers/mixin_dodo'; | ||||
| export * from '../test/generated-wrappers/mixin_dodo_v2'; | ||||
| export * from '../test/generated-wrappers/mixin_g_m_x'; | ||||
| export * from '../test/generated-wrappers/mixin_kyber'; | ||||
| export * from '../test/generated-wrappers/mixin_kyber_dmm'; | ||||
| export * from '../test/generated-wrappers/mixin_lido'; | ||||
| export * from '../test/generated-wrappers/mixin_m_stable'; | ||||
| export * from '../test/generated-wrappers/mixin_maker_p_s_m'; | ||||
| export * from '../test/generated-wrappers/mixin_mooniswap'; | ||||
| export * from '../test/generated-wrappers/mixin_nerve'; | ||||
| export * from '../test/generated-wrappers/mixin_platypus'; | ||||
| export * from '../test/generated-wrappers/mixin_oasis'; | ||||
| export * from '../test/generated-wrappers/mixin_shell'; | ||||
| export * from '../test/generated-wrappers/mixin_uniswap'; | ||||
| export * from '../test/generated-wrappers/mixin_uniswap_v2'; | ||||
| export * from '../test/generated-wrappers/mixin_uniswap_v3'; | ||||
| export * from '../test/generated-wrappers/mixin_velodrome'; | ||||
| export * from '../test/generated-wrappers/mixin_zero_ex_bridge'; | ||||
| export * from '../test/generated-wrappers/mooniswap_liquidity_provider'; | ||||
| export * from '../test/generated-wrappers/multiplex_feature'; | ||||
| @@ -141,13 +134,11 @@ export * from '../test/generated-wrappers/native_orders_feature'; | ||||
| export * from '../test/generated-wrappers/native_orders_info'; | ||||
| export * from '../test/generated-wrappers/native_orders_protocol_fees'; | ||||
| export * from '../test/generated-wrappers/native_orders_settlement'; | ||||
| export * from '../test/generated-wrappers/optimism_bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/otc_orders_feature'; | ||||
| export * from '../test/generated-wrappers/ownable_feature'; | ||||
| export * from '../test/generated-wrappers/pancake_swap_feature'; | ||||
| export * from '../test/generated-wrappers/pay_taker_transformer'; | ||||
| export * from '../test/generated-wrappers/permissionless_transformer_deployer'; | ||||
| export * from '../test/generated-wrappers/polygon_bridge_adapter'; | ||||
| export * from '../test/generated-wrappers/positive_slippage_fee_transformer'; | ||||
| export * from '../test/generated-wrappers/simple_function_registry_feature'; | ||||
| export * from '../test/generated-wrappers/test_bridge'; | ||||
|   | ||||
| @@ -4,13 +4,9 @@ | ||||
|     "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*", "./scripts/**/*"], | ||||
|     "files": [ | ||||
|         "generated-artifacts/AffiliateFeeTransformer.json", | ||||
|         "generated-artifacts/AvalancheBridgeAdapter.json", | ||||
|         "generated-artifacts/BSCBridgeAdapter.json", | ||||
|         "generated-artifacts/BatchFillNativeOrdersFeature.json", | ||||
|         "generated-artifacts/CeloBridgeAdapter.json", | ||||
|         "generated-artifacts/BridgeAdapter.json", | ||||
|         "generated-artifacts/CurveLiquidityProvider.json", | ||||
|         "generated-artifacts/EthereumBridgeAdapter.json", | ||||
|         "generated-artifacts/FantomBridgeAdapter.json", | ||||
|         "generated-artifacts/FeeCollector.json", | ||||
|         "generated-artifacts/FeeCollectorController.json", | ||||
|         "generated-artifacts/FillQuoteTransformer.json", | ||||
| @@ -32,30 +28,23 @@ | ||||
|         "generated-artifacts/MetaTransactionsFeature.json", | ||||
|         "generated-artifacts/MultiplexFeature.json", | ||||
|         "generated-artifacts/NativeOrdersFeature.json", | ||||
|         "generated-artifacts/OptimismBridgeAdapter.json", | ||||
|         "generated-artifacts/OtcOrdersFeature.json", | ||||
|         "generated-artifacts/OwnableFeature.json", | ||||
|         "generated-artifacts/PayTakerTransformer.json", | ||||
|         "generated-artifacts/PolygonBridgeAdapter.json", | ||||
|         "generated-artifacts/PositiveSlippageFeeTransformer.json", | ||||
|         "generated-artifacts/SimpleFunctionRegistryFeature.json", | ||||
|         "generated-artifacts/TransformERC20Feature.json", | ||||
|         "generated-artifacts/WethTransformer.json", | ||||
|         "generated-artifacts/ZeroEx.json", | ||||
|         "test/generated-artifacts/AbstractBridgeAdapter.json", | ||||
|         "test/generated-artifacts/AffiliateFeeTransformer.json", | ||||
|         "test/generated-artifacts/AvalancheBridgeAdapter.json", | ||||
|         "test/generated-artifacts/BSCBridgeAdapter.json", | ||||
|         "test/generated-artifacts/BatchFillNativeOrdersFeature.json", | ||||
|         "test/generated-artifacts/BootstrapFeature.json", | ||||
|         "test/generated-artifacts/BridgeAdapter.json", | ||||
|         "test/generated-artifacts/BridgeProtocols.json", | ||||
|         "test/generated-artifacts/CeloBridgeAdapter.json", | ||||
|         "test/generated-artifacts/CurveLiquidityProvider.json", | ||||
|         "test/generated-artifacts/ERC1155OrdersFeature.json", | ||||
|         "test/generated-artifacts/ERC165Feature.json", | ||||
|         "test/generated-artifacts/ERC721OrdersFeature.json", | ||||
|         "test/generated-artifacts/EthereumBridgeAdapter.json", | ||||
|         "test/generated-artifacts/FantomBridgeAdapter.json", | ||||
|         "test/generated-artifacts/FeeCollector.json", | ||||
|         "test/generated-artifacts/FeeCollectorController.json", | ||||
|         "test/generated-artifacts/FillQuoteTransformer.json", | ||||
| @@ -143,28 +132,26 @@ | ||||
|         "test/generated-artifacts/MixinAaveV2.json", | ||||
|         "test/generated-artifacts/MixinBalancer.json", | ||||
|         "test/generated-artifacts/MixinBalancerV2.json", | ||||
|         "test/generated-artifacts/MixinBalancerV2Batch.json", | ||||
|         "test/generated-artifacts/MixinBancor.json", | ||||
|         "test/generated-artifacts/MixinBancorV3.json", | ||||
|         "test/generated-artifacts/MixinCoFiX.json", | ||||
|         "test/generated-artifacts/MixinCompound.json", | ||||
|         "test/generated-artifacts/MixinCryptoCom.json", | ||||
|         "test/generated-artifacts/MixinCurve.json", | ||||
|         "test/generated-artifacts/MixinCurveV2.json", | ||||
|         "test/generated-artifacts/MixinDodo.json", | ||||
|         "test/generated-artifacts/MixinDodoV2.json", | ||||
|         "test/generated-artifacts/MixinGMX.json", | ||||
|         "test/generated-artifacts/MixinKyber.json", | ||||
|         "test/generated-artifacts/MixinKyberDmm.json", | ||||
|         "test/generated-artifacts/MixinLido.json", | ||||
|         "test/generated-artifacts/MixinMStable.json", | ||||
|         "test/generated-artifacts/MixinMakerPSM.json", | ||||
|         "test/generated-artifacts/MixinMooniswap.json", | ||||
|         "test/generated-artifacts/MixinNerve.json", | ||||
|         "test/generated-artifacts/MixinPlatypus.json", | ||||
|         "test/generated-artifacts/MixinOasis.json", | ||||
|         "test/generated-artifacts/MixinShell.json", | ||||
|         "test/generated-artifacts/MixinUniswap.json", | ||||
|         "test/generated-artifacts/MixinUniswapV2.json", | ||||
|         "test/generated-artifacts/MixinUniswapV3.json", | ||||
|         "test/generated-artifacts/MixinVelodrome.json", | ||||
|         "test/generated-artifacts/MixinZeroExBridge.json", | ||||
|         "test/generated-artifacts/MooniswapLiquidityProvider.json", | ||||
|         "test/generated-artifacts/MultiplexFeature.json", | ||||
| @@ -180,13 +167,11 @@ | ||||
|         "test/generated-artifacts/NativeOrdersInfo.json", | ||||
|         "test/generated-artifacts/NativeOrdersProtocolFees.json", | ||||
|         "test/generated-artifacts/NativeOrdersSettlement.json", | ||||
|         "test/generated-artifacts/OptimismBridgeAdapter.json", | ||||
|         "test/generated-artifacts/OtcOrdersFeature.json", | ||||
|         "test/generated-artifacts/OwnableFeature.json", | ||||
|         "test/generated-artifacts/PancakeSwapFeature.json", | ||||
|         "test/generated-artifacts/PayTakerTransformer.json", | ||||
|         "test/generated-artifacts/PermissionlessTransformerDeployer.json", | ||||
|         "test/generated-artifacts/PolygonBridgeAdapter.json", | ||||
|         "test/generated-artifacts/PositiveSlippageFeeTransformer.json", | ||||
|         "test/generated-artifacts/SimpleFunctionRegistryFeature.json", | ||||
|         "test/generated-artifacts/TestBridge.json", | ||||
|   | ||||
| @@ -4,28 +4,23 @@ Audits | ||||
|  | ||||
| Below are links to our third-party audit reports. | ||||
|  | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | **Release**          | **Reports**                                                                                                               | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | ERC721OrdersFeature  | * `ABDK Consulting <https://s3.us-east-2.amazonaws.com/zeips.0x.org/audits/abdk-consulting/ABDK_0x_Solidity_v_1_0.pdf>`__ | | ||||
| |                      |                                                                                                                           | | ||||
| |                      |                                                                                                                           | | ||||
| | ERC1155OrdersFeature |                                                                                                                           | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | Exchange V4          | * `Consensys Diligence (December 2020) <https://consensys.net/diligence/audits/2020/12/0x-exchange-v4/>`__                | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | Exchange V3          | * `Trail of Bits <http://zeips.0x.org.s3-website.us-east-2.amazonaws.com/audits/56/trail-of-bits/audit.pdf>`__            | | ||||
| |                      | * `Consensys Diligence (Exchange) <https://diligence.consensys.net/audits/2019/09/0x-v3-exchange/>`__                     | | ||||
| |                      | * `Consensys Diligence (Staking) <https://diligence.consensys.net/audits/2019/10/0x-v3-staking/>`__                       | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | Exchange V2.1        | * `First <https://docs.google.com/document/d/1jYv6V21MfCSwCS5fxD6ZyaLWGzkpRSUO0lZpST94XsA/edit>`_                         | | ||||
| |                      | * `Consensys Diligence <https://github.com/ConsenSys/0x_audit_report_2018-07-23>`_                                        | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | MultiAssetProxy      | * `Consensys Diligence <https://github.com/ConsenSys/0x-audit-report-2018-12>`__                                          | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | ERC1155Proxy         | * `Consensys Diligence <https://github.com/ConsenSys/0x-audit-report-2019-05>`__                                          | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | StaticCallProxy      | * No third-party audit.                                                                                                   | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| | ERC20BridgeProxy     | * No third-party audit.                                                                                                   | | ||||
| +----------------------+---------------------------------------------------------------------------------------------------------------------------+ | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
| | **Release**      | **Reports**                                                                                                   | | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
| | Exchange V4      | * `Consensys Diligence (December 2020) <https://consensys.net/diligence/audits/2020/12/0x-exchange-v4/>`__    | | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
| | Exchange V3      | * `Trail of Bits <http://zeips.0x.org.s3-website.us-east-2.amazonaws.com/audits/56/trail-of-bits/audit.pdf>`_ | | ||||
| |                  | * `Consensys Diligence (Exchange) <https://diligence.consensys.net/audits/2019/09/0x-v3-exchange/>`__         | | ||||
| |                  | * `Consensys Diligence (Staking) <https://diligence.consensys.net/audits/2019/10/0x-v3-staking/>`__           | | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
| | Exchange V2.1    | * `First <https://docs.google.com/document/d/1jYv6V21MfCSwCS5fxD6ZyaLWGzkpRSUO0lZpST94XsA/edit>`_             | | ||||
| |                  | * `Consensys Diligence <https://github.com/ConsenSys/0x_audit_report_2018-07-23>`_                            | | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
| | MultiAssetProxy  | * `Consensys Diligence <https://github.com/ConsenSys/0x-audit-report-2018-12>`__                              | | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
| | ERC1155Proxy     | * `Consensys Diligence <https://github.com/ConsenSys/0x-audit-report-2019-05>`__                              | | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
| | StaticCallProxy  | * No third-party audit.                                                                                       | | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
| | ERC20BridgeProxy | * No third-party audit.                                                                                       | | ||||
| +------------------+---------------------------------------------------------------------------------------------------------------+ | ||||
							
								
								
									
										13
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								package.json
									
									
									
									
									
								
							| @@ -52,30 +52,29 @@ | ||||
|     }, | ||||
|     "config": { | ||||
|         "contractsPackages": "@0x/contracts-erc20 @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-zero-ex @0x/contracts-treasury", | ||||
|         "nonContractPackages": "@0x/contract-wrappers @0x/contract-addresses @0x/contract-artifacts @0x/contract-wrappers-test @0x/asset-swapper", | ||||
|         "nonContractPackages": "@0x/migrations @0x/contract-wrappers @0x/contract-addresses @0x/contract-artifacts @0x/contract-wrappers-test @0x/asset-swapper", | ||||
|         "ignoreTestsForPackages": "", | ||||
|         "mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic", | ||||
|         "packagesWithDocPages": "@0x/contract-wrappers", | ||||
|         "packagesWithDocPages": "@0x/contract-wrappers @0x/migrations", | ||||
|         "ignoreDependencyVersions": "@types/styled-components @types/node", | ||||
|         "ignoreDependencyVersionsForPackage": "contract-wrappers" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0x/monorepo-scripts": "^3.2.1", | ||||
|         "@0x-lerna-fork/lerna": "3.16.10", | ||||
|         "@0x/monorepo-scripts": "^3.2.4", | ||||
|         "@0xproject/npm-cli-login": "^0.0.11", | ||||
|         "async-child-process": "^1.1.1", | ||||
|         "coveralls": "^3.0.0", | ||||
|         "ganache-cli": "6.12.2", | ||||
|         "ganache-cli": "6.8.0-istanbul.0", | ||||
|         "lcov-result-merger": "^3.0.0", | ||||
|         "lerna": "^3.0.0-beta.25", | ||||
|         "npm-run-all": "^4.1.2", | ||||
|         "prettier": "1.19.1", | ||||
|         "source-map-support": "^0.5.6", | ||||
|         "typescript": "4.6.3", | ||||
|         "typescript": "4.2.2", | ||||
|         "wsrun": "^5.2.4" | ||||
|     }, | ||||
|     "resolutions": { | ||||
|         "merkle-patricia-tree": "3.0.0", | ||||
|         "**/bignumber.js": "^9.0.2" | ||||
|         "merkle-patricia-tree": "^2.3.2" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,277 +1,4 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "16.62.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add MDEX on BSC", | ||||
|                 "pr": 496 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add KnightSwap on BSC", | ||||
|                 "pr": 498 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add Velodrome support on Optimism", | ||||
|                 "pr": 494 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Do not send empty entries on Quote Report", | ||||
|                 "pr": 501 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "KnightSwap/Mdex cosmetic change", | ||||
|                 "pr": 502 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Offboard JetSwap, CafeSwap, JulSwap, and PolyDex", | ||||
|                 "pr": 503 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1655244958 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.61.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add stETH wrap/unwrap support", | ||||
|                 "pr": 476 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Offboard/clean up Oasis, CoFix, and legacy Kyber", | ||||
|                 "pr": 482 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add MeshSwap on Polygon", | ||||
|                 "pr": 491 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1654284040 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.60.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Alias Balancer sor to the old version", | ||||
|                 "pr": 481 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1652931596 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.60.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add BiSwap on BSC", | ||||
|                 "pr": 467 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add GMX and Platypus on Avalanche and Enable KyberDMM on bsc", | ||||
|                 "pr": 478 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add Yoshi Exchange support in Fantom", | ||||
|                 "pr": 473 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Fix KyberDMM gas underestimation", | ||||
|                 "pr": 479 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1652919697 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.59.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Remove SnowSwap on mainnet", | ||||
|                 "pr": 468 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Offboard Swerve Finance and LinkSwap", | ||||
|                 "pr": 469 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Offboard Eth2Dai", | ||||
|                 "pr": 470 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add an optional IRfqClient for SwapQuoter#getSwapQuoteAsync", | ||||
|                 "pr": 467 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1652400434 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.58.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Update Saddle pools on Mainnet", | ||||
|                 "pr": 450 | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.57.3", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Fix a runtime error related to BalancerV2SwapInfoCache", | ||||
|                 "pr": 472 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1652146864 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.57.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Fix missing AMM quotes on indicative Quote Reports", | ||||
|                 "pr": 466 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1651526551 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.57.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Added QUICK/ANY pair on Polygon", | ||||
|                 "pr": 464 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Added cvxFXS/FXS curve pool on mainnet", | ||||
|                 "pr": 465 | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.57.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add BalancerV2 batch swap support", | ||||
|                 "pr": 462 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1650611093 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.56.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add estimatedGas to ExtendedQuoteReport", | ||||
|                 "pr": 463 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1650575781 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.55.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Fix fillRfqOrder VIP being used for swaps that need transformERC20", | ||||
|                 "pr": 461 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1649347667 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.54.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add true VIP support for eligible RFQt swaps", | ||||
|                 "pr": 458 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1649215576 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.53.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Adds support for STG/USDC pool on Curve Mainnet", | ||||
|                 "pr": 451 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Use neon-router in asset-swapper tests", | ||||
|                 "pr": 453 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add sampler blocknumber to quote report data", | ||||
|                 "pr": 448 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1648739346 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.52.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Adds support for mobius money on celo", | ||||
|                 "pr": 423 | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.51.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Added `Curve` `YFI-ETH` pool", | ||||
|                 "pr": 444 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1646888282 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.50.3", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Routing glue optimization", | ||||
|                 "pr": 439 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Move VIP source routing into neon-router & disable fallback orders for native/plp", | ||||
|                 "pr": 440 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1646837959 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.50.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Update `Uniswap_V3` address on `Ropsten`", | ||||
|                 "pr": 441 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1646617024 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.50.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add BTRFLY/WETH Curve pool on mainnet", | ||||
|                 "pr": 437 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Lower Uniswap V3 Sampler gas allowance", | ||||
|                 "pr": 438 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1646312638 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.50.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Adding support for Geist on `Fantom`", | ||||
|                 "pr": 398 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Improve Uniswap V3 gas schedule", | ||||
|                 "pr": 424 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1646225739 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.49.9", | ||||
|         "changes": [ | ||||
| @@ -308,6 +35,7 @@ | ||||
|                 "note": "Fixed btrfly routing to include the ohmV2/dai, ohmV2/btfly, and ohmV2/weth pools", | ||||
|                 "pr": 427 | ||||
|             } | ||||
|  | ||||
|         ], | ||||
|         "timestamp": 1645113751 | ||||
|     }, | ||||
|   | ||||
| @@ -5,105 +5,6 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v16.62.0 - _June 14, 2022_ | ||||
|  | ||||
|     * Add MDEX on BSC (#496) | ||||
|     * Add KnightSwap on BSC (#498) | ||||
|     * Add Velodrome support on Optimism (#494) | ||||
|     * Do not send empty entries on Quote Report (#501) | ||||
|     * KnightSwap/Mdex cosmetic change (#502) | ||||
|     * Offboard JetSwap, CafeSwap, JulSwap, and PolyDex (#503) | ||||
|  | ||||
| ## v16.61.0 - _June 3, 2022_ | ||||
|  | ||||
|     * Add stETH wrap/unwrap support (#476) | ||||
|     * Offboard/clean up Oasis, CoFix, and legacy Kyber (#482) | ||||
|     * Add MeshSwap on Polygon (#491) | ||||
|  | ||||
| ## v16.60.1 - _May 19, 2022_ | ||||
|  | ||||
|     * Alias Balancer sor to the old version (#481) | ||||
|  | ||||
| ## v16.60.0 - _May 19, 2022_ | ||||
|  | ||||
|     * Add BiSwap on BSC (#467) | ||||
|     * Add GMX and Platypus on Avalanche and Enable KyberDMM on bsc (#478) | ||||
|     * Add Yoshi Exchange support in Fantom (#473) | ||||
|     * Fix KyberDMM gas underestimation (#479) | ||||
|  | ||||
| ## v16.59.0 - _May 13, 2022_ | ||||
|  | ||||
|     * Remove SnowSwap on mainnet (#468) | ||||
|     * Offboard Swerve Finance and LinkSwap (#469) | ||||
|     * Offboard Eth2Dai (#470) | ||||
|     * Add an optional IRfqClient for SwapQuoter#getSwapQuoteAsync (#467) | ||||
|  | ||||
| ## v16.58.0 - _Invalid date_ | ||||
|  | ||||
|     * Update Saddle pools on Mainnet (#450) | ||||
|  | ||||
| ## v16.57.3 - _May 10, 2022_ | ||||
|  | ||||
|     * Fix a runtime error related to BalancerV2SwapInfoCache (#472) | ||||
|  | ||||
| ## v16.57.2 - _May 2, 2022_ | ||||
|  | ||||
|     * Fix missing AMM quotes on indicative Quote Reports (#466) | ||||
|  | ||||
| ## v16.57.1 - _Invalid date_ | ||||
|  | ||||
|     * Added QUICK/ANY pair on Polygon (#464) | ||||
|     * Added cvxFXS/FXS curve pool on mainnet (#465) | ||||
|  | ||||
| ## v16.57.0 - _April 22, 2022_ | ||||
|  | ||||
|     * Add BalancerV2 batch swap support (#462) | ||||
|  | ||||
| ## v16.56.0 - _April 21, 2022_ | ||||
|  | ||||
|     * Add estimatedGas to ExtendedQuoteReport (#463) | ||||
|  | ||||
| ## v16.55.0 - _April 7, 2022_ | ||||
|  | ||||
|     * Fix fillRfqOrder VIP being used for swaps that need transformERC20 (#461) | ||||
|  | ||||
| ## v16.54.0 - _April 6, 2022_ | ||||
|  | ||||
|     * Add true VIP support for eligible RFQt swaps (#458) | ||||
|  | ||||
| ## v16.53.0 - _March 31, 2022_ | ||||
|  | ||||
|     * Adds support for STG/USDC pool on Curve Mainnet (#451) | ||||
|     * Use neon-router in asset-swapper tests (#453) | ||||
|     * Add sampler blocknumber to quote report data (#448) | ||||
|  | ||||
| ## v16.52.0 - _Invalid date_ | ||||
|  | ||||
|     * Adds support for mobius money on celo (#423) | ||||
|  | ||||
| ## v16.51.0 - _March 10, 2022_ | ||||
|  | ||||
|     * Added `Curve` `YFI-ETH` pool (#444) | ||||
|  | ||||
| ## v16.50.3 - _March 9, 2022_ | ||||
|  | ||||
|     * Routing glue optimization (#439) | ||||
|     * Move VIP source routing into neon-router & disable fallback orders for native/plp (#440) | ||||
|  | ||||
| ## v16.50.2 - _March 7, 2022_ | ||||
|  | ||||
|     * Update `Uniswap_V3` address on `Ropsten` (#441) | ||||
|  | ||||
| ## v16.50.1 - _March 3, 2022_ | ||||
|  | ||||
|     * Add BTRFLY/WETH Curve pool on mainnet (#437) | ||||
|     * Lower Uniswap V3 Sampler gas allowance (#438) | ||||
|  | ||||
| ## v16.50.0 - _March 2, 2022_ | ||||
|  | ||||
|     * Adding support for Geist on `Fantom` (#398) | ||||
|     * Improve Uniswap V3 gas schedule (#424) | ||||
|  | ||||
| ## v16.49.9 - _February 24, 2022_ | ||||
|  | ||||
|     * Fix native order scaling & filter out 1 wei quotes (#430) | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|     "shouldSaveStandardInput": true, | ||||
|     "compilerSettings": { | ||||
|         "evmVersion": "istanbul", | ||||
|         "optimizer": { "enabled": true, "runs": 200, "details": { "yul": false, "deduplicate": true } }, | ||||
|         "optimizer": { "enabled": true, "runs": 200, "details": { "yul": true, "deduplicate": true } }, | ||||
|         "outputSelection": { | ||||
|             "*": { | ||||
|                 "*": [ | ||||
|   | ||||
| @@ -1,105 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2021 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./interfaces/IBalancerV2Vault.sol"; | ||||
| import "./BalancerV2Common.sol"; | ||||
|  | ||||
| contract BalancerV2BatchSampler is BalancerV2Common { | ||||
|  | ||||
|     // Replaces amount for first step with each takerTokenAmount and calls queryBatchSwap using supplied steps | ||||
|     /// @dev Sample sell quotes from Balancer V2 supporting multihops. | ||||
|     /// @param swapSteps Array of swap steps (can be >= 1). | ||||
|     /// @param swapAssets Array of token address for swaps. | ||||
|     /// @param takerTokenAmounts Taker token sell amount for each sample. | ||||
|     function sampleMultihopSellsFromBalancerV2( | ||||
|         IBalancerV2Vault vault, | ||||
|         IBalancerV2Vault.BatchSwapStep[] memory swapSteps, | ||||
|         address[] memory swapAssets, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         returns (uint256[] memory makerTokenAmounts) | ||||
|     { | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
|         IBalancerV2Vault.FundManagement memory swapFunds = | ||||
|             _createSwapFunds(); | ||||
|  | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             swapSteps[0].amount = takerTokenAmounts[i]; | ||||
|             try | ||||
|                 // For sells we specify the takerToken which is what the vault will receive from the trade | ||||
|                 vault.queryBatchSwap(IBalancerV2Vault.SwapKind.GIVEN_IN, swapSteps, swapAssets, swapFunds) | ||||
|             // amounts represent pool balance deltas from the swap (incoming balance, outgoing balance) | ||||
|             returns (int256[] memory amounts) { | ||||
|                 // Outgoing balance is negative so we need to flip the sign | ||||
|                 // Note - queryBatchSwap will return a delta for each token in the assets array and last asset should be tokenOut | ||||
|                 int256 amountOutFromPool = amounts[amounts.length - 1] * -1; | ||||
|                 if (amountOutFromPool <= 0) { | ||||
|                     break; | ||||
|                 } | ||||
|                 makerTokenAmounts[i] = uint256(amountOutFromPool); | ||||
|             } catch { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Replaces amount for first step with each makerTokenAmount and calls queryBatchSwap using supplied steps | ||||
|     /// @dev Sample buy quotes from Balancer V2 supporting multihops. | ||||
|     /// @param swapSteps Array of swap steps (can be >= 1). | ||||
|     /// @param swapAssets Array of token address for swaps. | ||||
|     /// @param makerTokenAmounts Maker token buy amount for each sample. | ||||
|     function sampleMultihopBuysFromBalancerV2( | ||||
|         IBalancerV2Vault vault, | ||||
|         IBalancerV2Vault.BatchSwapStep[] memory swapSteps, | ||||
|         address[] memory swapAssets, | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         returns (uint256[] memory takerTokenAmounts) | ||||
|     { | ||||
|         uint256 numSamples = makerTokenAmounts.length; | ||||
|         takerTokenAmounts = new uint256[](numSamples); | ||||
|         IBalancerV2Vault.FundManagement memory swapFunds = | ||||
|             _createSwapFunds(); | ||||
|  | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             swapSteps[0].amount = makerTokenAmounts[i]; | ||||
|             try | ||||
|                 // Uses GIVEN_OUT type for Buy | ||||
|                 vault.queryBatchSwap(IBalancerV2Vault.SwapKind.GIVEN_OUT, swapSteps, swapAssets, swapFunds) | ||||
|             // amounts represent pool balance deltas from the swap (incoming balance, outgoing balance) | ||||
|             returns (int256[] memory amounts) { | ||||
|                 int256 amountIntoPool = amounts[0]; | ||||
|                 if (amountIntoPool <= 0) { | ||||
|                     break; | ||||
|                 } | ||||
|                 takerTokenAmounts[i] = uint256(amountIntoPool); | ||||
|             } catch { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,41 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2021 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./interfaces/IBalancerV2Vault.sol"; | ||||
|  | ||||
|  | ||||
| contract BalancerV2Common { | ||||
|  | ||||
|     function _createSwapFunds() | ||||
|         internal | ||||
|         view | ||||
|         returns (IBalancerV2Vault.FundManagement memory) | ||||
|     { | ||||
|         return | ||||
|             IBalancerV2Vault.FundManagement({ | ||||
|                 sender: address(this), | ||||
|                 fromInternalBalance: false, | ||||
|                 recipient: payable(address(this)), | ||||
|                 toInternalBalance: false | ||||
|             }); | ||||
|     } | ||||
| } | ||||
| @@ -21,11 +21,44 @@ pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./SamplerUtils.sol"; | ||||
| import "./interfaces/IBalancerV2Vault.sol"; | ||||
| import "./BalancerV2Common.sol"; | ||||
|  | ||||
| /// @dev Minimal Balancer V2 Vault interface | ||||
| ///      for documentation refer to https://github.com/balancer-labs/balancer-core-v2/blob/master/contracts/vault/interfaces/IVault.sol | ||||
| interface IBalancerV2Vault { | ||||
|     enum SwapKind { GIVEN_IN, GIVEN_OUT } | ||||
|  | ||||
| contract BalancerV2Sampler is SamplerUtils, BalancerV2Common { | ||||
|     struct BatchSwapStep { | ||||
|         bytes32 poolId; | ||||
|         uint256 assetInIndex; | ||||
|         uint256 assetOutIndex; | ||||
|         uint256 amount; | ||||
|         bytes userData; | ||||
|     } | ||||
|  | ||||
|     struct FundManagement { | ||||
|         address sender; | ||||
|         bool fromInternalBalance; | ||||
|         address payable recipient; | ||||
|         bool toInternalBalance; | ||||
|     } | ||||
|  | ||||
|     function queryBatchSwap( | ||||
|         SwapKind kind, | ||||
|         BatchSwapStep[] calldata swaps, | ||||
|         IAsset[] calldata assets, | ||||
|         FundManagement calldata funds | ||||
|     ) external returns (int256[] memory assetDeltas); | ||||
| } | ||||
| interface IAsset { | ||||
|     // solhint-disable-previous-line no-empty-blocks | ||||
| } | ||||
|  | ||||
| contract BalancerV2Sampler is SamplerUtils { | ||||
|  | ||||
|     struct BalancerV2PoolInfo { | ||||
|         bytes32 poolId; | ||||
|         address vault; | ||||
|     } | ||||
|  | ||||
|     /// @dev Sample sell quotes from Balancer V2. | ||||
|     /// @param poolInfo Struct with pool related data | ||||
| @@ -35,7 +68,7 @@ contract BalancerV2Sampler is SamplerUtils, BalancerV2Common { | ||||
|     /// @return makerTokenAmounts Maker amounts bought at each taker token | ||||
|     ///         amount. | ||||
|     function sampleSellsFromBalancerV2( | ||||
|         IBalancerV2Vault.BalancerV2PoolInfo memory poolInfo, | ||||
|         BalancerV2PoolInfo memory poolInfo, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory takerTokenAmounts | ||||
| @@ -45,9 +78,9 @@ contract BalancerV2Sampler is SamplerUtils, BalancerV2Common { | ||||
|     { | ||||
|         _assertValidPair(makerToken, takerToken); | ||||
|         IBalancerV2Vault vault = IBalancerV2Vault(poolInfo.vault); | ||||
|         address[] memory swapAssets = new address[](2); | ||||
|         swapAssets[0] = takerToken; | ||||
|         swapAssets[1] = makerToken; | ||||
|         IAsset[] memory swapAssets = new IAsset[](2); | ||||
|         swapAssets[0] = IAsset(takerToken); | ||||
|         swapAssets[1] = IAsset(makerToken); | ||||
|  | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
| @@ -64,7 +97,7 @@ contract BalancerV2Sampler is SamplerUtils, BalancerV2Common { | ||||
|             // amounts represent pool balance deltas from the swap (incoming balance, outgoing balance) | ||||
|             returns (int256[] memory amounts) { | ||||
|                 // Outgoing balance is negative so we need to flip the sign | ||||
|                 int256 amountOutFromPool = amounts[amounts.length - 1] * -1; | ||||
|                 int256 amountOutFromPool = amounts[1] * -1; | ||||
|                 if (amountOutFromPool <= 0) { | ||||
|                     break; | ||||
|                 } | ||||
| @@ -84,7 +117,7 @@ contract BalancerV2Sampler is SamplerUtils, BalancerV2Common { | ||||
|     /// @return takerTokenAmounts Taker amounts sold at each maker token | ||||
|     ///         amount. | ||||
|     function sampleBuysFromBalancerV2( | ||||
|         IBalancerV2Vault.BalancerV2PoolInfo memory poolInfo, | ||||
|         BalancerV2PoolInfo memory poolInfo, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory makerTokenAmounts | ||||
| @@ -94,9 +127,9 @@ contract BalancerV2Sampler is SamplerUtils, BalancerV2Common { | ||||
|     { | ||||
|         _assertValidPair(makerToken, takerToken); | ||||
|         IBalancerV2Vault vault = IBalancerV2Vault(poolInfo.vault); | ||||
|         address[] memory swapAssets = new address[](2); | ||||
|         swapAssets[0] = takerToken; | ||||
|         swapAssets[1] = makerToken; | ||||
|         IAsset[] memory swapAssets = new IAsset[](2); | ||||
|         swapAssets[0] = IAsset(takerToken); | ||||
|         swapAssets[1] = IAsset(makerToken); | ||||
|  | ||||
|         uint256 numSamples = makerTokenAmounts.length; | ||||
|         takerTokenAmounts = new uint256[](numSamples); | ||||
| @@ -124,7 +157,7 @@ contract BalancerV2Sampler is SamplerUtils, BalancerV2Common { | ||||
|     } | ||||
|  | ||||
|     function _createSwapSteps( | ||||
|         IBalancerV2Vault.BalancerV2PoolInfo memory poolInfo, | ||||
|         BalancerV2PoolInfo memory poolInfo, | ||||
|         uint256 amount | ||||
|     ) private pure returns (IBalancerV2Vault.BatchSwapStep[] memory) { | ||||
|         IBalancerV2Vault.BatchSwapStep[] memory swapSteps = | ||||
| @@ -139,4 +172,18 @@ contract BalancerV2Sampler is SamplerUtils, BalancerV2Common { | ||||
|  | ||||
|         return swapSteps; | ||||
|     } | ||||
|  | ||||
|     function _createSwapFunds() | ||||
|         private | ||||
|         view | ||||
|         returns (IBalancerV2Vault.FundManagement memory) | ||||
|     { | ||||
|         return | ||||
|             IBalancerV2Vault.FundManagement({ | ||||
|                 sender: address(this), | ||||
|                 fromInternalBalance: false, | ||||
|                 recipient: payable(address(this)), | ||||
|                 toInternalBalance: false | ||||
|             }); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -22,8 +22,9 @@ pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./interfaces/IBancor.sol"; | ||||
|  | ||||
| contract CompilerHack {} | ||||
|  | ||||
| contract BancorSampler { | ||||
| contract BancorSampler is CompilerHack { | ||||
|  | ||||
|     /// @dev Base gas limit for Bancor calls. | ||||
|     uint256 constant private BANCOR_CALL_GAS = 300e3; // 300k | ||||
|   | ||||
| @@ -1,120 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./interfaces/IBancorV3.sol"; | ||||
|  | ||||
|  | ||||
| contract BancorV3Sampler | ||||
| { | ||||
|     /// @dev Gas limit for BancorV3 calls. | ||||
|     uint256 constant private BancorV3_CALL_GAS = 150e3; // 150k | ||||
|  | ||||
|     address constant public ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; | ||||
|  | ||||
|     /// @dev Sample sell quotes from BancorV3. | ||||
|     /// @param weth The WETH contract address | ||||
|     /// @param router Router to look up tokens and amounts | ||||
|     /// @param path Token route. Should be takerToken -> makerToken | ||||
|     /// @param takerTokenAmounts Taker token sell amount for each sample. | ||||
|     /// @return makerTokenAmounts Maker amounts bought at each taker token | ||||
|     ///         amount. | ||||
|     function sampleSellsFromBancorV3( | ||||
|         address weth, | ||||
|         address router, | ||||
|         address[] memory path, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory makerTokenAmounts) | ||||
|     { | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
|  | ||||
|         if(path[0] == weth){ | ||||
|             path[0] = ETH; | ||||
|         } | ||||
|         if(path[1] == weth){ | ||||
|             path[1] = ETH; | ||||
|         } | ||||
|  | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             try | ||||
|                 IBancorV3(router).tradeOutputBySourceAmount(path[0], path[1], takerTokenAmounts[i]) | ||||
|                 returns (uint256 amount) | ||||
|             { | ||||
|                 makerTokenAmounts[i] = amount; | ||||
|                 // Break early if there are 0 amounts | ||||
|                 if (makerTokenAmounts[i] == 0) { | ||||
|                     break; | ||||
|                 } | ||||
|             } catch (bytes memory) { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Sample buy quotes from BancorV3. | ||||
|     /// @param weth The WETH contract address | ||||
|     /// @param router Router to look up tokens and amounts | ||||
|     /// @param path Token route. Should be takerToken -> makerToken. | ||||
|     /// @param makerTokenAmounts Maker token buy amount for each sample. | ||||
|     /// @return takerTokenAmounts Taker amounts sold at each maker token | ||||
|     ///         amount. | ||||
|     function sampleBuysFromBancorV3( | ||||
|         address weth, | ||||
|         address router, | ||||
|         address[] memory path, | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory takerTokenAmounts) | ||||
|     { | ||||
|         uint256 numSamples = makerTokenAmounts.length; | ||||
|         takerTokenAmounts = new uint256[](numSamples); | ||||
|  | ||||
|         if(path[0] == weth){ | ||||
|             path[0] = ETH; | ||||
|         } | ||||
|         if(path[1] == weth){ | ||||
|             path[1] = ETH; | ||||
|         } | ||||
|  | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             try | ||||
|                 IBancorV3(router).tradeInputByTargetAmount(path[0], path[1], makerTokenAmounts[i]) | ||||
|                 returns (uint256 amount) | ||||
|             { | ||||
|                 takerTokenAmounts[i] = amount; | ||||
|                 // Break early if there are 0 amounts | ||||
|                 if (takerTokenAmounts[i] == 0) { | ||||
|                     break; | ||||
|                 } | ||||
|             } catch (bytes memory) { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -22,58 +22,52 @@ pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./BalancerSampler.sol"; | ||||
| import "./BalancerV2Sampler.sol"; | ||||
| import "./BalancerV2BatchSampler.sol"; | ||||
| import "./BancorSampler.sol"; | ||||
| import "./BancorV3Sampler.sol"; | ||||
| import "./CompoundSampler.sol"; | ||||
| import "./CurveSampler.sol"; | ||||
| import "./DODOSampler.sol"; | ||||
| import "./DODOV2Sampler.sol"; | ||||
| import "./GMXSampler.sol"; | ||||
| import "./KyberSampler.sol"; | ||||
| import "./KyberDmmSampler.sol"; | ||||
| import "./LidoSampler.sol"; | ||||
| import "./LiquidityProviderSampler.sol"; | ||||
| import "./MakerPSMSampler.sol"; | ||||
| import "./MultiBridgeSampler.sol"; | ||||
| import "./MStableSampler.sol"; | ||||
| import "./MooniswapSampler.sol"; | ||||
| import "./NativeOrderSampler.sol"; | ||||
| import "./PlatypusSampler.sol"; | ||||
| import "./ShellSampler.sol"; | ||||
| import "./SmoothySampler.sol"; | ||||
| import "./TwoHopSampler.sol"; | ||||
| import "./UniswapSampler.sol"; | ||||
| import "./UniswapV2Sampler.sol"; | ||||
| import "./UniswapV3Sampler.sol"; | ||||
| import "./VelodromeSampler.sol"; | ||||
| import "./UtilitySampler.sol"; | ||||
|  | ||||
|  | ||||
| contract ERC20BridgeSampler is | ||||
|     BalancerSampler, | ||||
|     BalancerV2Sampler, | ||||
|     BalancerV2BatchSampler, | ||||
|     BancorSampler, | ||||
|     BancorV3Sampler, | ||||
|     CompoundSampler, | ||||
|     CurveSampler, | ||||
|     DODOSampler, | ||||
|     DODOV2Sampler, | ||||
|     GMXSampler, | ||||
|     KyberSampler, | ||||
|     KyberDmmSampler, | ||||
|     LidoSampler, | ||||
|     LiquidityProviderSampler, | ||||
|     MakerPSMSampler, | ||||
|     MStableSampler, | ||||
|     MooniswapSampler, | ||||
|     MultiBridgeSampler, | ||||
|     NativeOrderSampler, | ||||
|     PlatypusSampler, | ||||
|     ShellSampler, | ||||
|     SmoothySampler, | ||||
|     TwoHopSampler, | ||||
|     UniswapSampler, | ||||
|     UniswapV2Sampler, | ||||
|     UniswapV3Sampler, | ||||
|     VelodromeSampler, | ||||
|     UtilitySampler | ||||
| { | ||||
|  | ||||
| @@ -98,6 +92,4 @@ contract ERC20BridgeSampler is | ||||
|             (callResults[i].success, callResults[i].data) = address(this).call(callDatas[i]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     receive() external payable {} | ||||
| } | ||||
|   | ||||
| @@ -1,96 +0,0 @@ | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./interfaces/IGMX.sol"; | ||||
| import "./ApproximateBuys.sol"; | ||||
| import "./SamplerUtils.sol"; | ||||
|  | ||||
| contract GMXSampler is | ||||
|     SamplerUtils, | ||||
|     ApproximateBuys | ||||
| { | ||||
|     struct GMXInfo { | ||||
|         address reader; | ||||
|         address vault; | ||||
|         address[] path; | ||||
|     } | ||||
|  | ||||
|     function sampleSellsFromGMX( | ||||
|         address reader, | ||||
|         address vault, | ||||
|         address[] memory path, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory makerTokenAmounts) | ||||
|     { | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             try | ||||
|                 IGMX(reader).getAmountOut(IVault(vault), path[0], path[1], takerTokenAmounts[i]) | ||||
|                 returns (uint256 amountAfterFees, uint256 feeAmount) | ||||
|             { | ||||
|                 makerTokenAmounts[i] = amountAfterFees; | ||||
|                 // Break early if there are 0 amounts | ||||
|                 if (makerTokenAmounts[i] == 0) { | ||||
|                     break; | ||||
|                 } | ||||
|             } catch (bytes memory) { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function sampleBuysFromGMX( | ||||
|         address reader, | ||||
|         address vault, | ||||
|         address[] memory path, | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory takerTokenAmounts) | ||||
|     { | ||||
|         address[] memory invertBuyPath = new address[](2); | ||||
|         invertBuyPath[0] = path[1]; | ||||
|         invertBuyPath[1] = path[0]; | ||||
|         return _sampleApproximateBuys( | ||||
|                 ApproximateBuyQuoteOpts({ | ||||
|                     makerTokenData: abi.encode(reader, vault, invertBuyPath), | ||||
|                     takerTokenData: abi.encode(reader, vault, path), | ||||
|                     getSellQuoteCallback: _sampleSellForApproximateBuyFromGMX | ||||
|                 }), | ||||
|                 makerTokenAmounts | ||||
|             ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     function _sampleSellForApproximateBuyFromGMX( | ||||
|         bytes memory takerTokenData, | ||||
|         bytes memory makerTokenData, | ||||
|         uint256 sellAmount | ||||
|     ) | ||||
|         private | ||||
|         view | ||||
|         returns (uint256 buyAmount) | ||||
|     { | ||||
|         (address _reader, address _vault, address[] memory _path ) = abi.decode(takerTokenData, (address, address, address[])); | ||||
|  | ||||
|         (bool success, bytes memory resultData) = address(this).staticcall(abi.encodeWithSelector( | ||||
|             this.sampleSellsFromGMX.selector, | ||||
|             _reader, | ||||
|             _vault, | ||||
|             _path, | ||||
|             _toSingleValueArray(sellAmount) | ||||
|         )); | ||||
|         if(!success) { | ||||
|             return 0; | ||||
|         } | ||||
|         // solhint-disable-next-line indent | ||||
|         return abi.decode(resultData, (uint256[]))[0]; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										301
									
								
								packages/asset-swapper/contracts/src/KyberSampler.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								packages/asset-swapper/contracts/src/KyberSampler.sol
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,301 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./interfaces/IKyberNetwork.sol"; | ||||
| import "./ApproximateBuys.sol"; | ||||
| import "./SamplerUtils.sol"; | ||||
|  | ||||
|  | ||||
| contract KyberSampler is | ||||
|     SamplerUtils, | ||||
|     ApproximateBuys | ||||
| { | ||||
|     /// @dev Gas limit for Kyber calls. | ||||
|     uint256 constant private KYBER_CALL_GAS = 500e3; // 500k | ||||
|     /// @dev Kyber ETH pseudo-address. | ||||
|     address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; | ||||
|  | ||||
|     struct KyberSamplerOpts { | ||||
|         uint256 reserveOffset; | ||||
|         address hintHandler; | ||||
|         address networkProxy; | ||||
|         address weth; | ||||
|         bytes hint; | ||||
|     } | ||||
|  | ||||
|     /// @dev Sample sell quotes from Kyber. | ||||
|     /// @param opts KyberSamplerOpts The nth reserve | ||||
|     /// @param takerToken Address of the taker token (what to sell). | ||||
|     /// @param makerToken Address of the maker token (what to buy). | ||||
|     /// @param takerTokenAmounts Taker token sell amount for each sample. | ||||
|     /// @return reserveId The id of the reserve found at reserveOffset | ||||
|     /// @return hint The hint for the selected reserve | ||||
|     /// @return makerTokenAmounts Maker amounts bought at each taker token amount. | ||||
|     function sampleSellsFromKyberNetwork( | ||||
|         KyberSamplerOpts memory opts, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (bytes32 reserveId, bytes memory hint, uint256[] memory makerTokenAmounts) | ||||
|     { | ||||
|         _assertValidPair(makerToken, takerToken); | ||||
|         reserveId = _getNextReserveId(opts, takerToken, makerToken); | ||||
|         if (reserveId == 0x0) { | ||||
|             return (reserveId, hint, makerTokenAmounts); | ||||
|         } | ||||
|         opts.hint = this.encodeKyberHint(opts, reserveId, takerToken, makerToken); | ||||
|         hint = opts.hint; | ||||
|  | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             uint256 value = this.sampleSellFromKyberNetwork( | ||||
|                 opts, | ||||
|                 takerToken, | ||||
|                 makerToken, | ||||
|                 takerTokenAmounts[i] | ||||
|             ); | ||||
|             makerTokenAmounts[i] = value; | ||||
|             // Break early if there are 0 amounts | ||||
|             if (makerTokenAmounts[i] == 0) { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Sample buy quotes from Kyber. | ||||
|     /// @param opts KyberSamplerOpts The nth reserve | ||||
|     /// @param takerToken Address of the taker token (what to sell). | ||||
|     /// @param makerToken Address of the maker token (what to buy). | ||||
|     /// @param makerTokenAmounts Maker token buy amount for each sample. | ||||
|     /// @return reserveId The id of the reserve found at reserveOffset | ||||
|     /// @return hint The hint for the selected reserve | ||||
|     /// @return takerTokenAmounts Taker amounts sold at each maker token amount. | ||||
|     function sampleBuysFromKyberNetwork( | ||||
|         KyberSamplerOpts memory opts, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (bytes32 reserveId, bytes memory hint, uint256[] memory takerTokenAmounts) | ||||
|     { | ||||
|         _assertValidPair(makerToken, takerToken); | ||||
|  | ||||
|         reserveId = _getNextReserveId(opts, takerToken, makerToken); | ||||
|         if (reserveId == 0x0) { | ||||
|             return (reserveId, hint, takerTokenAmounts); | ||||
|         } | ||||
|         opts.hint = this.encodeKyberHint(opts, reserveId, takerToken, makerToken); | ||||
|         hint = opts.hint; | ||||
|  | ||||
|         takerTokenAmounts = _sampleApproximateBuys( | ||||
|             ApproximateBuyQuoteOpts({ | ||||
|                 makerTokenData: abi.encode(makerToken, opts), | ||||
|                 takerTokenData: abi.encode(takerToken, opts), | ||||
|                 getSellQuoteCallback: _sampleSellForApproximateBuyFromKyber | ||||
|             }), | ||||
|             makerTokenAmounts | ||||
|         ); | ||||
|         return (reserveId, hint, takerTokenAmounts); | ||||
|     } | ||||
|  | ||||
|     function encodeKyberHint( | ||||
|         KyberSamplerOpts memory opts, | ||||
|         bytes32 reserveId, | ||||
|         address takerToken, | ||||
|         address makerToken | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (bytes memory hint) | ||||
|     { | ||||
|         // Build a hint selecting the single reserve | ||||
|         IKyberHintHandler kyberHint = IKyberHintHandler(opts.hintHandler); | ||||
|  | ||||
|         // All other reserves should be ignored with this hint | ||||
|         bytes32[] memory selectedReserves = new bytes32[](1); | ||||
|         selectedReserves[0] = reserveId; | ||||
|         uint256[] memory emptySplits = new uint256[](0); | ||||
|  | ||||
|         if (takerToken == opts.weth) { | ||||
|             // ETH to Token | ||||
|             try | ||||
|                 kyberHint.buildEthToTokenHint | ||||
|                     {gas: KYBER_CALL_GAS} | ||||
|                     ( | ||||
|                         makerToken, | ||||
|                         IKyberHintHandler.TradeType.MaskIn, | ||||
|                         selectedReserves, | ||||
|                         emptySplits | ||||
|                     ) | ||||
|                 returns (bytes memory result) | ||||
|             { | ||||
|                 return result; | ||||
|             } catch (bytes memory) { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|             } | ||||
|         } else if (makerToken == opts.weth) { | ||||
|             // Token to ETH | ||||
|             try | ||||
|                 kyberHint.buildTokenToEthHint | ||||
|                     {gas: KYBER_CALL_GAS} | ||||
|                     ( | ||||
|                         takerToken, | ||||
|                         IKyberHintHandler.TradeType.MaskIn, | ||||
|                         selectedReserves, | ||||
|                         emptySplits | ||||
|                     ) | ||||
|                 returns (bytes memory result) | ||||
|             { | ||||
|                 return result; | ||||
|             } catch (bytes memory) { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|             } | ||||
|  | ||||
|         } else { | ||||
|             // Token to Token | ||||
|             // We use the same reserve both ways | ||||
|             try | ||||
|                 kyberHint.buildTokenToTokenHint | ||||
|                     {gas: KYBER_CALL_GAS} | ||||
|                     ( | ||||
|                         takerToken, | ||||
|                         IKyberHintHandler.TradeType.MaskIn, | ||||
|                         selectedReserves, | ||||
|                         emptySplits, | ||||
|                         makerToken, | ||||
|                         IKyberHintHandler.TradeType.MaskIn, | ||||
|                         selectedReserves, | ||||
|                         emptySplits | ||||
|                     ) | ||||
|                 returns (bytes memory result) | ||||
|             { | ||||
|                 return result; | ||||
|             } catch (bytes memory) { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function _sampleSellForApproximateBuyFromKyber( | ||||
|         bytes memory takerTokenData, | ||||
|         bytes memory makerTokenData, | ||||
|         uint256 sellAmount | ||||
|     ) | ||||
|         private | ||||
|         view | ||||
|         returns (uint256) | ||||
|     { | ||||
|         (address makerToken, KyberSamplerOpts memory opts) = | ||||
|             abi.decode(makerTokenData, (address, KyberSamplerOpts)); | ||||
|         (address takerToken, ) = | ||||
|             abi.decode(takerTokenData, (address, KyberSamplerOpts)); | ||||
|         try | ||||
|             this.sampleSellFromKyberNetwork | ||||
|                 (opts, takerToken, makerToken, sellAmount) | ||||
|             returns (uint256 amount) | ||||
|         { | ||||
|             return amount; | ||||
|         } catch (bytes memory) { | ||||
|             // Swallow failures, leaving all results as zero. | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function sampleSellFromKyberNetwork( | ||||
|         KyberSamplerOpts memory opts, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256 takerTokenAmount | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256 makerTokenAmount) | ||||
|     { | ||||
|         // If there is no hint do not continue | ||||
|         if (opts.hint.length == 0) { | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         try | ||||
|             IKyberNetworkProxy(opts.networkProxy).getExpectedRateAfterFee | ||||
|                 {gas: KYBER_CALL_GAS} | ||||
|                 ( | ||||
|                     takerToken == opts.weth ? KYBER_ETH_ADDRESS : takerToken, | ||||
|                     makerToken == opts.weth ? KYBER_ETH_ADDRESS : makerToken, | ||||
|                     takerTokenAmount, | ||||
|                     0, // fee | ||||
|                     opts.hint | ||||
|                 ) | ||||
|             returns (uint256 rate) | ||||
|         { | ||||
|             uint256 makerTokenDecimals = _getTokenDecimals(makerToken); | ||||
|             uint256 takerTokenDecimals = _getTokenDecimals(takerToken); | ||||
|             makerTokenAmount = | ||||
|                 rate * | ||||
|                 takerTokenAmount * | ||||
|                 10 ** makerTokenDecimals / | ||||
|                 10 ** takerTokenDecimals / | ||||
|                 10 ** 18; | ||||
|             return makerTokenAmount; | ||||
|         } catch (bytes memory) { | ||||
|             // Swallow failures, leaving all results as zero. | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function _getNextReserveId( | ||||
|         KyberSamplerOpts memory opts, | ||||
|         address takerToken, | ||||
|         address makerToken | ||||
|     ) | ||||
|         internal | ||||
|         view | ||||
|         returns (bytes32 reserveId) | ||||
|     { | ||||
|         // Fetch the registered reserves for this pair | ||||
|         IKyberHintHandler kyberHint = IKyberHintHandler(opts.hintHandler); | ||||
|         (bytes32[] memory reserveIds, ,) = kyberHint.getTradingReserves( | ||||
|             takerToken == opts.weth ? KYBER_ETH_ADDRESS : takerToken, | ||||
|             makerToken == opts.weth ? KYBER_ETH_ADDRESS : makerToken, | ||||
|             true, | ||||
|             new bytes(0) // empty hint | ||||
|         ); | ||||
|  | ||||
|         if (opts.reserveOffset >= reserveIds.length) { | ||||
|             return 0x0; | ||||
|         } | ||||
|  | ||||
|         reserveId = reserveIds[opts.reserveOffset]; | ||||
|         // Ignore Kyber Bridged Reserves (0xbb) | ||||
|         if (uint256(reserveId >> 248) == 0xbb) { | ||||
|             return 0x0; | ||||
|         } | ||||
|  | ||||
|         return reserveId; | ||||
|     } | ||||
| } | ||||
| @@ -22,18 +22,10 @@ pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./SamplerUtils.sol"; | ||||
|  | ||||
|  | ||||
| interface IWstETH { | ||||
|     function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256); | ||||
|     function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256); | ||||
| } | ||||
|  | ||||
|  | ||||
| contract LidoSampler is SamplerUtils { | ||||
|     struct LidoInfo { | ||||
|         address stEthToken; | ||||
|         address wethToken; | ||||
|         address wstEthToken; | ||||
|     } | ||||
|  | ||||
|     /// @dev Sample sell quotes from Lido | ||||
| @@ -50,17 +42,20 @@ contract LidoSampler is SamplerUtils { | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         pure | ||||
|         returns (uint256[] memory) | ||||
|     { | ||||
|         _assertValidPair(makerToken, takerToken); | ||||
|  | ||||
|         if (takerToken == lidoInfo.wethToken && makerToken == address(lidoInfo.stEthToken)) { | ||||
|             // Minting stETH is always 1:1 therefore we can just return the same amounts back. | ||||
|             return takerTokenAmounts; | ||||
|         if (takerToken != lidoInfo.wethToken || makerToken != address(lidoInfo.stEthToken)) { | ||||
|             // Return 0 values if not selling WETH for stETH | ||||
|             uint256 numSamples = takerTokenAmounts.length; | ||||
|             uint256[] memory makerTokenAmounts = new uint256[](numSamples); | ||||
|             return makerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         return _sampleSellsForWrapped(lidoInfo, takerToken, makerToken, takerTokenAmounts); | ||||
|         // Minting stETH is always 1:1 therefore we can just return the same amounts back | ||||
|         return takerTokenAmounts; | ||||
|     } | ||||
|  | ||||
|     /// @dev Sample buy quotes from Lido. | ||||
| @@ -77,43 +72,20 @@ contract LidoSampler is SamplerUtils { | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         pure | ||||
|         returns (uint256[] memory) | ||||
|     { | ||||
|         if (takerToken == lidoInfo.wethToken && makerToken == address(lidoInfo.stEthToken)) { | ||||
|             // Minting stETH is always 1:1 therefore we can just return the same amounts back. | ||||
|             return makerTokenAmounts; | ||||
|         _assertValidPair(makerToken, takerToken); | ||||
|  | ||||
|         if (takerToken != lidoInfo.wethToken || makerToken != address(lidoInfo.stEthToken)) { | ||||
|             // Return 0 values if not buying stETH for WETH | ||||
|             uint256 numSamples = makerTokenAmounts.length; | ||||
|             uint256[] memory takerTokenAmounts = new uint256[](numSamples); | ||||
|             return takerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         // Swap out `makerToken` and `takerToken` and re-use `_sampleSellsForWrapped`. | ||||
|         return _sampleSellsForWrapped(lidoInfo, makerToken, takerToken, makerTokenAmounts); | ||||
|     } | ||||
|  | ||||
|     function _sampleSellsForWrapped( | ||||
|         LidoInfo memory lidoInfo, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) private view  returns (uint256[] memory) { | ||||
|         IWstETH wstETH = IWstETH(lidoInfo.wstEthToken); | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         uint256[] memory makerTokenAmounts = new uint256[](numSamples); | ||||
|  | ||||
|         if (takerToken == lidoInfo.stEthToken && makerToken == lidoInfo.wstEthToken) { | ||||
|             for (uint256 i = 0; i < numSamples; i++) { | ||||
|                 makerTokenAmounts[i] = wstETH.getWstETHByStETH(takerTokenAmounts[i]); | ||||
|             } | ||||
|             return makerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         if (takerToken == lidoInfo.wstEthToken && makerToken == lidoInfo.stEthToken) { | ||||
|             for (uint256 i = 0; i < numSamples; i++) { | ||||
|                 makerTokenAmounts[i] = wstETH.getStETHByWstETH(takerTokenAmounts[i]); | ||||
|             } | ||||
|             return makerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         // Returns 0 values. | ||||
|         // Minting stETH is always 1:1 therefore we can just return the same amounts back | ||||
|         return makerTokenAmounts; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										82
									
								
								packages/asset-swapper/contracts/src/MultiBridgeSampler.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								packages/asset-swapper/contracts/src/MultiBridgeSampler.sol
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./interfaces/IMultiBridge.sol"; | ||||
|  | ||||
|  | ||||
| contract MultiBridgeSampler { | ||||
|  | ||||
|     /// @dev Default gas limit for multibridge calls. | ||||
|     uint256 constant private DEFAULT_CALL_GAS = 400e3; // 400k | ||||
|  | ||||
|     /// @dev Sample sell quotes from MultiBridge. | ||||
|     /// @param multibridge Address of the MultiBridge contract. | ||||
|     /// @param takerToken Address of the taker token (what to sell). | ||||
|     /// @param intermediateToken The address of the intermediate token to | ||||
|     ///        use in an indirect route. | ||||
|     /// @param makerToken Address of the maker token (what to buy). | ||||
|     /// @param takerTokenAmounts Taker token sell amount for each sample. | ||||
|     /// @return makerTokenAmounts Maker amounts bought at each taker token | ||||
|     ///         amount. | ||||
|     function sampleSellsFromMultiBridge( | ||||
|         address multibridge, | ||||
|         address takerToken, | ||||
|         address intermediateToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory makerTokenAmounts) | ||||
|     { | ||||
|         // Initialize array of maker token amounts. | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
|  | ||||
|         // If no address provided, return all zeros. | ||||
|         if (multibridge == address(0)) { | ||||
|             return makerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             (bool didSucceed, bytes memory resultData) = | ||||
|                 multibridge.staticcall.gas(DEFAULT_CALL_GAS)( | ||||
|                     abi.encodeWithSelector( | ||||
|                         IMultiBridge(0).getSellQuote.selector, | ||||
|                         takerToken, | ||||
|                         intermediateToken, | ||||
|                         makerToken, | ||||
|                         takerTokenAmounts[i] | ||||
|                     )); | ||||
|             uint256 buyAmount = 0; | ||||
|             if (didSucceed) { | ||||
|                 buyAmount = abi.decode(resultData, (uint256)); | ||||
|             } | ||||
|             // Exit early if the amount is too high for the source to serve | ||||
|             if (buyAmount == 0) { | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             makerTokenAmounts[i] = buyAmount; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,89 +0,0 @@ | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./interfaces/IPlatypus.sol"; | ||||
| import "./ApproximateBuys.sol"; | ||||
| import "./SamplerUtils.sol"; | ||||
|  | ||||
|  | ||||
| contract PlatypusSampler is | ||||
|     SamplerUtils, | ||||
|     ApproximateBuys | ||||
| { | ||||
|  | ||||
|     function sampleSellsFromPlatypus( | ||||
|         address pool, | ||||
|         address[] memory path, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory makerTokenAmounts) | ||||
|     { | ||||
|  | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             try | ||||
|                 IPlatypus(pool).quotePotentialSwap(path[0], path[1], takerTokenAmounts[i]) | ||||
|                 returns (uint256 amountAfterFees, uint256 feeAmount) | ||||
|             { | ||||
|                 makerTokenAmounts[i] = amountAfterFees; | ||||
|                 // Break early if there are 0 amounts | ||||
|                 if (makerTokenAmounts[i] == 0) { | ||||
|                     break; | ||||
|                 } | ||||
|             } catch (bytes memory result) { | ||||
|                 // Swallow failures, leaving all results as zero. | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function sampleBuysFromPlatypus( | ||||
|         address pool, | ||||
|         address[] memory path, | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory takerTokenAmounts) | ||||
|     { | ||||
|         address[] memory invertBuyPath = new address[](2); | ||||
|         invertBuyPath[0] = path[1]; | ||||
|         invertBuyPath[1] = path[0]; | ||||
|         return _sampleApproximateBuys( | ||||
|                 ApproximateBuyQuoteOpts({ | ||||
|                     makerTokenData: abi.encode(pool, invertBuyPath), | ||||
|                     takerTokenData: abi.encode(pool, path), | ||||
|                     getSellQuoteCallback: _sampleSellForApproximateBuyFromPlatypus | ||||
|                 }), | ||||
|                 makerTokenAmounts | ||||
|             ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     function _sampleSellForApproximateBuyFromPlatypus( | ||||
|         bytes memory makerTokenData, | ||||
|         bytes memory takerTokenData, | ||||
|         uint256 sellAmount | ||||
|     ) | ||||
|         private | ||||
|         view | ||||
|         returns (uint256 buyAmount) | ||||
|     { | ||||
|         (address _pool, address[] memory _path ) = abi.decode(makerTokenData, (address, address[])); | ||||
|  | ||||
|         (bool success, bytes memory resultData) = address(this).staticcall(abi.encodeWithSelector( | ||||
|             this.sampleSellsFromPlatypus.selector, | ||||
|             _pool, | ||||
|             _path, | ||||
|             _toSingleValueArray(sellAmount) | ||||
|         )); | ||||
|         if(!success) { | ||||
|             return 0; | ||||
|         } | ||||
|         // solhint-disable-next-line indent | ||||
|         return abi.decode(resultData, (uint256[]))[0]; | ||||
|     } | ||||
| } | ||||
| @@ -22,43 +22,17 @@ pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
|  | ||||
| interface IUniswapV3QuoterV2 { | ||||
| interface IUniswapV3Quoter { | ||||
|     function factory() | ||||
|         external | ||||
|         view | ||||
|         returns (IUniswapV3Factory factory); | ||||
|  | ||||
|     // @notice Returns the amount out received for a given exact input swap without executing the swap | ||||
|     // @param path The path of the swap, i.e. each token pair and the pool fee | ||||
|     // @param amountIn The amount of the first token to swap | ||||
|     // @return amountOut The amount of the last token that would be received | ||||
|     // @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path | ||||
|     // @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path | ||||
|     // @return gasEstimate The estimate of the gas that the swap consumes | ||||
|     function quoteExactInput(bytes memory path, uint256 amountIn) | ||||
|         external | ||||
|         returns ( | ||||
|             uint256 amountOut, | ||||
|             uint160[] memory sqrtPriceX96AfterList, | ||||
|             uint32[] memory initializedTicksCrossedList, | ||||
|             uint256 gasEstimate | ||||
|         ); | ||||
|  | ||||
|     // @notice Returns the amount in required for a given exact output swap without executing the swap | ||||
|     // @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order | ||||
|     // @param amountOut The amount of the last token to receive | ||||
|     // @return amountIn The amount of first token required to be paid | ||||
|     // @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path | ||||
|     // @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path | ||||
|     // @return gasEstimate The estimate of the gas that the swap consumes | ||||
|         returns (uint256 amountOut); | ||||
|     function quoteExactOutput(bytes memory path, uint256 amountOut) | ||||
|         external | ||||
|         returns ( | ||||
|             uint256 amountIn, | ||||
|             uint160[] memory sqrtPriceX96AfterList, | ||||
|             uint32[] memory initializedTicksCrossedList, | ||||
|             uint256 gasEstimate | ||||
|         ); | ||||
|         returns (uint256 amountIn); | ||||
| } | ||||
|  | ||||
| interface IUniswapV3Factory { | ||||
| @@ -77,25 +51,23 @@ interface IUniswapV3Pool { | ||||
| contract UniswapV3Sampler | ||||
| { | ||||
|     /// @dev Gas limit for UniswapV3 calls. This is 100% a guess. | ||||
|     uint256 constant private QUOTE_GAS = 700e3; | ||||
|     uint256 constant private QUOTE_GAS = 600e3; | ||||
|  | ||||
|     /// @dev Sample sell quotes from UniswapV3. | ||||
|     /// @param quoter UniswapV3 Quoter contract. | ||||
|     /// @param path Token route. Should be takerToken -> makerToken | ||||
|     /// @param takerTokenAmounts Taker token sell amount for each sample. | ||||
|     /// @return uniswapPaths The encoded uniswap path for each sample. | ||||
|     /// @return uniswapGasUsed Estimated amount of gas used | ||||
|     /// @return makerTokenAmounts Maker amounts bought at each taker token | ||||
|     ///         amount. | ||||
|     function sampleSellsFromUniswapV3( | ||||
|         IUniswapV3QuoterV2 quoter, | ||||
|         IUniswapV3Quoter quoter, | ||||
|         IERC20TokenV06[] memory path, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         returns ( | ||||
|             bytes[] memory uniswapPaths, | ||||
|             uint256[] memory uniswapGasUsed, | ||||
|             uint256[] memory makerTokenAmounts | ||||
|         ) | ||||
|     { | ||||
| @@ -104,39 +76,31 @@ contract UniswapV3Sampler | ||||
|  | ||||
|         makerTokenAmounts = new uint256[](takerTokenAmounts.length); | ||||
|         uniswapPaths = new bytes[](takerTokenAmounts.length); | ||||
|         uniswapGasUsed = new uint256[](takerTokenAmounts.length); | ||||
|  | ||||
|         for (uint256 i = 0; i < takerTokenAmounts.length; ++i) { | ||||
|             // Pick the best result from all the paths. | ||||
|             bytes memory topUniswapPath; | ||||
|             uint256 topBuyAmount = 0; | ||||
|             for (uint256 j = 0; j < poolPaths.length; ++j) { | ||||
|                 bytes memory uniswapPath = _toUniswapPath(path, poolPaths[j]); | ||||
|                 try quoter.quoteExactInput | ||||
|                     { gas: QUOTE_GAS } | ||||
|                     (uniswapPath, takerTokenAmounts[i]) | ||||
|                     returns ( | ||||
|                         uint256 buyAmount, | ||||
|                         uint160[] memory, /* sqrtPriceX96AfterList */ | ||||
|                         uint32[] memory, /* initializedTicksCrossedList */ | ||||
|                         uint256 gasUsed | ||||
|                     ) | ||||
|                 try | ||||
|                     quoter.quoteExactInput | ||||
|                         { gas: QUOTE_GAS } | ||||
|                         (uniswapPath, takerTokenAmounts[i]) | ||||
|                         returns (uint256 buyAmount) | ||||
|                 { | ||||
|                     if (topBuyAmount <= buyAmount) { | ||||
|                         topBuyAmount = buyAmount; | ||||
|                         uniswapPaths[i] = uniswapPath; | ||||
|                         uniswapGasUsed[i] = gasUsed; | ||||
|                         topUniswapPath = uniswapPath; | ||||
|                     } | ||||
|                 } catch {} | ||||
|                 } catch { } | ||||
|             } | ||||
|             // Break early if we can't complete the sells. | ||||
|             // Break early if we can't complete the buys. | ||||
|             if (topBuyAmount == 0) { | ||||
|                 // HACK(kimpers): To avoid too many local variables, paths and gas used is set directly in the loop | ||||
|                 // then reset if no valid valid quote was found | ||||
|                 uniswapPaths[i] = ""; | ||||
|                 uniswapGasUsed[i] = 0; | ||||
|                 break; | ||||
|             } | ||||
|             makerTokenAmounts[i] = topBuyAmount; | ||||
|             uniswapPaths[i] = topUniswapPath; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -145,18 +109,16 @@ contract UniswapV3Sampler | ||||
|     /// @param path Token route. Should be takerToken -> makerToken. | ||||
|     /// @param makerTokenAmounts Maker token buy amount for each sample. | ||||
|     /// @return uniswapPaths The encoded uniswap path for each sample. | ||||
|     /// @return uniswapGasUsed Estimated amount of gas used | ||||
|     /// @return takerTokenAmounts Taker amounts sold at each maker token | ||||
|     ///         amount. | ||||
|     function sampleBuysFromUniswapV3( | ||||
|         IUniswapV3QuoterV2 quoter, | ||||
|         IUniswapV3Quoter quoter, | ||||
|         IERC20TokenV06[] memory path, | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         returns ( | ||||
|             bytes[] memory uniswapPaths, | ||||
|             uint256[] memory uniswapGasUsed, | ||||
|             uint256[] memory takerTokenAmounts | ||||
|         ) | ||||
|     { | ||||
| @@ -166,10 +128,10 @@ contract UniswapV3Sampler | ||||
|  | ||||
|         takerTokenAmounts = new uint256[](makerTokenAmounts.length); | ||||
|         uniswapPaths = new bytes[](makerTokenAmounts.length); | ||||
|         uniswapGasUsed = new uint256[](makerTokenAmounts.length); | ||||
|  | ||||
|         for (uint256 i = 0; i < makerTokenAmounts.length; ++i) { | ||||
|             // Pick the best result from all the paths. | ||||
|             bytes memory topUniswapPath; | ||||
|             uint256 topSellAmount = 0; | ||||
|             for (uint256 j = 0; j < poolPaths.length; ++j) { | ||||
|                 // quoter requires path to be reversed for buys. | ||||
| @@ -181,30 +143,21 @@ contract UniswapV3Sampler | ||||
|                     quoter.quoteExactOutput | ||||
|                         { gas: QUOTE_GAS } | ||||
|                         (uniswapPath, makerTokenAmounts[i]) | ||||
|                         returns ( | ||||
|                             uint256 sellAmount, | ||||
|                             uint160[] memory, /* sqrtPriceX96AfterList */ | ||||
|                             uint32[] memory, /* initializedTicksCrossedList */ | ||||
|                             uint256 gasUsed | ||||
|                         ) | ||||
|                         returns (uint256 sellAmount) | ||||
|                 { | ||||
|                     if (topSellAmount == 0 || topSellAmount >= sellAmount) { | ||||
|                         topSellAmount = sellAmount; | ||||
|                         // But the output path should still be encoded for sells. | ||||
|                         uniswapPaths[i] = _toUniswapPath(path, poolPaths[j]); | ||||
|                         uniswapGasUsed[i] = gasUsed; | ||||
|                         topUniswapPath = _toUniswapPath(path, poolPaths[j]); | ||||
|                     } | ||||
|                 } catch {} | ||||
|             } | ||||
|             // Break early if we can't complete the buys. | ||||
|             if (topSellAmount == 0) { | ||||
|                 // HACK(kimpers): To avoid too many local variables, paths and gas used is set directly in the loop | ||||
|                 // then reset if no valid valid quote was found | ||||
|                 uniswapPaths[i] = ""; | ||||
|                 uniswapGasUsed[i] = 0; | ||||
|                 break; | ||||
|             } | ||||
|             takerTokenAmounts[i] = topSellAmount; | ||||
|             uniswapPaths[i] = topUniswapPath; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -283,7 +236,6 @@ contract UniswapV3Sampler | ||||
|  | ||||
|     function _reverseTokenPath(IERC20TokenV06[] memory tokenPath) | ||||
|         private | ||||
|         pure | ||||
|         returns (IERC20TokenV06[] memory reversed) | ||||
|     { | ||||
|         reversed = new IERC20TokenV06[](tokenPath.length); | ||||
| @@ -294,7 +246,6 @@ contract UniswapV3Sampler | ||||
|  | ||||
|     function _reversePoolPath(IUniswapV3Pool[] memory poolPath) | ||||
|         private | ||||
|         pure | ||||
|         returns (IUniswapV3Pool[] memory reversed) | ||||
|     { | ||||
|         reversed = new IUniswapV3Pool[](poolPath.length); | ||||
|   | ||||
| @@ -1,134 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import './ApproximateBuys.sol'; | ||||
| import './SamplerUtils.sol'; | ||||
|  | ||||
| struct VeloRoute { | ||||
|     address from; | ||||
|     address to; | ||||
|     bool stable; | ||||
| } | ||||
|  | ||||
| interface IVelodromeRouter { | ||||
|     function getAmountOut( | ||||
|         uint256 amountIn, | ||||
|         address tokenIn, | ||||
|         address tokenOut | ||||
|     ) external view returns (uint256 amount, bool stable); | ||||
|  | ||||
|     function getAmountsOut(uint256 amountIn, VeloRoute[] calldata routes) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256[] memory amounts); | ||||
| } | ||||
|  | ||||
| contract VelodromeSampler is SamplerUtils, ApproximateBuys { | ||||
|     /// @dev Sample sell quotes from Velodrome | ||||
|     /// @param router Address of Velodrome router. | ||||
|     /// @param takerToken Address of the taker token (what to sell). | ||||
|     /// @param makerToken Address of the maker token (what to buy). | ||||
|     /// @param takerTokenAmounts Taker token sell amount for each sample (sorted in ascending order). | ||||
|     /// @return stable Whether the pool is a stable pool (vs volatile). | ||||
|     /// @return makerTokenAmounts Maker amounts bought at each taker token amount. | ||||
|     function sampleSellsFromVelodrome( | ||||
|         IVelodromeRouter router, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) public view returns (bool stable, uint256[] memory makerTokenAmounts) { | ||||
|         _assertValidPair(makerToken, takerToken); | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
|  | ||||
|         // Sampling should not mix stable and volatile pools. | ||||
|         // Find the most liquid pool based on max(takerTokenAmounts) and stick with it. | ||||
|         stable = _isMostLiquidPoolStablePool(router, takerToken, makerToken, takerTokenAmounts); | ||||
|         VeloRoute[] memory routes = new VeloRoute[](1); | ||||
|         routes[0] = VeloRoute({ from: takerToken, to: makerToken, stable: stable }); | ||||
|  | ||||
|         for (uint256 i = 0; i < numSamples; i++) { | ||||
|             makerTokenAmounts[i] = router.getAmountsOut(takerTokenAmounts[i], routes)[1]; | ||||
|             // Break early if there are 0 amounts | ||||
|             if (makerTokenAmounts[i] == 0) { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Sample buy quotes from Velodrome. | ||||
|     /// @param router Address of Velodrome router. | ||||
|     /// @param takerToken Address of the taker token (what to sell). | ||||
|     /// @param makerToken Address of the maker token (what to buy). | ||||
|     /// @param makerTokenAmounts Maker token buy amount for each sample. | ||||
|     /// @return stable Whether the pool is a stable pool (vs volatile). | ||||
|     /// @return takerTokenAmounts Taker amounts sold at each maker token amount. | ||||
|     function sampleBuysFromVelodrome( | ||||
|         IVelodromeRouter router, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) public view returns (bool stable, uint256[] memory takerTokenAmounts) { | ||||
|         _assertValidPair(makerToken, takerToken); | ||||
|  | ||||
|         // Sampling should not mix stable and volatile pools. | ||||
|         // Find the most liquid pool based on the reverse swap (maker -> taker) and stick with it. | ||||
|         stable = _isMostLiquidPoolStablePool(router, makerToken, takerToken, makerTokenAmounts); | ||||
|  | ||||
|         takerTokenAmounts = _sampleApproximateBuys( | ||||
|             ApproximateBuyQuoteOpts({ | ||||
|                 takerTokenData: abi.encode(router, VeloRoute({ from: takerToken, to: makerToken, stable: stable })), | ||||
|                 makerTokenData: abi.encode(router, VeloRoute({ from: makerToken, to: takerToken, stable: stable })), | ||||
|                 getSellQuoteCallback: _sampleSellForApproximateBuyFromVelodrome | ||||
|             }), | ||||
|             makerTokenAmounts | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function _sampleSellForApproximateBuyFromVelodrome( | ||||
|         bytes memory takerTokenData, | ||||
|         bytes memory, /* makerTokenData */ | ||||
|         uint256 sellAmount | ||||
|     ) internal view returns (uint256) { | ||||
|         (IVelodromeRouter router, VeloRoute memory route) = abi.decode(takerTokenData, (IVelodromeRouter, VeloRoute)); | ||||
|  | ||||
|         VeloRoute[] memory routes = new VeloRoute[](1); | ||||
|         routes[0] = route; | ||||
|         return router.getAmountsOut(sellAmount, routes)[1]; | ||||
|     } | ||||
|  | ||||
|     /// @dev Returns whether the most liquid pool is a stable pool. | ||||
|     /// @param router Address of Velodrome router. | ||||
|     /// @param takerToken Address of the taker token (what to sell). | ||||
|     /// @param makerToken Address of the maker token (what to buy). | ||||
|     /// @param takerTokenAmounts Taker token buy amount for each sample (sorted in ascending order) | ||||
|     /// @return stable Whether the pool is a stable pool (vs volatile). | ||||
|     function _isMostLiquidPoolStablePool( | ||||
|         IVelodromeRouter router, | ||||
|         address takerToken, | ||||
|         address makerToken, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) internal view returns (bool stable) { | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         (, stable) = router.getAmountOut(takerTokenAmounts[numSamples - 1], takerToken, makerToken); | ||||
|     } | ||||
| } | ||||
| @@ -1,54 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| /// @dev Minimal Balancer V2 Vault interface | ||||
| ///      for documentation refer to https://github.com/balancer-labs/balancer-core-v2/blob/master/contracts/vault/interfaces/IVault.sol | ||||
| interface IBalancerV2Vault { | ||||
|     enum SwapKind { GIVEN_IN, GIVEN_OUT } | ||||
|  | ||||
|     struct BatchSwapStep { | ||||
|         bytes32 poolId; | ||||
|         uint256 assetInIndex; | ||||
|         uint256 assetOutIndex; | ||||
|         uint256 amount; | ||||
|         bytes userData; | ||||
|     } | ||||
|  | ||||
|     struct FundManagement { | ||||
|         address sender; | ||||
|         bool fromInternalBalance; | ||||
|         address payable recipient; | ||||
|         bool toInternalBalance; | ||||
|     } | ||||
|  | ||||
|     struct BalancerV2PoolInfo { | ||||
|         bytes32 poolId; | ||||
|         address vault; | ||||
|     } | ||||
|  | ||||
|     function queryBatchSwap( | ||||
|         SwapKind kind, | ||||
|         BatchSwapStep[] calldata swaps, | ||||
|         address[] calldata assets, | ||||
|         FundManagement calldata funds | ||||
|     ) external returns (int256[] memory assetDeltas); | ||||
| } | ||||
| @@ -1,43 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2022 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| interface IBancorV3 { | ||||
|  | ||||
|     /** | ||||
|      * @dev returns the output amount when trading by providing the source amount | ||||
|      */ | ||||
|     function tradeOutputBySourceAmount( | ||||
|         address sourceToken, | ||||
|         address targetToken, | ||||
|         uint256 sourceAmount | ||||
|     ) external view returns (uint256); | ||||
|  | ||||
|     /** | ||||
|      * @dev returns the input amount when trading by providing the target amount | ||||
|      */ | ||||
|     function tradeInputByTargetAmount( | ||||
|         address sourceToken, | ||||
|         address targetToken, | ||||
|         uint256 targetAmount | ||||
|     ) external view returns (uint256); | ||||
|  | ||||
| } | ||||
| @@ -1,23 +0,0 @@ | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| interface IGMX { | ||||
|     function getMaxAmountIn(IVault _vault, address _tokenIn, address _tokenOut) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256); | ||||
|  | ||||
|     function getAmountOut(IVault _vault, address _tokenIn, address _tokenOut, uint256 _amountIn) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256, uint256); | ||||
| } | ||||
|  | ||||
| interface IVault { | ||||
|     function getFeeBasisPoints(address _token, uint256 _usdgDelta, uint256 _feeBasisPoints, uint256 _taxBasisPoints, bool _increment) external view returns (uint256); | ||||
|     function stableSwapFeeBasisPoints() external view returns (uint256); | ||||
|     function stableTokens(address _token) external view returns (bool); | ||||
|     function tokenDecimals(address _token) external view returns (uint256); | ||||
|     function getMaxPrice(address _token) external view returns (uint256); | ||||
|     function getMinPrice(address _token) external view returns (uint256); | ||||
| } | ||||
| @@ -0,0 +1,96 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.6; | ||||
|  | ||||
| // Keepin everything together | ||||
| interface IKyberNetwork { | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| interface IKyberNetworkProxy { | ||||
|  | ||||
|     function getExpectedRateAfterFee( | ||||
|         address src, | ||||
|         address dest, | ||||
|         uint256 srcQty, | ||||
|         uint256 platformFeeBps, | ||||
|         bytes calldata hint | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 expectedRate); | ||||
| } | ||||
|  | ||||
| interface IKyberHintHandler { | ||||
|  | ||||
|     enum TradeType {BestOfAll, MaskIn, MaskOut, Split} | ||||
|  | ||||
|     enum ProcessWithRate {NotRequired, Required} | ||||
|  | ||||
|     function getTradingReserves( | ||||
|         address tokenSrc, | ||||
|         address tokenDest, | ||||
|         bool isTokenToToken, | ||||
|         bytes calldata hint | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             bytes32[] memory reserveIds, | ||||
|             uint256[] memory splitValuesBps, | ||||
|             ProcessWithRate processWithRate | ||||
|         ); | ||||
|  | ||||
|     function buildTokenToEthHint( | ||||
|         address tokenSrc, | ||||
|         TradeType tokenToEthType, | ||||
|         bytes32[] calldata tokenToEthReserveIds, | ||||
|         uint256[] calldata tokenToEthSplits | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (bytes memory hint); | ||||
|  | ||||
|     function buildEthToTokenHint( | ||||
|         address tokenDest, | ||||
|         TradeType ethToTokenType, | ||||
|         bytes32[] calldata ethToTokenReserveIds, | ||||
|         uint256[] calldata ethToTokenSplits | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (bytes memory hint); | ||||
|  | ||||
|     function buildTokenToTokenHint( | ||||
|         address tokenSrc, | ||||
|         TradeType tokenToEthType, | ||||
|         bytes32[] calldata tokenToEthReserveIds, | ||||
|         uint256[] calldata tokenToEthSplits, | ||||
|         address tokenDest, | ||||
|         TradeType ethToTokenType, | ||||
|         bytes32[] calldata ethToTokenReserveIds, | ||||
|         uint256[] calldata ethToTokenSplits | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (bytes memory hint); | ||||
| } | ||||
| @@ -1,11 +0,0 @@ | ||||
| pragma solidity ^0.6; | ||||
|  | ||||
| interface IPlatypus { | ||||
|     function quotePotentialSwap( | ||||
|         address fromToken, | ||||
|         address toToken, | ||||
|         uint256 fromAmount | ||||
|     ) external view returns (uint256 potentialOutcome, uint256 haircut); | ||||
|  | ||||
|     function assetOf(address token) external view returns (address); | ||||
| } | ||||
| @@ -0,0 +1,39 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
|  | ||||
| contract DummyLiquidityProvider | ||||
| { | ||||
|     /// @dev Quotes the amount of `makerToken` that would be obtained by | ||||
|     ///      selling `sellAmount` of `takerToken`. | ||||
|     /// @param sellAmount Amount of `takerToken` to sell. | ||||
|     /// @return makerTokenAmount Amount of `makerToken` that would be obtained. | ||||
|     function getSellQuote( | ||||
|         address, /* takerToken */ | ||||
|         address, /* makerToken */ | ||||
|         uint256 sellAmount | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 makerTokenAmount) | ||||
|     { | ||||
|         makerTokenAmount = sellAmount - 1; | ||||
|     } | ||||
|  | ||||
|     /// @dev Quotes the amount of `takerToken` that would need to be sold in | ||||
|     ///      order to obtain `buyAmount` of `makerToken`. | ||||
|     /// @param buyAmount Amount of `makerToken` to buy. | ||||
|     /// @return takerTokenAmount Amount of `takerToken` that would need to be sold. | ||||
|     function getBuyQuote( | ||||
|         address, /* takerToken */ | ||||
|         address, /* makerToken */ | ||||
|         uint256 buyAmount | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 takerTokenAmount) | ||||
|     { | ||||
|         takerTokenAmount = buyAmount + 1; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										455
									
								
								packages/asset-swapper/contracts/test/TestERC20BridgeSampler.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										455
									
								
								packages/asset-swapper/contracts/test/TestERC20BridgeSampler.sol
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,455 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
| pragma solidity ^0.6; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../src/ERC20BridgeSampler.sol"; | ||||
| import "../src/interfaces/IKyberNetwork.sol"; | ||||
| import "../src/interfaces/IUniswapV2Router01.sol"; | ||||
|  | ||||
|  | ||||
| library LibDeterministicQuotes { | ||||
|  | ||||
|     address private constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; | ||||
|     uint256 private constant RATE_DENOMINATOR = 1 ether; | ||||
|     uint256 private constant MIN_RATE = RATE_DENOMINATOR / 100; | ||||
|     uint256 private constant MAX_RATE = 100 * RATE_DENOMINATOR; | ||||
|     uint8 private constant MIN_DECIMALS = 4; | ||||
|     uint8 private constant MAX_DECIMALS = 20; | ||||
|  | ||||
|     function getDeterministicSellQuote( | ||||
|         bytes32 salt, | ||||
|         address sellToken, | ||||
|         address buyToken, | ||||
|         uint256 sellAmount | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (uint256 buyAmount) | ||||
|     { | ||||
|         uint256 sellBase = uint256(10) ** getDeterministicTokenDecimals(sellToken); | ||||
|         uint256 buyBase = uint256(10) ** getDeterministicTokenDecimals(buyToken); | ||||
|         uint256 rate = getDeterministicRate(salt, sellToken, buyToken); | ||||
|         return sellAmount * rate * buyBase / sellBase / RATE_DENOMINATOR; | ||||
|     } | ||||
|  | ||||
|     function getDeterministicBuyQuote( | ||||
|         bytes32 salt, | ||||
|         address sellToken, | ||||
|         address buyToken, | ||||
|         uint256 buyAmount | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (uint256 sellAmount) | ||||
|     { | ||||
|         uint256 sellBase = uint256(10) ** getDeterministicTokenDecimals(sellToken); | ||||
|         uint256 buyBase = uint256(10) ** getDeterministicTokenDecimals(buyToken); | ||||
|         uint256 rate = getDeterministicRate(salt, sellToken, buyToken); | ||||
|         return buyAmount * RATE_DENOMINATOR * sellBase / rate / buyBase; | ||||
|     } | ||||
|  | ||||
|     function getDeterministicTokenDecimals(address token) | ||||
|         internal | ||||
|         pure | ||||
|         returns (uint8 decimals) | ||||
|     { | ||||
|         if (token == WETH_ADDRESS) { | ||||
|             return 18; | ||||
|         } | ||||
|         bytes32 seed = keccak256(abi.encodePacked(token)); | ||||
|         return uint8(uint256(seed) % (MAX_DECIMALS - MIN_DECIMALS)) + MIN_DECIMALS; | ||||
|     } | ||||
|  | ||||
|     function getDeterministicRate(bytes32 salt, address sellToken, address buyToken) | ||||
|         internal | ||||
|         pure | ||||
|         returns (uint256 rate) | ||||
|     { | ||||
|         bytes32 seed = keccak256(abi.encodePacked(salt, sellToken, buyToken)); | ||||
|         return uint256(seed) % (MAX_RATE - MIN_RATE) + MIN_RATE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| contract TestDeploymentConstants { | ||||
|  | ||||
|     // solhint-disable separate-by-one-line-in-contract | ||||
|  | ||||
|     // Mainnet addresses /////////////////////////////////////////////////////// | ||||
|     /// @dev Mainnet address of the WETH contract. | ||||
|     address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; | ||||
|  | ||||
|     /// @dev Overridable way to get the WETH address. | ||||
|     /// @return wethAddress The WETH address. | ||||
|     function _getWethAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address wethAddress) | ||||
|     { | ||||
|         return WETH_ADDRESS; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| contract FailTrigger { | ||||
|  | ||||
|     // Give this address a balance to force operations to fail. | ||||
|     address payable constant public FAILURE_ADDRESS = 0xe9dB8717BC5DFB20aaf538b4a5a02B7791FF430C; | ||||
|  | ||||
|     // Funds `FAILURE_ADDRESS`. | ||||
|     function enableFailTrigger() external payable { | ||||
|         FAILURE_ADDRESS.transfer(msg.value); | ||||
|     } | ||||
|  | ||||
|     function _revertIfShouldFail() internal view { | ||||
|         if (FAILURE_ADDRESS.balance != 0) { | ||||
|             revert("FAIL_TRIGGERED"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| contract TestERC20BridgeSamplerUniswapExchange is | ||||
|     IUniswapExchangeQuotes, | ||||
|     TestDeploymentConstants, | ||||
|     FailTrigger | ||||
| { | ||||
|     bytes32 constant private BASE_SALT = 0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab; | ||||
|  | ||||
|     address public tokenAddress; | ||||
|     bytes32 public salt; | ||||
|  | ||||
|     constructor(address _tokenAddress) public { | ||||
|         tokenAddress = _tokenAddress; | ||||
|         salt = keccak256(abi.encodePacked(BASE_SALT, _tokenAddress)); | ||||
|     } | ||||
|  | ||||
|     // Deterministic `IUniswapExchangeQuotes.getEthToTokenInputPrice()`. | ||||
|     function getEthToTokenInputPrice( | ||||
|         uint256 ethSold | ||||
|     ) | ||||
|         override | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 tokensBought) | ||||
|     { | ||||
|         _revertIfShouldFail(); | ||||
|         return LibDeterministicQuotes.getDeterministicSellQuote( | ||||
|             salt, | ||||
|             tokenAddress, | ||||
|             _getWethAddress(), | ||||
|             ethSold | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     // Deterministic `IUniswapExchangeQuotes.getEthToTokenOutputPrice()`. | ||||
|     function getEthToTokenOutputPrice( | ||||
|         uint256 tokensBought | ||||
|     ) | ||||
|         override | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 ethSold) | ||||
|     { | ||||
|         _revertIfShouldFail(); | ||||
|         return LibDeterministicQuotes.getDeterministicBuyQuote( | ||||
|             salt, | ||||
|             _getWethAddress(), | ||||
|             tokenAddress, | ||||
|             tokensBought | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     // Deterministic `IUniswapExchangeQuotes.getTokenToEthInputPrice()`. | ||||
|     function getTokenToEthInputPrice( | ||||
|         uint256 tokensSold | ||||
|     ) | ||||
|         override | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 ethBought) | ||||
|     { | ||||
|         _revertIfShouldFail(); | ||||
|         return LibDeterministicQuotes.getDeterministicSellQuote( | ||||
|             salt, | ||||
|             tokenAddress, | ||||
|             _getWethAddress(), | ||||
|             tokensSold | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     // Deterministic `IUniswapExchangeQuotes.getTokenToEthOutputPrice()`. | ||||
|     function getTokenToEthOutputPrice( | ||||
|         uint256 ethBought | ||||
|     ) | ||||
|         override | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 tokensSold) | ||||
|     { | ||||
|         _revertIfShouldFail(); | ||||
|         return LibDeterministicQuotes.getDeterministicBuyQuote( | ||||
|             salt, | ||||
|             _getWethAddress(), | ||||
|             tokenAddress, | ||||
|             ethBought | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| contract TestERC20BridgeSamplerUniswapV2Router01 is | ||||
|     IUniswapV2Router01, | ||||
|     TestDeploymentConstants, | ||||
|     FailTrigger | ||||
| { | ||||
|     bytes32 constant private SALT = 0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1; | ||||
|  | ||||
|     // Deterministic `IUniswapV2Router01.getAmountsOut()`. | ||||
|     function getAmountsOut(uint256 amountIn, address[] calldata path) | ||||
|         override | ||||
|         external | ||||
|         view | ||||
|         returns (uint256[] memory amounts) | ||||
|     { | ||||
|         require(path.length >= 2, "PATH_TOO_SHORT"); | ||||
|         _revertIfShouldFail(); | ||||
|         amounts = new uint256[](path.length); | ||||
|         amounts[0] = amountIn; | ||||
|         for (uint256 i = 0; i < path.length - 1; ++i) { | ||||
|             amounts[i + 1] = LibDeterministicQuotes.getDeterministicSellQuote( | ||||
|                 SALT, | ||||
|                 path[i], | ||||
|                 path[i + 1], | ||||
|                 amounts[i] | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Deterministic `IUniswapV2Router01.getAmountsInt()`. | ||||
|     function getAmountsIn(uint256 amountOut, address[] calldata path) | ||||
|         override | ||||
|         external | ||||
|         view | ||||
|         returns (uint256[] memory amounts) | ||||
|     { | ||||
|         require(path.length >= 2, "PATH_TOO_SHORT"); | ||||
|         _revertIfShouldFail(); | ||||
|         amounts = new uint256[](path.length); | ||||
|         amounts[path.length - 1] = amountOut; | ||||
|         for (uint256 i = path.length - 1; i > 0; --i) { | ||||
|             amounts[i - 1] = LibDeterministicQuotes.getDeterministicBuyQuote( | ||||
|                 SALT, | ||||
|                 path[i - 1], | ||||
|                 path[i], | ||||
|                 amounts[i] | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| // solhint-disable space-after-comma | ||||
| contract TestERC20BridgeSamplerKyberNetwork is | ||||
|     TestDeploymentConstants, | ||||
|     FailTrigger | ||||
| { | ||||
|     bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7; | ||||
|     address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; | ||||
|  | ||||
|     enum TradeType {BestOfAll, MaskIn, MaskOut, Split} | ||||
|     enum ProcessWithRate {NotRequired, Required} | ||||
|  | ||||
|     // IKyberHintHandler | ||||
|     function buildTokenToEthHint( | ||||
|         address tokenSrc, | ||||
|         TradeType /* tokenToEthType */, | ||||
|         bytes32[] calldata /* tokenToEthReserveIds */, | ||||
|         uint256[] calldata /* tokenToEthSplits */ | ||||
|     ) external view returns (bytes memory hint) | ||||
|     { | ||||
|         return abi.encode(tokenSrc); | ||||
|     } | ||||
|  | ||||
|     function buildEthToTokenHint( | ||||
|         address tokenDest, | ||||
|         TradeType /* ethToTokenType */, | ||||
|         bytes32[] calldata /* ethToTokenReserveIds */, | ||||
|         uint256[] calldata /* ethToTokenSplits */ | ||||
|     ) external view returns (bytes memory hint) | ||||
|     { | ||||
|         return abi.encode(tokenDest); | ||||
|     } | ||||
|  | ||||
|     // IKyberHintHandler | ||||
|     function buildTokenToTokenHint( | ||||
|         address tokenSrc, | ||||
|         TradeType /* tokenToEthType */, | ||||
|         bytes32[] calldata /* tokenToEthReserveIds */, | ||||
|         uint256[] calldata /* tokenToEthSplits */, | ||||
|         address /* tokenDest  */, | ||||
|         TradeType /* EthToTokenType */, | ||||
|         bytes32[] calldata /* EthToTokenReserveIds */, | ||||
|         uint256[] calldata /* EthToTokenSplits */ | ||||
|     ) external view returns (bytes memory hint) | ||||
|     { | ||||
|         return abi.encode(tokenSrc); | ||||
|     } | ||||
|  | ||||
|     // IKyberHintHandler | ||||
|     function getTradingReserves( | ||||
|         address tokenSrc, | ||||
|         address tokenDest, | ||||
|         bool isTokenToToken, | ||||
|         bytes calldata hint | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             bytes32[] memory reserveIds, | ||||
|             uint256[] memory splitValuesBps, | ||||
|             ProcessWithRate processWithRate | ||||
|         ) | ||||
|     { | ||||
|         reserveIds = new bytes32[](1); | ||||
|         reserveIds[0] = bytes32(uint256(1)); | ||||
|         splitValuesBps = new uint256[](0); | ||||
|         processWithRate = ProcessWithRate.NotRequired; | ||||
|     } | ||||
|  | ||||
|     // Deterministic `IKyberNetworkProxy.getExpectedRateAfterFee()`. | ||||
|     function getExpectedRateAfterFee( | ||||
|         address fromToken, | ||||
|         address toToken, | ||||
|         uint256 /* srcQty */, | ||||
|         uint256 /* fee */, | ||||
|         bytes calldata /* hint */ | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns | ||||
|         (uint256 expectedRate) | ||||
|     { | ||||
|         _revertIfShouldFail(); | ||||
|         fromToken = fromToken == ETH_ADDRESS ? _getWethAddress() : fromToken; | ||||
|         toToken = toToken == ETH_ADDRESS ? _getWethAddress() : toToken; | ||||
|         expectedRate = LibDeterministicQuotes.getDeterministicRate( | ||||
|             SALT, | ||||
|             fromToken, | ||||
|             toToken | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     // Deterministic `IKyberNetworkProxy.getExpectedRate()`. | ||||
|     function getExpectedRate( | ||||
|         address fromToken, | ||||
|         address toToken, | ||||
|         uint256 | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 expectedRate, uint256) | ||||
|     { | ||||
|         _revertIfShouldFail(); | ||||
|         fromToken = fromToken == ETH_ADDRESS ? _getWethAddress() : fromToken; | ||||
|         toToken = toToken == ETH_ADDRESS ? _getWethAddress() : toToken; | ||||
|         expectedRate = LibDeterministicQuotes.getDeterministicRate( | ||||
|             SALT, | ||||
|             fromToken, | ||||
|             toToken | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| contract TestERC20BridgeSamplerUniswapExchangeFactory is | ||||
|     IUniswapExchangeFactory | ||||
| { | ||||
|     mapping (address => IUniswapExchangeQuotes) private _exchangesByToken; | ||||
|  | ||||
|     // Creates Uniswap exchange contracts for tokens. | ||||
|     function createTokenExchanges(address[] calldata tokenAddresses) | ||||
|         external | ||||
|     { | ||||
|         for (uint256 i = 0; i < tokenAddresses.length; i++) { | ||||
|             address tokenAddress = tokenAddresses[i]; | ||||
|             _exchangesByToken[tokenAddress] = | ||||
|                 new TestERC20BridgeSamplerUniswapExchange(tokenAddress); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // `IUniswapExchangeFactory.getExchange()`. | ||||
|     function getExchange(address tokenAddress) | ||||
|         override | ||||
|         external | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return address(_exchangesByToken[tokenAddress]); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| contract TestERC20BridgeSampler is | ||||
|     ERC20BridgeSampler, | ||||
|     FailTrigger | ||||
| { | ||||
|     TestERC20BridgeSamplerUniswapExchangeFactory public uniswap; | ||||
|     TestERC20BridgeSamplerUniswapV2Router01 public uniswapV2Router; | ||||
|     TestERC20BridgeSamplerKyberNetwork public kyber; | ||||
|  | ||||
|     uint8 private constant MAX_ORDER_STATUS = uint8(IExchange.OrderStatus.CANCELLED) + 1; | ||||
|  | ||||
|     constructor() public ERC20BridgeSampler() { | ||||
|         uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory(); | ||||
|         uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01(); | ||||
|         kyber = new TestERC20BridgeSamplerKyberNetwork(); | ||||
|     } | ||||
|  | ||||
|     // Creates Uniswap exchange contracts for tokens. | ||||
|     function createTokenExchanges(address[] calldata tokenAddresses) | ||||
|         external | ||||
|     { | ||||
|         uniswap.createTokenExchanges(tokenAddresses); | ||||
|     } | ||||
|  | ||||
|     // Overridden to return deterministic states. | ||||
|     function getLimitOrderFillableTakerAmount( | ||||
|         IExchange.LimitOrder memory order, | ||||
|         IExchange.Signature memory, | ||||
|         IExchange | ||||
|     ) | ||||
|         override | ||||
|         public | ||||
|         view | ||||
|         returns (uint256 fillableTakerAmount) | ||||
|     { | ||||
|         return uint256(keccak256(abi.encode(order.salt))) % order.takerAmount; | ||||
|     } | ||||
|  | ||||
|     // Overriden to return deterministic decimals. | ||||
|     function _getTokenDecimals(address tokenAddress) | ||||
|         override | ||||
|         internal | ||||
|         view | ||||
|         returns (uint8 decimals) | ||||
|     { | ||||
|         return LibDeterministicQuotes.getDeterministicTokenDecimals(tokenAddress); | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/asset-swapper", | ||||
|     "version": "16.62.0", | ||||
|     "version": "16.49.9", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -34,13 +34,12 @@ | ||||
|         "contracts:gen": "contracts-gen generate", | ||||
|         "contracts:copy": "contracts-gen copy", | ||||
|         "publish:private": "yarn build && gitpkg publish", | ||||
|         "sampler-size": "jq .compilerOutput.evm.deployedBytecode.object  -- test/generated-artifacts/ERC20BridgeSampler.json | echo $(( $(wc -c) / 2 - 1 ))", | ||||
|         "list:deps": "yarn lerna list -l" | ||||
|         "sampler-size": "jq .compilerOutput.evm.deployedBytecode.object  -- test/generated-artifacts/ERC20BridgeSampler.json | echo $(( $(wc -c) / 2 - 1 ))" | ||||
|     }, | ||||
|     "config": { | ||||
|         "publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker", | ||||
|         "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", | ||||
|         "abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2BatchSampler|BalancerV2Common|BalancerV2Sampler|BancorSampler|BancorV3Sampler|CompoundSampler|CurveSampler|DODOSampler|DODOV2Sampler|ERC20BridgeSampler|FakeTaker|GMXSampler|IBalancer|IBalancerV2Vault|IBancor|IBancorV3|ICurve|IGMX|IMStable|IMooniswap|IMultiBridge|IPlatypus|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|NativeOrderSampler|PlatypusSampler|SamplerUtils|ShellSampler|SmoothySampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler|VelodromeSampler).json", | ||||
|         "abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2Sampler|BancorSampler|CompoundSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|FakeTaker|IBalancer|IBancor|ICurve|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|KyberSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SmoothySampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler).json", | ||||
|         "postpublish": { | ||||
|             "assets": [] | ||||
|         } | ||||
| @@ -59,22 +58,22 @@ | ||||
|         "registry": "git@github.com:0xProject/gitpkg-registry.git" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/assert": "^3.0.34", | ||||
|         "@0x/base-contract": "^6.5.0", | ||||
|         "@0x/contract-addresses": "^6.16.0", | ||||
|         "@0x/contract-wrappers": "^13.20.4", | ||||
|         "@0x/contracts-erc20": "^3.3.32", | ||||
|         "@0x/contracts-zero-ex": "^0.35.0", | ||||
|         "@0x/dev-utils": "^4.2.14", | ||||
|         "@0x/json-schemas": "^6.4.4", | ||||
|         "@0x/neon-router": "^0.3.5", | ||||
|         "@0x/protocol-utils": "^11.15.0", | ||||
|         "@0x/assert": "^3.0.31", | ||||
|         "@0x/base-contract": "^6.4.5", | ||||
|         "@0x/contract-addresses": "^6.11.0", | ||||
|         "@0x/contract-wrappers": "^13.19.0", | ||||
|         "@0x/contracts-erc20": "^3.3.26", | ||||
|         "@0x/contracts-zero-ex": "^0.31.0", | ||||
|         "@0x/dev-utils": "^4.2.11", | ||||
|         "@0x/json-schemas": "^6.4.1", | ||||
|         "@0x/neon-router": "^0.3.3", | ||||
|         "@0x/protocol-utils": "^1.11.0", | ||||
|         "@0x/quote-server": "^6.0.6", | ||||
|         "@0x/types": "^3.3.6", | ||||
|         "@0x/typescript-typings": "^5.3.1", | ||||
|         "@0x/utils": "^6.5.3", | ||||
|         "@0x/web3-wrapper": "^7.6.5", | ||||
|         "@balancer-labs/sdk": "0.1.6", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|         "@0x/utils": "^6.5.0", | ||||
|         "@0x/web3-wrapper": "^7.6.2", | ||||
|         "@balancer-labs/sor": "0.3.2", | ||||
|         "@bancor/sdk": "0.2.9", | ||||
|         "@ethersproject/abi": "^5.0.1", | ||||
|         "@ethersproject/address": "^5.0.1", | ||||
| @@ -83,10 +82,9 @@ | ||||
|         "@ethersproject/strings": "^5.0.10", | ||||
|         "axios": "^0.21.1", | ||||
|         "axios-mock-adapter": "^1.19.0", | ||||
|         "balancer-labs-sor-v1": "npm:@balancer-labs/sor@0.3.2", | ||||
|         "cream-sor": "^0.3.3", | ||||
|         "decimal.js": "^10.2.0", | ||||
|         "ethereum-types": "^3.7.0", | ||||
|         "ethereum-types": "^3.6.0", | ||||
|         "ethereumjs-util": "^7.0.10", | ||||
|         "fast-abi": "^0.0.4", | ||||
|         "graphql": "^15.4.0", | ||||
| @@ -95,19 +93,20 @@ | ||||
|         "lodash": "^4.17.11" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.8.0", | ||||
|         "@0x/abi-gen": "^5.7.2", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.19", | ||||
|         "@0x/contracts-exchange": "^3.2.38", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.37", | ||||
|         "@0x/contracts-gen": "^2.0.46", | ||||
|         "@0x/contracts-test-utils": "^5.4.23", | ||||
|         "@0x/contracts-utils": "^4.8.13", | ||||
|         "@0x/contracts-gen": "^2.0.43", | ||||
|         "@0x/contracts-test-utils": "^5.4.17", | ||||
|         "@0x/contracts-utils": "^4.8.7", | ||||
|         "@0x/mesh-rpc-client": "^9.4.2", | ||||
|         "@0x/sol-compiler": "^4.8.1", | ||||
|         "@0x/subproviders": "^6.6.5", | ||||
|         "@0x/migrations": "^8.1.15", | ||||
|         "@0x/sol-compiler": "^4.7.8", | ||||
|         "@0x/subproviders": "^6.6.2", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.4", | ||||
|         "@0x/types": "^3.3.6", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "@types/mocha": "^5.2.7", | ||||
|         "@types/node": "12.12.54", | ||||
| @@ -124,7 +123,7 @@ | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typemoq": "^2.1.0", | ||||
|         "typescript": "4.6.3" | ||||
|         "typescript": "4.2.2" | ||||
|     }, | ||||
|     "publishConfig": { | ||||
|         "access": "public" | ||||
|   | ||||
| @@ -116,15 +116,6 @@ export { | ||||
|     SamplerMetrics, | ||||
| } from './types'; | ||||
| export { affiliateFeeUtils } from './utils/affiliate_fee_utils'; | ||||
| export { | ||||
|     IRfqClient, | ||||
|     RfqClientV1Price, | ||||
|     RfqClientV1PriceRequest, | ||||
|     RfqClientV1PriceResponse, | ||||
|     RfqClientV1Quote, | ||||
|     RfqClientV1QuoteRequest, | ||||
|     RfqClientV1QuoteResponse, | ||||
| } from './utils/irfq_client'; | ||||
| export { | ||||
|     DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID, | ||||
|     DEFAULT_GAS_SCHEDULE, | ||||
| @@ -153,6 +144,7 @@ export { | ||||
|     Fill, | ||||
|     FillData, | ||||
|     GetMarketOrdersRfqOpts, | ||||
|     KyberFillData, | ||||
|     LiquidityProviderFillData, | ||||
|     LiquidityProviderRegistry, | ||||
|     MarketDepth, | ||||
|   | ||||
| @@ -1,57 +0,0 @@ | ||||
| import { BigNumber } from '@0x/utils'; | ||||
|  | ||||
| import { ZERO_AMOUNT } from '../constants'; | ||||
| export interface GeistInfo { | ||||
|     lendingPool: string; | ||||
|     gToken: string; | ||||
|     underlyingToken: string; | ||||
| } | ||||
| // tslint:disable-next-line:no-unnecessary-class | ||||
| export class GeistSampler { | ||||
|     public static sampleSellsFromGeist( | ||||
|         geistInfo: GeistInfo, | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         takerTokenAmounts: BigNumber[], | ||||
|     ): BigNumber[] { | ||||
|         // Deposit/Withdrawal underlying <-> gToken is always 1:1 | ||||
|         if ( | ||||
|             (takerToken.toLowerCase() === geistInfo.gToken.toLowerCase() && | ||||
|                 makerToken.toLowerCase() === geistInfo.underlyingToken.toLowerCase()) || | ||||
|             (takerToken.toLowerCase() === geistInfo.underlyingToken.toLowerCase() && | ||||
|                 makerToken.toLowerCase() === geistInfo.gToken.toLowerCase()) | ||||
|         ) { | ||||
|             return takerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         // Not matching the reserve return 0 results | ||||
|         const numSamples = takerTokenAmounts.length; | ||||
|  | ||||
|         const makerTokenAmounts = new Array(numSamples); | ||||
|         makerTokenAmounts.fill(ZERO_AMOUNT); | ||||
|         return makerTokenAmounts; | ||||
|     } | ||||
|  | ||||
|     public static sampleBuysFromGeist( | ||||
|         geistInfo: GeistInfo, | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         makerTokenAmounts: BigNumber[], | ||||
|     ): BigNumber[] { | ||||
|         // Deposit/Withdrawal underlying <-> gToken is always 1:1 | ||||
|         if ( | ||||
|             (takerToken.toLowerCase() === geistInfo.gToken.toLowerCase() && | ||||
|                 makerToken.toLowerCase() === geistInfo.underlyingToken.toLowerCase()) || | ||||
|             (takerToken.toLowerCase() === geistInfo.underlyingToken.toLowerCase() && | ||||
|                 makerToken.toLowerCase() === geistInfo.gToken.toLowerCase()) | ||||
|         ) { | ||||
|             return makerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         // Not matching the reserve return 0 results | ||||
|         const numSamples = makerTokenAmounts.length; | ||||
|         const takerTokenAmounts = new Array(numSamples); | ||||
|         takerTokenAmounts.fill(ZERO_AMOUNT); | ||||
|         return takerTokenAmounts; | ||||
|     } | ||||
| } | ||||
| @@ -42,7 +42,6 @@ import { | ||||
|     FinalUniswapV3FillData, | ||||
|     LiquidityProviderFillData, | ||||
|     MooniswapFillData, | ||||
|     NativeRfqOrderFillData, | ||||
|     OptimizedMarketBridgeOrder, | ||||
|     OptimizedMarketOrder, | ||||
|     UniswapV2FillData, | ||||
| @@ -61,7 +60,6 @@ import { | ||||
|     isDirectSwapCompatible, | ||||
|     isMultiplexBatchFillCompatible, | ||||
|     isMultiplexMultiHopFillCompatible, | ||||
|     requiresTransformERC20, | ||||
| } from './quote_consumer_utils'; | ||||
|  | ||||
| // tslint:disable-next-line:custom-no-magic-numbers | ||||
| @@ -75,7 +73,9 @@ const PANCAKE_SWAP_FORKS = [ | ||||
|     ERC20BridgeSource.BakerySwap, | ||||
|     ERC20BridgeSource.SushiSwap, | ||||
|     ERC20BridgeSource.ApeSwap, | ||||
|     ERC20BridgeSource.CafeSwap, | ||||
|     ERC20BridgeSource.CheeseSwap, | ||||
|     ERC20BridgeSource.JulSwap, | ||||
| ]; | ||||
| const FAKE_PROVIDER: any = { | ||||
|     sendAsync(): void { | ||||
| @@ -220,7 +220,9 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase { | ||||
|                 ERC20BridgeSource.BakerySwap, | ||||
|                 ERC20BridgeSource.SushiSwap, | ||||
|                 ERC20BridgeSource.ApeSwap, | ||||
|                 ERC20BridgeSource.CafeSwap, | ||||
|                 ERC20BridgeSource.CheeseSwap, | ||||
|                 ERC20BridgeSource.JulSwap, | ||||
|             ]) | ||||
|         ) { | ||||
|             const source = slippedOrders[0].source; | ||||
| @@ -276,7 +278,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase { | ||||
|  | ||||
|         if ( | ||||
|             this.chainId === ChainId.Mainnet && | ||||
|             isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Curve]) && | ||||
|             isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Curve, ERC20BridgeSource.Swerve]) && | ||||
|             // Curve VIP cannot currently support WETH buy/sell as the functionality needs to WITHDRAW or DEPOSIT | ||||
|             // into WETH prior/post the trade. | ||||
|             // ETH buy/sell is supported | ||||
| @@ -331,49 +333,6 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase { | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         // RFQT VIP | ||||
|         if ( | ||||
|             [ChainId.Mainnet, ChainId.Polygon].includes(this.chainId) && | ||||
|             !isToETH && | ||||
|             !isFromETH && | ||||
|             quote.orders.every(o => o.type === FillQuoteTransformerOrderType.Rfq) && | ||||
|             !requiresTransformERC20(optsWithDefaults) | ||||
|         ) { | ||||
|             const rfqOrdersData = quote.orders.map(o => o.fillData as NativeRfqOrderFillData); | ||||
|             const fillAmountPerOrder = (() => { | ||||
|                 // Don't think order taker amounts are clipped to actual sell amount | ||||
|                 // (the last one might be too large) so figure them out manually. | ||||
|                 let remaining = sellAmount; | ||||
|                 const fillAmounts = []; | ||||
|                 for (const o of quote.orders) { | ||||
|                     const fillAmount = BigNumber.min(o.takerAmount, remaining); | ||||
|                     fillAmounts.push(fillAmount); | ||||
|                     remaining = remaining.minus(fillAmount); | ||||
|                 } | ||||
|                 return fillAmounts; | ||||
|             })(); | ||||
|             const callData = | ||||
|                 quote.orders.length === 1 | ||||
|                     ? this._exchangeProxy | ||||
|                           .fillRfqOrder(rfqOrdersData[0].order, rfqOrdersData[0].signature, fillAmountPerOrder[0]) | ||||
|                           .getABIEncodedTransactionData() | ||||
|                     : this._exchangeProxy | ||||
|                           .batchFillRfqOrders( | ||||
|                               rfqOrdersData.map(d => d.order), | ||||
|                               rfqOrdersData.map(d => d.signature), | ||||
|                               fillAmountPerOrder, | ||||
|                               true, | ||||
|                           ) | ||||
|                           .getABIEncodedTransactionData(); | ||||
|             return { | ||||
|                 calldataHexString: callData, | ||||
|                 ethAmount: ZERO_AMOUNT, | ||||
|                 toAddress: this._exchangeProxy.address, | ||||
|                 allowanceTarget: this._exchangeProxy.address, | ||||
|                 gasOverhead: ZERO_AMOUNT, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         if (this.chainId === ChainId.Mainnet && isMultiplexBatchFillCompatible(quote, optsWithDefaults)) { | ||||
|             return { | ||||
|                 calldataHexString: this._encodeMultiplexBatchFillCalldata( | ||||
|   | ||||
| @@ -25,7 +25,6 @@ import { | ||||
|     SwapQuoterRfqOpts, | ||||
| } from './types'; | ||||
| import { assert } from './utils/assert'; | ||||
| import { IRfqClient } from './utils/irfq_client'; | ||||
| import { MarketOperationUtils } from './utils/market_operation_utils'; | ||||
| import { BancorService } from './utils/market_operation_utils/bancor_service'; | ||||
| import { SAMPLER_ADDRESS, SOURCE_FLAGS, ZERO_AMOUNT } from './utils/market_operation_utils/constants'; | ||||
| @@ -328,7 +327,6 @@ export class SwapQuoter { | ||||
|         assetFillAmount: BigNumber, | ||||
|         marketOperation: MarketOperation, | ||||
|         options: Partial<SwapQuoteRequestOpts>, | ||||
|         rfqClient?: IRfqClient | undefined, | ||||
|     ): Promise<SwapQuote> { | ||||
|         assert.isETHAddressHex('makerToken', makerToken); | ||||
|         assert.isETHAddressHex('takerToken', takerToken); | ||||
| @@ -383,7 +381,6 @@ export class SwapQuoter { | ||||
|                 this.expiryBufferMs, | ||||
|                 rfqtOptions?.metricsProxy, | ||||
|             ); | ||||
|             calcOpts.rfqt.rfqClient = rfqClient; | ||||
|         } | ||||
|  | ||||
|         const result: OptimizerResultWithReport = await this._marketOperationUtils.getOptimizerResultAsync( | ||||
| @@ -522,7 +519,7 @@ function createSwapQuote( | ||||
|         : calculateQuoteInfo(optimizedOrders, operation, assetFillAmount, gasPrice, gasSchedule, slippage); | ||||
|  | ||||
|     // Put together the swap quote | ||||
|     const { makerTokenDecimals, takerTokenDecimals, blockNumber } = optimizerResult.marketSideLiquidity; | ||||
|     const { makerTokenDecimals, takerTokenDecimals } = optimizerResult.marketSideLiquidity; | ||||
|     const swapQuote = { | ||||
|         makerToken, | ||||
|         takerToken, | ||||
| @@ -539,7 +536,6 @@ function createSwapQuote( | ||||
|         extendedQuoteReportSources, | ||||
|         isTwoHop, | ||||
|         priceComparisonsReport, | ||||
|         blockNumber, | ||||
|     }; | ||||
|  | ||||
|     if (operation === MarketOperation.Buy) { | ||||
|   | ||||
| @@ -179,7 +179,6 @@ export interface SwapQuoteBase { | ||||
|     takerTokenDecimals: number; | ||||
|     takerAmountPerEth: BigNumber; | ||||
|     makerAmountPerEth: BigNumber; | ||||
|     blockNumber: number; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -17,10 +17,7 @@ import { | ||||
|  | ||||
| const SUCCESS_CODE = 201; | ||||
|  | ||||
| /** | ||||
|  * Returns the AltOffering if it exists for a given pair | ||||
|  */ | ||||
| export function getAltMarketInfo( | ||||
| function getAltMarketInfo( | ||||
|     offerings: AltOffering[], | ||||
|     buyTokenAddress: string, | ||||
|     sellTokenAddress: string, | ||||
|   | ||||
| @@ -1,59 +0,0 @@ | ||||
| import { RfqOrder, Signature } from '@0x/protocol-utils'; | ||||
| import { BigNumber } from '@0x/utils'; | ||||
|  | ||||
| import { AltRfqMakerAssetOfferings } from '../types'; | ||||
|  | ||||
| export interface RfqClientV1PriceRequest { | ||||
|     altRfqAssetOfferings: AltRfqMakerAssetOfferings | undefined; | ||||
|     assetFillAmount: BigNumber; | ||||
|     chainId: number; | ||||
|     comparisonPrice: BigNumber | undefined; | ||||
|     integratorId: string; | ||||
|     intentOnFilling: boolean; | ||||
|     makerToken: string; | ||||
|     marketOperation: 'Sell' | 'Buy'; | ||||
|     takerAddress: string; | ||||
|     takerToken: string; | ||||
|     txOrigin: string; | ||||
| } | ||||
|  | ||||
| export interface RfqClientV1QuoteRequest extends RfqClientV1PriceRequest {} | ||||
|  | ||||
| export interface RfqClientV1Price { | ||||
|     expiry: BigNumber; | ||||
|     kind: 'rfq' | 'otc'; | ||||
|     makerAmount: BigNumber; | ||||
|     makerToken: string; | ||||
|     makerUri: string; | ||||
|     takerAmount: BigNumber; | ||||
|     takerToken: string; | ||||
| } | ||||
|  | ||||
| export interface RfqClientV1PriceResponse { | ||||
|     prices: RfqClientV1Price[]; | ||||
| } | ||||
|  | ||||
| export interface RfqClientV1Quote { | ||||
|     makerUri: string; | ||||
|     order: RfqOrder; | ||||
|     signature: Signature; | ||||
| } | ||||
|  | ||||
| export interface RfqClientV1QuoteResponse { | ||||
|     quotes: RfqClientV1Quote[]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * IRfqClient is an interface that defines how to connect with an Rfq system. | ||||
|  */ | ||||
| export interface IRfqClient { | ||||
|     /** | ||||
|      * Fetches a list of "indicative quotes" or prices from a remote Rfq server | ||||
|      */ | ||||
|     getV1PricesAsync(request: RfqClientV1PriceRequest): Promise<RfqClientV1PriceResponse>; | ||||
|  | ||||
|     /** | ||||
|      * Fetches a list of "firm quotes" or signed quotes from a remote Rfq server. | ||||
|      */ | ||||
|     getV1QuotesAsync(request: RfqClientV1QuoteRequest): Promise<RfqClientV1QuoteResponse>; | ||||
| } | ||||
| @@ -1,12 +1,12 @@ | ||||
| import { ChainId } from '@0x/contract-addresses'; | ||||
| import { BigNumber } from '@0x/utils'; | ||||
| import { BigNumber, NULL_BYTES } from '@0x/utils'; | ||||
|  | ||||
| import { | ||||
|     ACRYPTOS_BSC_INFOS, | ||||
|     APESWAP_ROUTER_BY_CHAIN_ID, | ||||
|     BAKERYSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     BELT_BSC_INFOS, | ||||
|     BISWAP_ROUTER_BY_CHAIN_ID, | ||||
|     CAFESWAP_ROUTER_BY_CHAIN_ID, | ||||
|     CHEESESWAP_ROUTER_BY_CHAIN_ID, | ||||
|     COMETHSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     COMPONENT_POOLS_BY_CHAIN_ID, | ||||
| @@ -25,11 +25,12 @@ import { | ||||
|     FIREBIRDONESWAP_BSC_INFOS, | ||||
|     FIREBIRDONESWAP_POLYGON_INFOS, | ||||
|     IRONSWAP_POLYGON_INFOS, | ||||
|     KNIGHTSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     JETSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     JULSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     KYBER_BANNED_RESERVES, | ||||
|     KYBER_BRIDGED_LIQUIDITY_PREFIX, | ||||
|     MAX_DODOV2_POOLS_QUERIED, | ||||
|     MDEX_ROUTER_BY_CHAIN_ID, | ||||
|     MESHSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     MOBIUSMONEY_CELO_INFOS, | ||||
|     MAX_KYBER_RESERVES_QUERIED, | ||||
|     MORPHEUSSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     MSTABLE_POOLS_BY_CHAIN_ID, | ||||
|     NERVE_BSC_INFOS, | ||||
| @@ -37,16 +38,18 @@ import { | ||||
|     PANCAKESWAP_ROUTER_BY_CHAIN_ID, | ||||
|     PANCAKESWAPV2_ROUTER_BY_CHAIN_ID, | ||||
|     PANGOLIN_ROUTER_BY_CHAIN_ID, | ||||
|     PLATYPUS_AVALANCHE_INFOS, | ||||
|     POLYDEX_ROUTER_BY_CHAIN_ID, | ||||
|     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, | ||||
|     SPIRITSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     SPOOKYSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     SUSHISWAP_ROUTER_BY_CHAIN_ID, | ||||
|     SWERVE_MAINNET_INFOS, | ||||
|     SYNAPSE_AVALANCHE_INFOS, | ||||
|     SYNAPSE_BSC_INFOS, | ||||
|     SYNAPSE_FANTOM_INFOS, | ||||
| @@ -58,15 +61,35 @@ import { | ||||
|     UNISWAPV2_ROUTER_BY_CHAIN_ID, | ||||
|     WAULTSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     XSIGMA_MAINNET_INFOS, | ||||
|     YOSHI_ROUTER_BY_CHAIN_ID, | ||||
| } from './constants'; | ||||
| import { CurveInfo, ERC20BridgeSource, PlatypusInfo } from './types'; | ||||
| import { CurveInfo, ERC20BridgeSource } from './types'; | ||||
|  | ||||
| /** | ||||
|  * Filter Kyber reserves which should not be used (0xbb bridged reserves) | ||||
|  * @param reserveId Kyber reserveId | ||||
|  */ | ||||
| export function isAllowedKyberReserveId(reserveId: string): boolean { | ||||
|     return ( | ||||
|         reserveId !== NULL_BYTES && | ||||
|         !reserveId.startsWith(KYBER_BRIDGED_LIQUIDITY_PREFIX) && | ||||
|         !KYBER_BANNED_RESERVES.includes(reserveId) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| // tslint:disable-next-line: completed-docs ban-types | ||||
| export function isValidAddress(address: string | String): address is string { | ||||
|     return (typeof address === 'string' || address instanceof String) && address.toString() !== NULL_ADDRESS; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns the offsets to be used to discover Kyber reserves | ||||
|  */ | ||||
| export function getKyberOffsets(): BigNumber[] { | ||||
|     return Array(MAX_KYBER_RESERVES_QUERIED) | ||||
|         .fill(0) | ||||
|         .map((_v, i) => new BigNumber(i)); | ||||
| } | ||||
|  | ||||
| // tslint:disable completed-docs | ||||
| export function getDodoV2Offsets(): BigNumber[] { | ||||
|     return Array(MAX_DODOV2_POOLS_QUERIED) | ||||
| @@ -201,6 +224,32 @@ export function getCurveV2InfosForPair(chainId: ChainId, takerToken: string, mak | ||||
|     } | ||||
| } | ||||
|  | ||||
| export function getSwerveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] { | ||||
|     if (chainId !== ChainId.Mainnet) { | ||||
|         return []; | ||||
|     } | ||||
|     return Object.values(SWERVE_MAINNET_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 getSnowSwapInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] { | ||||
|     if (chainId !== ChainId.Mainnet) { | ||||
|         return []; | ||||
|     } | ||||
|     return Object.values(SNOWSWAP_MAINNET_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 getNerveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] { | ||||
|     if (chainId !== ChainId.BSC) { | ||||
|         return []; | ||||
| @@ -400,27 +449,6 @@ export function getAcryptosInfosForPair(chainId: ChainId, takerToken: string, ma | ||||
|         ), | ||||
|     ); | ||||
| } | ||||
| export function getMobiusMoneyInfoForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] { | ||||
|     if (chainId !== ChainId.Celo) { | ||||
|         return []; | ||||
|     } | ||||
|     return Object.values(MOBIUSMONEY_CELO_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 getPlatypusInfoForPair(chainId: ChainId, takerToken: string, makerToken: string): PlatypusInfo[] { | ||||
|     if (chainId !== ChainId.Avalanche) { | ||||
|         return []; | ||||
|     } | ||||
|     return Object.values(PLATYPUS_AVALANCHE_INFOS).filter(c => | ||||
|         [makerToken, takerToken].every(t => c.tokens.includes(t)), | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export function getShellLikeInfosForPair( | ||||
|     chainId: ChainId, | ||||
| @@ -452,6 +480,8 @@ export function getCurveLikeInfosForPair( | ||||
|     source: | ||||
|         | ERC20BridgeSource.Curve | ||||
|         | ERC20BridgeSource.CurveV2 | ||||
|         | ERC20BridgeSource.Swerve | ||||
|         | ERC20BridgeSource.SnowSwap | ||||
|         | ERC20BridgeSource.Nerve | ||||
|         | ERC20BridgeSource.Synapse | ||||
|         | ERC20BridgeSource.Belt | ||||
| @@ -461,8 +491,7 @@ export function getCurveLikeInfosForPair( | ||||
|         | ERC20BridgeSource.IronSwap | ||||
|         | ERC20BridgeSource.XSigma | ||||
|         | ERC20BridgeSource.FirebirdOneSwap | ||||
|         | ERC20BridgeSource.ACryptos | ||||
|         | ERC20BridgeSource.MobiusMoney, | ||||
|         | ERC20BridgeSource.ACryptos, | ||||
| ): CurveDetailedInfo[] { | ||||
|     let pools: CurveInfo[] = []; | ||||
|     switch (source) { | ||||
| @@ -472,6 +501,12 @@ export function getCurveLikeInfosForPair( | ||||
|         case ERC20BridgeSource.CurveV2: | ||||
|             pools = getCurveV2InfosForPair(chainId, takerToken, makerToken); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Swerve: | ||||
|             pools = getSwerveInfosForPair(chainId, takerToken, makerToken); | ||||
|             break; | ||||
|         case ERC20BridgeSource.SnowSwap: | ||||
|             pools = getSnowSwapInfosForPair(chainId, takerToken, makerToken); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Nerve: | ||||
|             pools = getNerveInfosForPair(chainId, takerToken, makerToken); | ||||
|             break; | ||||
| @@ -502,9 +537,6 @@ export function getCurveLikeInfosForPair( | ||||
|         case ERC20BridgeSource.ACryptos: | ||||
|             pools = getAcryptosInfosForPair(chainId, takerToken, makerToken); | ||||
|             break; | ||||
|         case ERC20BridgeSource.MobiusMoney: | ||||
|             pools = getMobiusMoneyInfoForPair(chainId, takerToken, makerToken); | ||||
|             break; | ||||
|         default: | ||||
|             throw new Error(`Unknown Curve like source ${source}`); | ||||
|     } | ||||
| @@ -525,23 +557,22 @@ export function uniswapV2LikeRouterAddress( | ||||
|         | ERC20BridgeSource.PancakeSwapV2 | ||||
|         | ERC20BridgeSource.BakerySwap | ||||
|         | ERC20BridgeSource.ApeSwap | ||||
|         | ERC20BridgeSource.CafeSwap | ||||
|         | ERC20BridgeSource.CheeseSwap | ||||
|         | ERC20BridgeSource.JulSwap | ||||
|         | ERC20BridgeSource.QuickSwap | ||||
|         | ERC20BridgeSource.ComethSwap | ||||
|         | ERC20BridgeSource.Dfyn | ||||
|         | ERC20BridgeSource.WaultSwap | ||||
|         | ERC20BridgeSource.Polydex | ||||
|         | ERC20BridgeSource.ShibaSwap | ||||
|         | ERC20BridgeSource.JetSwap | ||||
|         | ERC20BridgeSource.TraderJoe | ||||
|         | ERC20BridgeSource.Pangolin | ||||
|         | ERC20BridgeSource.UbeSwap | ||||
|         | ERC20BridgeSource.MorpheusSwap | ||||
|         | ERC20BridgeSource.SpookySwap | ||||
|         | ERC20BridgeSource.SpiritSwap | ||||
|         | ERC20BridgeSource.BiSwap | ||||
|         | ERC20BridgeSource.Yoshi | ||||
|         | ERC20BridgeSource.MDex | ||||
|         | ERC20BridgeSource.KnightSwap | ||||
|         | ERC20BridgeSource.MeshSwap, | ||||
|         | ERC20BridgeSource.SpiritSwap, | ||||
| ): string { | ||||
|     switch (source) { | ||||
|         case ERC20BridgeSource.UniswapV2: | ||||
| @@ -558,8 +589,12 @@ export function uniswapV2LikeRouterAddress( | ||||
|             return BAKERYSWAP_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]; | ||||
|         case ERC20BridgeSource.QuickSwap: | ||||
|             return QUICKSWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.ComethSwap: | ||||
| @@ -568,8 +603,12 @@ export function uniswapV2LikeRouterAddress( | ||||
|             return DFYN_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.WaultSwap: | ||||
|             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]; | ||||
|         case ERC20BridgeSource.Pangolin: | ||||
|             return PANGOLIN_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.TraderJoe: | ||||
| @@ -582,16 +621,6 @@ export function uniswapV2LikeRouterAddress( | ||||
|             return SPOOKYSWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.SpiritSwap: | ||||
|             return SPIRITSWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.BiSwap: | ||||
|             return BISWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.Yoshi: | ||||
|             return YOSHI_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.MeshSwap: | ||||
|             return MESHSWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.MDex: | ||||
|             return MDEX_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.KnightSwap: | ||||
|             return KNIGHTSWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         default: | ||||
|             throw new Error(`Unknown UniswapV2 like source ${source}`); | ||||
|     } | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -175,9 +175,9 @@ export function dexSamplesToFills( | ||||
|         const { source, fillData } = sample; | ||||
|         const input = sample.input.minus(prevSample ? prevSample.input : 0); | ||||
|         const output = sample.output.minus(prevSample ? prevSample.output : 0); | ||||
|         const fee = fees[source] === undefined ? 0 : fees[source]!(sample.fillData) || 0; | ||||
|         let penalty = ZERO_AMOUNT; | ||||
|         if (i === 0) { | ||||
|             const fee = fees[source] === undefined ? 0 : fees[source]!(sample.fillData) || 0; | ||||
|             // Only the first fill in a DEX path incurs a penalty. | ||||
|             penalty = ethToOutputAmount({ | ||||
|                 input, | ||||
|   | ||||
| @@ -1,36 +0,0 @@ | ||||
| import { FANTOM_TOKENS, GEIST_FANTOM_POOLS } from './constants'; | ||||
| import { GeistInfo } from './types'; | ||||
|  | ||||
| const gTokenToUnderlyingToken = new Map<string, string>([ | ||||
|     [FANTOM_TOKENS.gFTM, FANTOM_TOKENS.WFTM], | ||||
|     [FANTOM_TOKENS.gfUSDT, FANTOM_TOKENS.fUSDT], | ||||
|     [FANTOM_TOKENS.gDAI, FANTOM_TOKENS.DAI], | ||||
|     [FANTOM_TOKENS.gUSDC, FANTOM_TOKENS.USDC], | ||||
|     [FANTOM_TOKENS.gETH, FANTOM_TOKENS.WETH], | ||||
|     [FANTOM_TOKENS.gWBTC, FANTOM_TOKENS.WBTC], | ||||
|     [FANTOM_TOKENS.gCRV, FANTOM_TOKENS.WCRV], | ||||
|     [FANTOM_TOKENS.gMIM, FANTOM_TOKENS.MIM], | ||||
| ]); | ||||
|  | ||||
| /** | ||||
|  * Returns GeistInfo for a certain pair if that pair exists on Geist | ||||
|  */ | ||||
| export function getGeistInfoForPair(takerToken: string, makerToken: string): GeistInfo | undefined { | ||||
|     let gToken; | ||||
|     let underlyingToken; | ||||
|     if (gTokenToUnderlyingToken.get(takerToken) === makerToken) { | ||||
|         gToken = takerToken; | ||||
|         underlyingToken = makerToken; | ||||
|     } else if (gTokenToUnderlyingToken.get(makerToken) === takerToken) { | ||||
|         gToken = makerToken; | ||||
|         underlyingToken = takerToken; | ||||
|     } else { | ||||
|         return undefined; | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         lendingPool: GEIST_FANTOM_POOLS.lendingPool, | ||||
|         gToken, | ||||
|         underlyingToken, | ||||
|     }; | ||||
| } | ||||
| @@ -4,15 +4,12 @@ import * as _ from 'lodash'; | ||||
|  | ||||
| import { DEFAULT_INFO_LOGGER, INVALID_SIGNATURE } from '../../constants'; | ||||
| import { | ||||
|     AltRfqMakerAssetOfferings, | ||||
|     AssetSwapperContractAddresses, | ||||
|     MarketOperation, | ||||
|     NativeOrderWithFillableAmounts, | ||||
|     SignedNativeOrder, | ||||
| } from '../../types'; | ||||
| import { getAltMarketInfo } from '../alt_mm_implementation_utils'; | ||||
| import { QuoteRequestor, V4RFQIndicativeQuoteMM } from '../quote_requestor'; | ||||
| import { toSignedNativeOrder } from '../rfq_client_mappers'; | ||||
| import { QuoteRequestor } from '../quote_requestor'; | ||||
| import { | ||||
|     getNativeAdjustedFillableAmountsFromMakerAmount, | ||||
|     getNativeAdjustedFillableAmountsFromTakerAmount, | ||||
| @@ -45,7 +42,7 @@ import { createFills } from './fills'; | ||||
| import { getBestTwoHopQuote } from './multihop_utils'; | ||||
| import { createOrdersFromTwoHopSample } from './orders'; | ||||
| import { Path, PathPenaltyOpts } from './path'; | ||||
| import { findOptimalPathJSAsync, findOptimalRustPathFromSamples } from './path_optimizer'; | ||||
| import { fillsToSortedPaths, findOptimalPathJSAsync, findOptimalRustPathFromSamples } from './path_optimizer'; | ||||
| import { DexOrderSampler, getSampleAmounts } from './sampler'; | ||||
| import { SourceFilters } from './source_filters'; | ||||
| import { | ||||
| @@ -244,7 +241,6 @@ export class MarketOperationUtils { | ||||
|                 dexQuotes, | ||||
|             }, | ||||
|             isRfqSupported, | ||||
|             blockNumber: blockNumber.toNumber(), | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| @@ -273,7 +269,6 @@ export class MarketOperationUtils { | ||||
|  | ||||
|         // Call the sampler contract. | ||||
|         const samplerPromise = this._sampler.executeAsync( | ||||
|             this._sampler.getBlockNumber(), | ||||
|             this._sampler.getTokenDecimals([makerToken, takerToken]), | ||||
|             // Get native order fillable amounts. | ||||
|             this._sampler.getLimitOrderFillableMakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy), | ||||
| @@ -307,7 +302,6 @@ export class MarketOperationUtils { | ||||
|  | ||||
|         const [ | ||||
|             [ | ||||
|                 blockNumber, | ||||
|                 tokenDecimals, | ||||
|                 orderFillableMakerAmounts, | ||||
|                 ethToMakerAssetRate, | ||||
| @@ -348,7 +342,6 @@ export class MarketOperationUtils { | ||||
|                 dexQuotes, | ||||
|             }, | ||||
|             isRfqSupported, | ||||
|             blockNumber: blockNumber.toNumber(), | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| @@ -379,7 +372,6 @@ export class MarketOperationUtils { | ||||
|         const feeSourceFilters = this._feeSources.exclude(_opts.excludedFeeSources); | ||||
|  | ||||
|         const ops = [ | ||||
|             this._sampler.getBlockNumber(), | ||||
|             ...batchNativeOrders.map(orders => | ||||
|                 this._sampler.getLimitOrderFillableMakerAmounts(orders, this.contractAddresses.exchangeProxy), | ||||
|             ), | ||||
| @@ -404,15 +396,13 @@ export class MarketOperationUtils { | ||||
|             ), | ||||
|         ]; | ||||
|  | ||||
|         const [blockNumberRaw, ...executeResults] = await this._sampler.executeBatchAsync(ops); | ||||
|         const executeResults = await this._sampler.executeBatchAsync(ops); | ||||
|         const batchOrderFillableMakerAmounts = executeResults.splice(0, batchNativeOrders.length) as BigNumber[][]; | ||||
|         const batchEthToTakerAssetRate = executeResults.splice(0, batchNativeOrders.length) as BigNumber[]; | ||||
|         const batchDexQuotes = executeResults.splice(0, batchNativeOrders.length) as DexSample[][][]; | ||||
|         const batchTokenDecimals = executeResults.splice(0, batchNativeOrders.length) as number[][]; | ||||
|         const inputAmountPerEth = ZERO_AMOUNT; | ||||
|  | ||||
|         const blockNumber: number = (blockNumberRaw as BigNumber).toNumber(); | ||||
|  | ||||
|         return Promise.all( | ||||
|             batchNativeOrders.map(async (nativeOrders, i) => { | ||||
|                 if (nativeOrders.length === 0) { | ||||
| @@ -445,7 +435,6 @@ export class MarketOperationUtils { | ||||
|                                 twoHopQuotes: [], | ||||
|                             }, | ||||
|                             isRfqSupported: false, | ||||
|                             blockNumber, | ||||
|                         }, | ||||
|                         { | ||||
|                             bridgeSlippage: _opts.bridgeSlippage, | ||||
| @@ -504,6 +493,18 @@ export class MarketOperationUtils { | ||||
|                 } as NativeOrderWithFillableAmounts), | ||||
|         ); | ||||
|  | ||||
|         // Convert native orders and dex quotes into `Fill` objects. | ||||
|         const fills = createFills({ | ||||
|             side, | ||||
|             orders: [...nativeOrders, ...augmentedRfqtIndicativeQuotes], | ||||
|             dexQuotes, | ||||
|             targetInput: inputAmount, | ||||
|             outputAmountPerEth, | ||||
|             inputAmountPerEth, | ||||
|             excludedSources: opts.excludedSources, | ||||
|             feeSchedule: opts.feeSchedule, | ||||
|         }); | ||||
|  | ||||
|         // Find the optimal path. | ||||
|         const penaltyOpts: PathPenaltyOpts = { | ||||
|             outputAmountPerEth, | ||||
| @@ -516,11 +517,13 @@ export class MarketOperationUtils { | ||||
|         const takerAmountPerEth = side === MarketOperation.Sell ? inputAmountPerEth : outputAmountPerEth; | ||||
|         const makerAmountPerEth = side === MarketOperation.Sell ? outputAmountPerEth : inputAmountPerEth; | ||||
|  | ||||
|         let fills: Fill[][]; | ||||
|         // Find the unoptimized best rate to calculate savings from optimizer | ||||
|         const _unoptimizedPath = fillsToSortedPaths(fills, side, inputAmount, penaltyOpts)[0]; | ||||
|         const unoptimizedPath = _unoptimizedPath ? _unoptimizedPath.collapse(orderOpts) : undefined; | ||||
|  | ||||
|         // Find the optimal path using Rust router if enabled, otherwise fallback to JS Router | ||||
|         let optimalPath: Path | undefined; | ||||
|         if (SHOULD_USE_RUST_ROUTER) { | ||||
|             fills = [[]]; | ||||
|             optimalPath = findOptimalRustPathFromSamples( | ||||
|                 side, | ||||
|                 dexQuotes, | ||||
| @@ -533,18 +536,6 @@ export class MarketOperationUtils { | ||||
|                 opts.samplerMetrics, | ||||
|             ); | ||||
|         } else { | ||||
|             // Convert native orders and dex quotes into `Fill` objects. | ||||
|             fills = createFills({ | ||||
|                 side, | ||||
|                 orders: [...nativeOrders, ...augmentedRfqtIndicativeQuotes], | ||||
|                 dexQuotes, | ||||
|                 targetInput: inputAmount, | ||||
|                 outputAmountPerEth, | ||||
|                 inputAmountPerEth, | ||||
|                 excludedSources: opts.excludedSources, | ||||
|                 feeSchedule: opts.feeSchedule, | ||||
|             }); | ||||
|  | ||||
|             optimalPath = await findOptimalPathJSAsync( | ||||
|                 side, | ||||
|                 fills, | ||||
| @@ -570,6 +561,7 @@ export class MarketOperationUtils { | ||||
|                 sourceFlags: SOURCE_FLAGS[ERC20BridgeSource.MultiHop], | ||||
|                 marketSideLiquidity, | ||||
|                 adjustedRate: bestTwoHopRate, | ||||
|                 unoptimizedPath, | ||||
|                 takerAmountPerEth, | ||||
|                 makerAmountPerEth, | ||||
|             }; | ||||
| @@ -581,10 +573,7 @@ export class MarketOperationUtils { | ||||
|         } | ||||
|  | ||||
|         // Generate a fallback path if required | ||||
|         // TODO(kimpers): Will experiment with disabling this and see how it affects revert rate | ||||
|         // to avoid yet another router roundtrip | ||||
|         // TODO: clean this up if we don't need it | ||||
|         // await this._addOptionalFallbackAsync(side, inputAmount, optimalPath, dexQuotes, fills, opts, penaltyOpts); | ||||
|         await this._addOptionalFallbackAsync(side, inputAmount, optimalPath, dexQuotes, fills, opts, penaltyOpts); | ||||
|         const collapsedPath = optimalPath.collapse(orderOpts); | ||||
|  | ||||
|         return { | ||||
| @@ -593,6 +582,7 @@ export class MarketOperationUtils { | ||||
|             sourceFlags: collapsedPath.sourceFlags, | ||||
|             marketSideLiquidity, | ||||
|             adjustedRate: optimalPathRate, | ||||
|             unoptimizedPath, | ||||
|             takerAmountPerEth, | ||||
|             makerAmountPerEth, | ||||
|         }; | ||||
| @@ -666,49 +656,17 @@ export class MarketOperationUtils { | ||||
|             // Timing of RFQT lifecycle | ||||
|             const timeStart = new Date().getTime(); | ||||
|             const { makerToken, takerToken } = nativeOrders[0].order; | ||||
|  | ||||
|             // Filter Alt Rfq Maker Asset Offerings to the current pair | ||||
|             const filteredOfferings: AltRfqMakerAssetOfferings = {}; | ||||
|             if (rfqt.altRfqAssetOfferings) { | ||||
|                 const endpoints = Object.keys(rfqt.altRfqAssetOfferings); | ||||
|                 for (const endpoint of endpoints) { | ||||
|                     // Get the current pair if being offered | ||||
|                     const offering = getAltMarketInfo(rfqt.altRfqAssetOfferings[endpoint], makerToken, takerToken); | ||||
|                     if (offering) { | ||||
|                         filteredOfferings[endpoint] = [offering]; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (rfqt.isIndicative) { | ||||
|                 // An indicative quote is being requested, and indicative quotes price-aware enabled | ||||
|                 // Make the RFQT request and then re-run the sampler if new orders come back. | ||||
|  | ||||
|                 const indicativeQuotes = | ||||
|                     rfqt.rfqClient !== undefined | ||||
|                         ? (( | ||||
|                               await rfqt.rfqClient.getV1PricesAsync({ | ||||
|                                   altRfqAssetOfferings: filteredOfferings, | ||||
|                                   assetFillAmount: amount, | ||||
|                                   chainId: this._sampler.chainId, | ||||
|                                   comparisonPrice: wholeOrderPrice, | ||||
|                                   integratorId: rfqt.integrator.integratorId, | ||||
|                                   intentOnFilling: rfqt.intentOnFilling, | ||||
|                                   makerToken, | ||||
|                                   marketOperation: side, | ||||
|                                   takerAddress: rfqt.takerAddress, | ||||
|                                   takerToken, | ||||
|                                   txOrigin: rfqt.txOrigin, | ||||
|                               }) | ||||
|                           ).prices as V4RFQIndicativeQuoteMM[]) | ||||
|                         : await rfqt.quoteRequestor.requestRfqtIndicativeQuotesAsync( | ||||
|                               makerToken, | ||||
|                               takerToken, | ||||
|                               amount, | ||||
|                               side, | ||||
|                               wholeOrderPrice, | ||||
|                               rfqt, | ||||
|                           ); | ||||
|                 const indicativeQuotes = await rfqt.quoteRequestor.requestRfqtIndicativeQuotesAsync( | ||||
|                     makerToken, | ||||
|                     takerToken, | ||||
|                     amount, | ||||
|                     side, | ||||
|                     wholeOrderPrice, | ||||
|                     rfqt, | ||||
|                 ); | ||||
|                 const deltaTime = new Date().getTime() - timeStart; | ||||
|                 DEFAULT_INFO_LOGGER({ | ||||
|                     rfqQuoteType: 'indicative', | ||||
| @@ -722,31 +680,14 @@ export class MarketOperationUtils { | ||||
|             } else { | ||||
|                 // A firm quote is being requested, and firm quotes price-aware enabled. | ||||
|                 // Ensure that `intentOnFilling` is enabled and make the request. | ||||
|                 const firmQuotes = | ||||
|                     rfqt.rfqClient !== undefined | ||||
|                         ? ( | ||||
|                               await rfqt.rfqClient.getV1QuotesAsync({ | ||||
|                                   altRfqAssetOfferings: filteredOfferings, | ||||
|                                   assetFillAmount: amount, | ||||
|                                   chainId: this._sampler.chainId, | ||||
|                                   comparisonPrice: wholeOrderPrice, | ||||
|                                   integratorId: rfqt.integrator.integratorId, | ||||
|                                   intentOnFilling: rfqt.intentOnFilling, | ||||
|                                   makerToken, | ||||
|                                   marketOperation: side, | ||||
|                                   takerAddress: rfqt.takerAddress, | ||||
|                                   takerToken, | ||||
|                                   txOrigin: rfqt.txOrigin, | ||||
|                               }) | ||||
|                           ).quotes.map(toSignedNativeOrder) | ||||
|                         : await rfqt.quoteRequestor.requestRfqtFirmQuotesAsync( | ||||
|                               makerToken, | ||||
|                               takerToken, | ||||
|                               amount, | ||||
|                               side, | ||||
|                               wholeOrderPrice, | ||||
|                               rfqt, | ||||
|                           ); | ||||
|                 const firmQuotes = await rfqt.quoteRequestor.requestRfqtFirmQuotesAsync( | ||||
|                     makerToken, | ||||
|                     takerToken, | ||||
|                     amount, | ||||
|                     side, | ||||
|                     wholeOrderPrice, | ||||
|                     rfqt, | ||||
|                 ); | ||||
|                 const deltaTime = new Date().getTime() - timeStart; | ||||
|                 DEFAULT_INFO_LOGGER({ | ||||
|                     rfqQuoteType: 'firm', | ||||
| @@ -829,7 +770,7 @@ export class MarketOperationUtils { | ||||
|     private async _refreshPoolCacheIfRequiredAsync(takerToken: string, makerToken: string): Promise<void> { | ||||
|         void Promise.all( | ||||
|             Object.values(this._sampler.poolsCaches).map(async cache => { | ||||
|                 if (!cache || cache.isFresh(takerToken, makerToken)) { | ||||
|                 if (cache.isFresh(takerToken, makerToken)) { | ||||
|                     return Promise.resolve([]); | ||||
|                 } | ||||
|                 return cache.getFreshPoolsForPairAsync(takerToken, makerToken); | ||||
| @@ -837,8 +778,6 @@ export class MarketOperationUtils { | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * TODO(kimpers): Remove this when we know that it's safe to drop the fallbacks on native orders | ||||
|     // tslint:disable-next-line: prefer-function-over-method | ||||
|     private async _addOptionalFallbackAsync( | ||||
|         side: MarketOperation, | ||||
| @@ -904,7 +843,6 @@ export class MarketOperationUtils { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  | ||||
| // tslint:disable: max-file-line-count | ||||
|   | ||||
| @@ -8,7 +8,6 @@ import { | ||||
|     AaveV2FillData, | ||||
|     AggregationError, | ||||
|     BalancerFillData, | ||||
|     BalancerV2BatchSwapFillData, | ||||
|     BalancerV2FillData, | ||||
|     BancorFillData, | ||||
|     CollapsedFill, | ||||
| @@ -19,10 +18,9 @@ import { | ||||
|     ERC20BridgeSource, | ||||
|     FillData, | ||||
|     FinalUniswapV3FillData, | ||||
|     GeistFillData, | ||||
|     GenericRouterFillData, | ||||
|     GMXFillData, | ||||
|     KyberDmmFillData, | ||||
|     KyberFillData, | ||||
|     LidoFillData, | ||||
|     LiquidityProviderFillData, | ||||
|     MakerPsmFillData, | ||||
| @@ -35,12 +33,9 @@ import { | ||||
|     OptimizedMarketOrder, | ||||
|     OptimizedMarketOrderBase, | ||||
|     OrderDomain, | ||||
|     PlatypusFillData, | ||||
|     ShellFillData, | ||||
|     UniswapV2FillData, | ||||
|     UniswapV3FillData, | ||||
|     UniswapV3PathAmount, | ||||
|     VelodromeFillData, | ||||
| } from './types'; | ||||
|  | ||||
| // tslint:disable completed-docs | ||||
| @@ -89,9 +84,11 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s | ||||
|         case ERC20BridgeSource.Balancer: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Balancer, 'Balancer'); | ||||
|         case ERC20BridgeSource.BalancerV2: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.BalancerV2Batch, 'BalancerV2'); | ||||
|             return encodeBridgeSourceId(BridgeProtocol.BalancerV2, 'BalancerV2'); | ||||
|         case ERC20BridgeSource.Bancor: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Bancor, 'Bancor'); | ||||
|         // case ERC20BridgeSource.CoFiX: | ||||
|         //    return encodeBridgeSourceId(BridgeProtocol.CoFiX, 'CoFiX'); | ||||
|         case ERC20BridgeSource.Curve: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Curve, 'Curve'); | ||||
|         case ERC20BridgeSource.Cream: | ||||
| @@ -100,6 +97,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s | ||||
|             return encodeBridgeSourceId(BridgeProtocol.CryptoCom, 'CryptoCom'); | ||||
|         case ERC20BridgeSource.Dodo: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Dodo, 'Dodo'); | ||||
|         case ERC20BridgeSource.Kyber: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Kyber, 'Kyber'); | ||||
|         case ERC20BridgeSource.LiquidityProvider: | ||||
|             // "LiquidityProvider" is too long to encode (17 characters). | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Unknown, 'LP'); | ||||
| @@ -109,16 +108,24 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Mooniswap, 'Mooniswap'); | ||||
|         case ERC20BridgeSource.MStable: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.MStable, 'MStable'); | ||||
|         case ERC20BridgeSource.Eth2Dai: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Oasis, 'Eth2Dai'); | ||||
|         case ERC20BridgeSource.Shell: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Shell, 'Shell'); | ||||
|         case ERC20BridgeSource.SnowSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Curve, 'SnowSwap'); | ||||
|         case ERC20BridgeSource.SushiSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SushiSwap'); | ||||
|         case ERC20BridgeSource.Swerve: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Curve, 'Swerve'); | ||||
|         case ERC20BridgeSource.Uniswap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Uniswap, 'Uniswap'); | ||||
|         case ERC20BridgeSource.UniswapV2: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'UniswapV2'); | ||||
|         case ERC20BridgeSource.DodoV2: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.DodoV2, 'DodoV2'); | ||||
|         case ERC20BridgeSource.Linkswap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'Linkswap'); | ||||
|         case ERC20BridgeSource.PancakeSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwap'); | ||||
|         case ERC20BridgeSource.PancakeSwapV2: | ||||
| @@ -143,8 +150,12 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Curve, 'xSigma'); | ||||
|         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'); | ||||
|         case ERC20BridgeSource.UniswapV3: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV3, 'UniswapV3'); | ||||
|         case ERC20BridgeSource.KyberDmm: | ||||
| @@ -159,12 +170,16 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s | ||||
|             return encodeBridgeSourceId(BridgeProtocol.CurveV2, 'CurveV2'); | ||||
|         case ERC20BridgeSource.WaultSwap: | ||||
|             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: | ||||
| @@ -183,32 +198,10 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SpookySwap'); | ||||
|         case ERC20BridgeSource.MorpheusSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MorpheusSwap'); | ||||
|         case ERC20BridgeSource.Yoshi: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'Yoshi'); | ||||
|         case ERC20BridgeSource.AaveV2: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.AaveV2, 'AaveV2'); | ||||
|         case ERC20BridgeSource.Compound: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Compound, 'Compound'); | ||||
|         case ERC20BridgeSource.Geist: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.AaveV2, 'Geist'); | ||||
|         case ERC20BridgeSource.MobiusMoney: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Nerve, 'MobiusMoney'); | ||||
|         case ERC20BridgeSource.BiSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'BiSwap'); | ||||
|         case ERC20BridgeSource.MDex: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MDex'); | ||||
|         case ERC20BridgeSource.KnightSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'KnightSwap'); | ||||
|         case ERC20BridgeSource.GMX: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.GMX, 'GMX'); | ||||
|         case ERC20BridgeSource.Platypus: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Platypus, 'Platypus'); | ||||
|         case ERC20BridgeSource.MeshSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MeshSwap'); | ||||
|         case ERC20BridgeSource.BancorV3: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.BancorV3, 'BancorV3'); | ||||
|         case ERC20BridgeSource.Velodrome: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Velodrome, 'Velodrome'); | ||||
|         default: | ||||
|             throw new Error(AggregationError.NoBridgeForSource); | ||||
|     } | ||||
| @@ -232,6 +225,8 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|     switch (order.source) { | ||||
|         case ERC20BridgeSource.Curve: | ||||
|         case ERC20BridgeSource.CurveV2: | ||||
|         case ERC20BridgeSource.Swerve: | ||||
|         case ERC20BridgeSource.SnowSwap: | ||||
|         case ERC20BridgeSource.Nerve: | ||||
|         case ERC20BridgeSource.Synapse: | ||||
|         case ERC20BridgeSource.Belt: | ||||
| @@ -242,7 +237,6 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|         case ERC20BridgeSource.FirebirdOneSwap: | ||||
|         case ERC20BridgeSource.IronSwap: | ||||
|         case ERC20BridgeSource.ACryptos: | ||||
|         case ERC20BridgeSource.MobiusMoney: | ||||
|             const curveFillData = (order as OptimizedMarketBridgeOrder<CurveFillData>).fillData; | ||||
|             bridgeData = encoder.encode([ | ||||
|                 curveFillData.pool.poolAddress, | ||||
| @@ -257,18 +251,9 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|             bridgeData = encoder.encode([balancerFillData.poolAddress]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.BalancerV2: | ||||
|             { | ||||
|                 const balancerV2FillData = (order as OptimizedMarketBridgeOrder<BalancerV2BatchSwapFillData>).fillData; | ||||
|                 bridgeData = encoder.encode([ | ||||
|                     balancerV2FillData.vault, | ||||
|                     balancerV2FillData.swapSteps, | ||||
|                     balancerV2FillData.assets, | ||||
|                 ]); | ||||
|             } | ||||
|             break; | ||||
|         case ERC20BridgeSource.Beethovenx: | ||||
|             const beethovenFillData = (order as OptimizedMarketBridgeOrder<BalancerV2FillData>).fillData; | ||||
|             const { vault, poolId } = beethovenFillData; | ||||
|             const balancerV2FillData = (order as OptimizedMarketBridgeOrder<BalancerV2FillData>).fillData; | ||||
|             const { vault, poolId } = balancerV2FillData; | ||||
|             bridgeData = encoder.encode([vault, poolId]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Bancor: | ||||
| @@ -278,30 +263,34 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|         case ERC20BridgeSource.UniswapV2: | ||||
|         case ERC20BridgeSource.SushiSwap: | ||||
|         case ERC20BridgeSource.CryptoCom: | ||||
|         case ERC20BridgeSource.Linkswap: | ||||
|         case ERC20BridgeSource.PancakeSwap: | ||||
|         case ERC20BridgeSource.PancakeSwapV2: | ||||
|         case ERC20BridgeSource.BakerySwap: | ||||
|         case ERC20BridgeSource.ApeSwap: | ||||
|         case ERC20BridgeSource.CafeSwap: | ||||
|         case ERC20BridgeSource.CheeseSwap: | ||||
|         case ERC20BridgeSource.JulSwap: | ||||
|         case ERC20BridgeSource.QuickSwap: | ||||
|         case ERC20BridgeSource.ComethSwap: | ||||
|         case ERC20BridgeSource.Dfyn: | ||||
|         case ERC20BridgeSource.WaultSwap: | ||||
|         case ERC20BridgeSource.Polydex: | ||||
|         case ERC20BridgeSource.ShibaSwap: | ||||
|         case ERC20BridgeSource.JetSwap: | ||||
|         case ERC20BridgeSource.Pangolin: | ||||
|         case ERC20BridgeSource.TraderJoe: | ||||
|         case ERC20BridgeSource.UbeSwap: | ||||
|         case ERC20BridgeSource.SpiritSwap: | ||||
|         case ERC20BridgeSource.SpookySwap: | ||||
|         case ERC20BridgeSource.MorpheusSwap: | ||||
|         case ERC20BridgeSource.BiSwap: | ||||
|         case ERC20BridgeSource.MDex: | ||||
|         case ERC20BridgeSource.KnightSwap: | ||||
|         case ERC20BridgeSource.Yoshi: | ||||
|         case ERC20BridgeSource.MeshSwap: | ||||
|             const uniswapV2FillData = (order as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData; | ||||
|             bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Kyber: | ||||
|             const kyberFillData = (order as OptimizedMarketBridgeOrder<KyberFillData>).fillData; | ||||
|             bridgeData = encoder.encode([kyberFillData.networkProxy, kyberFillData.hint]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Mooniswap: | ||||
|             const mooniswapFillData = (order as OptimizedMarketBridgeOrder<MooniswapFillData>).fillData; | ||||
|             bridgeData = encoder.encode([mooniswapFillData.poolAddress]); | ||||
| @@ -331,6 +320,10 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|             const uniFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData; | ||||
|             bridgeData = encoder.encode([uniFillData.router]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Eth2Dai: | ||||
|             const oasisFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData; | ||||
|             bridgeData = encoder.encode([oasisFillData.router]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.MStable: | ||||
|             const mStableFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData; | ||||
|             bridgeData = encoder.encode([mStableFillData.router]); | ||||
| @@ -353,7 +346,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|             break; | ||||
|         case ERC20BridgeSource.Lido: | ||||
|             const lidoFillData = (order as OptimizedMarketBridgeOrder<LidoFillData>).fillData; | ||||
|             bridgeData = encoder.encode([lidoFillData.stEthTokenAddress, lidoFillData.wstEthTokenAddress]); | ||||
|             bridgeData = encoder.encode([lidoFillData.stEthTokenAddress]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.AaveV2: | ||||
|             const aaveFillData = (order as OptimizedMarketBridgeOrder<AaveV2FillData>).fillData; | ||||
| @@ -363,35 +356,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|             const compoundFillData = (order as OptimizedMarketBridgeOrder<CompoundFillData>).fillData; | ||||
|             bridgeData = encoder.encode([compoundFillData.cToken]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Geist: | ||||
|             const geistFillData = (order as OptimizedMarketBridgeOrder<GeistFillData>).fillData; | ||||
|             bridgeData = encoder.encode([geistFillData.lendingPool, geistFillData.gToken]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.GMX: | ||||
|             const gmxFillData = (order as OptimizedMarketBridgeOrder<GMXFillData>).fillData; | ||||
|             bridgeData = encoder.encode([ | ||||
|                 gmxFillData.router, | ||||
|                 gmxFillData.reader, | ||||
|                 gmxFillData.vault, | ||||
|                 gmxFillData.tokenAddressPath, | ||||
|             ]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Platypus: | ||||
|             const platypusFillData = (order as OptimizedMarketBridgeOrder<PlatypusFillData>).fillData; | ||||
|             bridgeData = encoder.encode([ | ||||
|                 platypusFillData.router, | ||||
|                 platypusFillData.pool, | ||||
|                 platypusFillData.tokenAddressPath, | ||||
|             ]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.BancorV3: | ||||
|             const bancorV3FillData = (order as OptimizedMarketBridgeOrder<BancorFillData>).fillData; | ||||
|             bridgeData = encoder.encode([bancorV3FillData.networkAddress, bancorV3FillData.path]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Velodrome: | ||||
|             const velodromeFillData = (order as OptimizedMarketBridgeOrder<VelodromeFillData>).fillData; | ||||
|             bridgeData = encoder.encode([velodromeFillData.router, velodromeFillData.stable]); | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             throw new Error(AggregationError.NoBridgeForSource); | ||||
|     } | ||||
| @@ -422,14 +387,11 @@ function createFinalBridgeOrderFillDataFromCollapsedFill(fill: CollapsedFill): F | ||||
|     switch (fill.source) { | ||||
|         case ERC20BridgeSource.UniswapV3: { | ||||
|             const fd = fill.fillData as UniswapV3FillData; | ||||
|             const { uniswapPath, gasUsed } = getBestUniswapV3PathAmountForInputAmount(fd, fill.input); | ||||
|             const finalFillData: FinalUniswapV3FillData = { | ||||
|             return { | ||||
|                 router: fd.router, | ||||
|                 tokenAddressPath: fd.tokenAddressPath, | ||||
|                 uniswapPath, | ||||
|                 gasUsed, | ||||
|                 uniswapPath: getBestUniswapV3PathForInputAmount(fd, fill.input), | ||||
|             }; | ||||
|             return finalFillData; | ||||
|         } | ||||
|         default: | ||||
|             break; | ||||
| @@ -437,21 +399,18 @@ function createFinalBridgeOrderFillDataFromCollapsedFill(fill: CollapsedFill): F | ||||
|     return fill.fillData; | ||||
| } | ||||
|  | ||||
| function getBestUniswapV3PathAmountForInputAmount( | ||||
|     fillData: UniswapV3FillData, | ||||
|     inputAmount: BigNumber, | ||||
| ): UniswapV3PathAmount { | ||||
| function getBestUniswapV3PathForInputAmount(fillData: UniswapV3FillData, inputAmount: BigNumber): string { | ||||
|     if (fillData.pathAmounts.length === 0) { | ||||
|         throw new Error(`No Uniswap V3 paths`); | ||||
|     } | ||||
|     // Find the best path that can satisfy `inputAmount`. | ||||
|     // Assumes `fillData.pathAmounts` is sorted ascending. | ||||
|     for (const pathAmount of fillData.pathAmounts) { | ||||
|         if (pathAmount.inputAmount.gte(inputAmount)) { | ||||
|             return pathAmount; | ||||
|     for (const { inputAmount: pathInputAmount, uniswapPath } of fillData.pathAmounts) { | ||||
|         if (pathInputAmount.gte(inputAmount)) { | ||||
|             return uniswapPath; | ||||
|         } | ||||
|     } | ||||
|     return fillData.pathAmounts[fillData.pathAmounts.length - 1]; | ||||
|     return fillData.pathAmounts[fillData.pathAmounts.length - 1].uniswapPath; | ||||
| } | ||||
|  | ||||
| export function getMakerTakerTokens(opts: CreateOrderFromPathOpts): [string, string] { | ||||
| @@ -477,8 +436,6 @@ const balancerV2Encoder = AbiEncoder.create([ | ||||
| ]); | ||||
| const routerAddressPathEncoder = AbiEncoder.create('(address,address[])'); | ||||
| const tokenAddressEncoder = AbiEncoder.create([{ name: 'tokenAddress', type: 'address' }]); | ||||
| const gmxAddressPathEncoder = AbiEncoder.create('(address,address,address,address[])'); | ||||
| const platypusAddressPathEncoder = AbiEncoder.create('(address,address[],address[])'); | ||||
|  | ||||
| export const BRIDGE_ENCODERS: { | ||||
|     [key in Exclude< | ||||
| @@ -490,6 +447,10 @@ export const BRIDGE_ENCODERS: { | ||||
|         { name: 'provider', type: 'address' }, | ||||
|         { name: 'data', type: 'bytes' }, | ||||
|     ]), | ||||
|     [ERC20BridgeSource.Kyber]: AbiEncoder.create([ | ||||
|         { name: 'kyberNetworkProxy', type: 'address' }, | ||||
|         { name: 'hint', type: 'bytes' }, | ||||
|     ]), | ||||
|     [ERC20BridgeSource.Dodo]: AbiEncoder.create([ | ||||
|         { name: 'helper', type: 'address' }, | ||||
|         { name: 'poolAddress', type: 'address' }, | ||||
| @@ -502,6 +463,8 @@ export const BRIDGE_ENCODERS: { | ||||
|     // Curve like | ||||
|     [ERC20BridgeSource.Curve]: curveEncoder, | ||||
|     [ERC20BridgeSource.CurveV2]: curveEncoder, | ||||
|     [ERC20BridgeSource.Swerve]: curveEncoder, | ||||
|     [ERC20BridgeSource.SnowSwap]: curveEncoder, | ||||
|     [ERC20BridgeSource.Nerve]: curveEncoder, | ||||
|     [ERC20BridgeSource.Synapse]: curveEncoder, | ||||
|     [ERC20BridgeSource.Belt]: curveEncoder, | ||||
| @@ -512,27 +475,18 @@ export const BRIDGE_ENCODERS: { | ||||
|     [ERC20BridgeSource.FirebirdOneSwap]: curveEncoder, | ||||
|     [ERC20BridgeSource.IronSwap]: curveEncoder, | ||||
|     [ERC20BridgeSource.ACryptos]: curveEncoder, | ||||
|     [ERC20BridgeSource.MobiusMoney]: curveEncoder, | ||||
|     // UniswapV2 like, (router, address[]) | ||||
|     [ERC20BridgeSource.Bancor]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.BancorV3]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.UniswapV2]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.SushiSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.Linkswap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.ShibaSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.Pangolin]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.TraderJoe]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.SpiritSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.SpookySwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.MorpheusSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.BiSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.MDex]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.KnightSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.Yoshi]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.MeshSwap]: routerAddressPathEncoder, | ||||
|     // Avalanche | ||||
|     [ERC20BridgeSource.GMX]: gmxAddressPathEncoder, | ||||
|     [ERC20BridgeSource.Platypus]: platypusAddressPathEncoder, | ||||
|     // Celo | ||||
|     [ERC20BridgeSource.UbeSwap]: routerAddressPathEncoder, | ||||
|     // BSC | ||||
| @@ -540,48 +494,37 @@ export const BRIDGE_ENCODERS: { | ||||
|     [ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.ApeSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.CafeSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.CheeseSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.JulSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.WaultSwap]: routerAddressPathEncoder, | ||||
|     // Polygon | ||||
|     [ERC20BridgeSource.QuickSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.ComethSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.Dfyn]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.Polydex]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.JetSwap]: routerAddressPathEncoder, | ||||
|     // Generic pools | ||||
|     [ERC20BridgeSource.Shell]: poolEncoder, | ||||
|     [ERC20BridgeSource.Component]: poolEncoder, | ||||
|     [ERC20BridgeSource.Mooniswap]: poolEncoder, | ||||
|     [ERC20BridgeSource.Eth2Dai]: poolEncoder, | ||||
|     [ERC20BridgeSource.MStable]: poolEncoder, | ||||
|     [ERC20BridgeSource.Balancer]: poolEncoder, | ||||
|     [ERC20BridgeSource.Cream]: poolEncoder, | ||||
|     [ERC20BridgeSource.Uniswap]: poolEncoder, | ||||
|     // Custom integrations | ||||
|     [ERC20BridgeSource.MakerPsm]: makerPsmEncoder, | ||||
|     [ERC20BridgeSource.BalancerV2]: AbiEncoder.create([ | ||||
|         { name: 'vault', type: 'address' }, | ||||
|         { | ||||
|             name: 'swapSteps', | ||||
|             type: 'tuple[]', | ||||
|             components: [ | ||||
|                 { name: 'poolId', type: 'bytes32' }, | ||||
|                 { name: 'assetInIndex', type: 'uint256' }, | ||||
|                 { name: 'assetOutIndex', type: 'uint256' }, | ||||
|                 { name: 'amount', type: 'uint256' }, | ||||
|                 { name: 'userData', type: 'bytes' }, | ||||
|             ], | ||||
|         }, | ||||
|         { name: 'assets', type: 'address[]' }, | ||||
|     ]), | ||||
|     [ERC20BridgeSource.BalancerV2]: balancerV2Encoder, | ||||
|     [ERC20BridgeSource.Beethovenx]: balancerV2Encoder, | ||||
|     [ERC20BridgeSource.UniswapV3]: AbiEncoder.create([ | ||||
|         { name: 'router', type: 'address' }, | ||||
|         { name: 'path', type: 'bytes' }, | ||||
|     ]), | ||||
|     [ERC20BridgeSource.KyberDmm]: AbiEncoder.create('(address,address[],address[])'), | ||||
|     [ERC20BridgeSource.Lido]: AbiEncoder.create('(address,address)'), | ||||
|     [ERC20BridgeSource.Lido]: AbiEncoder.create('(address)'), | ||||
|     [ERC20BridgeSource.AaveV2]: AbiEncoder.create('(address,address)'), | ||||
|     [ERC20BridgeSource.Compound]: AbiEncoder.create('(address)'), | ||||
|     [ERC20BridgeSource.Geist]: AbiEncoder.create('(address,address)'), | ||||
|     [ERC20BridgeSource.Velodrome]: AbiEncoder.create('(address,bool)'), | ||||
| }; | ||||
|  | ||||
| function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] { | ||||
|   | ||||
| @@ -122,8 +122,17 @@ export class Path { | ||||
|                 ++i; | ||||
|                 continue; | ||||
|             } | ||||
|             // If there are contiguous bridge orders, we can batch them together. | ||||
|             // TODO jacob pretty sure this is from DFB and we can remove | ||||
|             const contiguousBridgeFills = [collapsedFills[i]]; | ||||
|             for (let j = i + 1; j < collapsedFills.length; ++j) { | ||||
|                 if (collapsedFills[j].source === ERC20BridgeSource.Native) { | ||||
|                     break; | ||||
|                 } | ||||
|                 contiguousBridgeFills.push(collapsedFills[j]); | ||||
|             } | ||||
|  | ||||
|             this.orders.push(createBridgeOrder(collapsedFills[i], makerToken, takerToken, opts.side)); | ||||
|             this.orders.push(createBridgeOrder(contiguousBridgeFills[0], makerToken, takerToken, opts.side)); | ||||
|             i += 1; | ||||
|         } | ||||
|         return this as CollapsedPath; | ||||
|   | ||||
| @@ -76,12 +76,11 @@ function findRoutesAndCreateOptimalPath( | ||||
|     opts: PathPenaltyOpts, | ||||
|     fees: FeeSchedule, | ||||
|     neonRouterNumSamples: number, | ||||
|     vipSourcesSet: Set<ERC20BridgeSource>, | ||||
| ): { allSourcesPath: Path | undefined; vipSourcesPath: Path | undefined } | undefined { | ||||
| ): Path | undefined { | ||||
|     // Currently the rust router is unable to handle 1 base unit sized quotes and will error out | ||||
|     // To avoid flooding the logs with these errors we just return an insufficient liquidity error | ||||
|     // which is how the JS router handles these quotes today | ||||
|     if (input.isLessThanOrEqualTo(ONE_BASE_UNIT)) { | ||||
|     if (input.eq(ONE_BASE_UNIT)) { | ||||
|         return undefined; | ||||
|     } | ||||
|  | ||||
| @@ -95,127 +94,6 @@ function findRoutesAndCreateOptimalPath( | ||||
|         return fills[0]; | ||||
|     }; | ||||
|  | ||||
|     const createPathFromStrategy = (sourcesRustRoute: Float64Array, sourcesOutputAmounts: Float64Array) => { | ||||
|         const routesAndSamplesAndOutputs = _.zip( | ||||
|             sourcesRustRoute, | ||||
|             samplesAndNativeOrdersWithResults, | ||||
|             sourcesOutputAmounts, | ||||
|             sampleSourcePathIds, | ||||
|         ); | ||||
|         const adjustedFills: Fill[] = []; | ||||
|         const totalRoutedAmount = BigNumber.sum(...sourcesRustRoute); | ||||
|  | ||||
|         const scale = input.dividedBy(totalRoutedAmount); | ||||
|         for (const [ | ||||
|             routeInput, | ||||
|             routeSamplesAndNativeOrders, | ||||
|             outputAmount, | ||||
|             sourcePathId, | ||||
|         ] of routesAndSamplesAndOutputs) { | ||||
|             if (!Number.isFinite(outputAmount)) { | ||||
|                 DEFAULT_WARNING_LOGGER(rustArgs, `neon-router: invalid route outputAmount ${outputAmount}`); | ||||
|                 return undefined; | ||||
|             } | ||||
|             if (!routeInput || !routeSamplesAndNativeOrders || !outputAmount) { | ||||
|                 continue; | ||||
|             } | ||||
|             // TODO(kimpers): [TKR-241] amounts are sometimes clipped in the router due to precision loss for number/f64 | ||||
|             // we can work around it by scaling it and rounding up. However now we end up with a total amount of a couple base units too much | ||||
|             const rustInputAdjusted = BigNumber.min( | ||||
|                 new BigNumber(routeInput).multipliedBy(scale).integerValue(BigNumber.ROUND_CEIL), | ||||
|                 input, | ||||
|             ); | ||||
|  | ||||
|             const current = routeSamplesAndNativeOrders[routeSamplesAndNativeOrders.length - 1]; | ||||
|             if (!isDexSample(current)) { | ||||
|                 const nativeFill = nativeOrdersToFills( | ||||
|                     side, | ||||
|                     [current], | ||||
|                     rustInputAdjusted, | ||||
|                     opts.outputAmountPerEth, | ||||
|                     opts.inputAmountPerEth, | ||||
|                     fees, | ||||
|                     false, | ||||
|                 )[0] as Fill | undefined; | ||||
|                 // Note: If the order has an adjusted rate of less than or equal to 0 it will be skipped | ||||
|                 // and nativeFill will be `undefined` | ||||
|                 if (nativeFill) { | ||||
|                     // NOTE: For Limit/RFQ orders we are done here. No need to scale output | ||||
|                     adjustedFills.push({ ...nativeFill, sourcePathId: sourcePathId ?? hexUtils.random() }); | ||||
|                 } | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // NOTE: For DexSamples only | ||||
|             let fill = createFill(current); | ||||
|             if (!fill) { | ||||
|                 continue; | ||||
|             } | ||||
|             const routeSamples = routeSamplesAndNativeOrders as Array<DexSample<FillData>>; | ||||
|             // Descend to approach a closer fill for fillData which may not be consistent | ||||
|             // throughout the path (UniswapV3) and for a closer guesstimate at | ||||
|             // gas used | ||||
|  | ||||
|             assert.assert(routeSamples.length >= 1, 'Found no sample to use for source'); | ||||
|             for (let k = routeSamples.length - 1; k >= 0; k--) { | ||||
|                 if (k === 0) { | ||||
|                     fill = createFill(routeSamples[0]) ?? fill; | ||||
|                 } | ||||
|                 if (rustInputAdjusted.isGreaterThan(routeSamples[k].input)) { | ||||
|                     const left = routeSamples[k]; | ||||
|                     const right = routeSamples[k + 1]; | ||||
|                     if (left && right) { | ||||
|                         fill = | ||||
|                             createFill({ | ||||
|                                 ...right, // default to the greater (for gas used) | ||||
|                                 input: rustInputAdjusted, | ||||
|                                 output: new BigNumber(outputAmount), | ||||
|                             }) ?? fill; | ||||
|                     } else { | ||||
|                         assert.assert(Boolean(left || right), 'No valid sample to use'); | ||||
|                         fill = createFill(left || right) ?? fill; | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // TODO(kimpers): remove once we have solved the rounding/precision loss issues in the Rust router | ||||
|             const maxSampledOutput = BigNumber.max(...routeSamples.map(s => s.output)); | ||||
|             // Scale output by scale factor but never go above the largest sample in sell quotes (unknown liquidity)  or below 1 base unit (unfillable) | ||||
|             const scaleOutput = (output: BigNumber) => { | ||||
|                 // Don't try to scale 0 output as it will be clamped to 1 | ||||
|                 if (output.eq(ZERO_AMOUNT)) { | ||||
|                     return output; | ||||
|                 } | ||||
|  | ||||
|                 const scaled = output | ||||
|                     .times(scale) | ||||
|                     .decimalPlaces(0, side === MarketOperation.Sell ? BigNumber.ROUND_FLOOR : BigNumber.ROUND_CEIL); | ||||
|                 const capped = MarketOperation.Sell ? BigNumber.min(scaled, maxSampledOutput) : scaled; | ||||
|  | ||||
|                 return BigNumber.max(capped, 1); | ||||
|             }; | ||||
|  | ||||
|             adjustedFills.push({ | ||||
|                 ...fill, | ||||
|                 input: rustInputAdjusted, | ||||
|                 output: scaleOutput(fill.output), | ||||
|                 adjustedOutput: scaleOutput(fill.adjustedOutput), | ||||
|                 index: 0, | ||||
|                 parent: undefined, | ||||
|                 sourcePathId: sourcePathId ?? hexUtils.random(), | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         if (adjustedFills.length === 0) { | ||||
|             return undefined; | ||||
|         } | ||||
|  | ||||
|         const pathFromRustInputs = Path.create(side, adjustedFills, input, opts); | ||||
|  | ||||
|         return pathFromRustInputs; | ||||
|     }; | ||||
|  | ||||
|     const samplesAndNativeOrdersWithResults: Array<DexSample[] | NativeOrderWithFillableAmounts[]> = []; | ||||
|     const serializedPaths: SerializedPath[] = []; | ||||
|     const sampleSourcePathIds: string[] = []; | ||||
| @@ -227,9 +105,8 @@ function findRoutesAndCreateOptimalPath( | ||||
|         const sourcePathId = hexUtils.random(); | ||||
|         const singleSourceSamplesWithOutput = [...singleSourceSamples]; | ||||
|         for (let i = singleSourceSamples.length - 1; i >= 0; i--) { | ||||
|             const currentOutput = singleSourceSamples[i].output; | ||||
|             if (currentOutput.isZero() || !currentOutput.isFinite()) { | ||||
|                 // Remove trailing 0/invalid output samples | ||||
|             if (singleSourceSamples[i].output.isZero()) { | ||||
|                 // Remove trailing 0 output samples | ||||
|                 singleSourceSamplesWithOutput.pop(); | ||||
|             } else { | ||||
|                 break; | ||||
| @@ -259,7 +136,6 @@ function findRoutesAndCreateOptimalPath( | ||||
|                 inputs: [], | ||||
|                 outputs: [], | ||||
|                 outputFees: [], | ||||
|                 isVip: vipSourcesSet.has(singleSourceSamplesWithOutput[0]?.source), | ||||
|             }, | ||||
|         ); | ||||
|  | ||||
| @@ -318,7 +194,6 @@ function findRoutesAndCreateOptimalPath( | ||||
|             inputs, | ||||
|             outputs, | ||||
|             outputFees, | ||||
|             isVip: true, | ||||
|         }; | ||||
|  | ||||
|         samplesAndNativeOrdersWithResults.push([nativeOrder]); | ||||
| @@ -337,42 +212,129 @@ function findRoutesAndCreateOptimalPath( | ||||
|     }; | ||||
|  | ||||
|     const allSourcesRustRoute = new Float64Array(rustArgs.pathsIn.length); | ||||
|     const allSourcesOutputAmounts = new Float64Array(rustArgs.pathsIn.length); | ||||
|     const vipSourcesRustRoute = new Float64Array(rustArgs.pathsIn.length); | ||||
|     const vipSourcesOutputAmounts = new Float64Array(rustArgs.pathsIn.length); | ||||
|  | ||||
|     route( | ||||
|         rustArgs, | ||||
|         allSourcesRustRoute, | ||||
|         allSourcesOutputAmounts, | ||||
|         vipSourcesRustRoute, | ||||
|         vipSourcesOutputAmounts, | ||||
|         neonRouterNumSamples, | ||||
|     ); | ||||
|     const strategySourcesOutputAmounts = new Float64Array(rustArgs.pathsIn.length); | ||||
|     route(rustArgs, allSourcesRustRoute, strategySourcesOutputAmounts, neonRouterNumSamples); | ||||
|     assert.assert( | ||||
|         rustArgs.pathsIn.length === allSourcesRustRoute.length, | ||||
|         'different number of sources in the Router output than the input', | ||||
|     ); | ||||
|     assert.assert( | ||||
|         rustArgs.pathsIn.length === allSourcesOutputAmounts.length, | ||||
|         'different number of sources in the Router output amounts results than the input', | ||||
|     ); | ||||
|     assert.assert( | ||||
|         rustArgs.pathsIn.length === vipSourcesRustRoute.length, | ||||
|         'different number of sources in the Router output than the input', | ||||
|     ); | ||||
|     assert.assert( | ||||
|         rustArgs.pathsIn.length === vipSourcesOutputAmounts.length, | ||||
|         rustArgs.pathsIn.length === strategySourcesOutputAmounts.length, | ||||
|         'different number of sources in the Router output amounts results than the input', | ||||
|     ); | ||||
|  | ||||
|     const allSourcesPath = createPathFromStrategy(allSourcesRustRoute, allSourcesOutputAmounts); | ||||
|     const vipSourcesPath = createPathFromStrategy(vipSourcesRustRoute, vipSourcesOutputAmounts); | ||||
|     const routesAndSamplesAndOutputs = _.zip( | ||||
|         allSourcesRustRoute, | ||||
|         samplesAndNativeOrdersWithResults, | ||||
|         strategySourcesOutputAmounts, | ||||
|         sampleSourcePathIds, | ||||
|     ); | ||||
|     const adjustedFills: Fill[] = []; | ||||
|     const totalRoutedAmount = BigNumber.sum(...allSourcesRustRoute); | ||||
|  | ||||
|     return { | ||||
|         allSourcesPath, | ||||
|         vipSourcesPath, | ||||
|     }; | ||||
|     const scale = input.dividedBy(totalRoutedAmount); | ||||
|     for (const [routeInput, routeSamplesAndNativeOrders, outputAmount, sourcePathId] of routesAndSamplesAndOutputs) { | ||||
|         if (!Number.isFinite(outputAmount)) { | ||||
|             DEFAULT_WARNING_LOGGER(rustArgs, `neon-router: invalid route outputAmount ${outputAmount}`); | ||||
|             return undefined; | ||||
|         } | ||||
|         if (!routeInput || !routeSamplesAndNativeOrders || !outputAmount) { | ||||
|             continue; | ||||
|         } | ||||
|         // TODO(kimpers): [TKR-241] amounts are sometimes clipped in the router due to precision loss for number/f64 | ||||
|         // we can work around it by scaling it and rounding up. However now we end up with a total amount of a couple base units too much | ||||
|         const rustInputAdjusted = BigNumber.min( | ||||
|             new BigNumber(routeInput).multipliedBy(scale).integerValue(BigNumber.ROUND_CEIL), | ||||
|             input, | ||||
|         ); | ||||
|  | ||||
|         const current = routeSamplesAndNativeOrders[routeSamplesAndNativeOrders.length - 1]; | ||||
|         if (!isDexSample(current)) { | ||||
|             const nativeFill = nativeOrdersToFills( | ||||
|                 side, | ||||
|                 [current], | ||||
|                 rustInputAdjusted, | ||||
|                 opts.outputAmountPerEth, | ||||
|                 opts.inputAmountPerEth, | ||||
|                 fees, | ||||
|                 false, | ||||
|             )[0] as Fill | undefined; | ||||
|             // Note: If the order has an adjusted rate of less than or equal to 0 it will be skipped | ||||
|             // and nativeFill will be `undefined` | ||||
|             if (nativeFill) { | ||||
|                 // NOTE: For Limit/RFQ orders we are done here. No need to scale output | ||||
|                 adjustedFills.push({ ...nativeFill, sourcePathId: sourcePathId ?? hexUtils.random() }); | ||||
|             } | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         // NOTE: For DexSamples only | ||||
|         let fill = createFill(current); | ||||
|         if (!fill) { | ||||
|             continue; | ||||
|         } | ||||
|         const routeSamples = routeSamplesAndNativeOrders as Array<DexSample<FillData>>; | ||||
|         // Descend to approach a closer fill for fillData which may not be consistent | ||||
|         // throughout the path (UniswapV3) and for a closer guesstimate at | ||||
|         // gas used | ||||
|  | ||||
|         assert.assert(routeSamples.length >= 1, 'Found no sample to use for source'); | ||||
|         for (let k = routeSamples.length - 1; k >= 0; k--) { | ||||
|             if (k === 0) { | ||||
|                 fill = createFill(routeSamples[0]) ?? fill; | ||||
|             } | ||||
|             if (rustInputAdjusted.isGreaterThan(routeSamples[k].input)) { | ||||
|                 const left = routeSamples[k]; | ||||
|                 const right = routeSamples[k + 1]; | ||||
|                 if (left && right) { | ||||
|                     fill = | ||||
|                         createFill({ | ||||
|                             ...right, // default to the greater (for gas used) | ||||
|                             input: rustInputAdjusted, | ||||
|                             output: new BigNumber(outputAmount), | ||||
|                         }) ?? fill; | ||||
|                 } else { | ||||
|                     assert.assert(Boolean(left || right), 'No valid sample to use'); | ||||
|                     fill = createFill(left || right) ?? fill; | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // TODO(kimpers): remove once we have solved the rounding/precision loss issues in the Rust router | ||||
|         const maxSampledOutput = BigNumber.max(...routeSamples.map(s => s.output)); | ||||
|         // Scale output by scale factor but never go above the largest sample (unknown liquidity) or below 1 base unit (unfillable) | ||||
|         const scaleOutput = (output: BigNumber) => { | ||||
|             // Don't try to scale 0 output as it will be clamped to 1 | ||||
|             if (output.eq(ZERO_AMOUNT)) { | ||||
|                 return output; | ||||
|             } | ||||
|  | ||||
|             const scaled = output | ||||
|                 .times(scale) | ||||
|                 .decimalPlaces(0, side === MarketOperation.Sell ? BigNumber.ROUND_FLOOR : BigNumber.ROUND_CEIL); | ||||
|  | ||||
|             return BigNumber.max(BigNumber.min(scaled, maxSampledOutput), 1); | ||||
|         }; | ||||
|  | ||||
|         adjustedFills.push({ | ||||
|             ...fill, | ||||
|             input: rustInputAdjusted, | ||||
|             output: scaleOutput(fill.output), | ||||
|             adjustedOutput: scaleOutput(fill.adjustedOutput), | ||||
|             index: 0, | ||||
|             parent: undefined, | ||||
|             sourcePathId: sourcePathId ?? hexUtils.random(), | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     if (adjustedFills.length === 0) { | ||||
|         return undefined; | ||||
|     } | ||||
|  | ||||
|     const pathFromRustInputs = Path.create(side, adjustedFills, input, opts); | ||||
|  | ||||
|     return pathFromRustInputs; | ||||
| } | ||||
|  | ||||
| export function findOptimalRustPathFromSamples( | ||||
| @@ -386,18 +348,9 @@ export function findOptimalRustPathFromSamples( | ||||
|     neonRouterNumSamples: number, | ||||
|     samplerMetrics?: SamplerMetrics, | ||||
| ): Path | undefined { | ||||
|     const beforeTimeMs = performance.now(); | ||||
|     const sendMetrics = () => { | ||||
|         // tslint:disable-next-line: no-unused-expression | ||||
|         samplerMetrics && | ||||
|             samplerMetrics.logRouterDetails({ | ||||
|                 router: 'neon-router', | ||||
|                 type: 'total', | ||||
|                 timingMs: performance.now() - beforeTimeMs, | ||||
|             }); | ||||
|     }; | ||||
|     const vipSourcesSet = new Set(VIP_ERC20_BRIDGE_SOURCES_BY_CHAIN_ID[chainId]); | ||||
|     const paths = findRoutesAndCreateOptimalPath( | ||||
|     const beforeAllTimeMs = performance.now(); | ||||
|     let beforeTimeMs = performance.now(); | ||||
|     const allSourcesPath = findRoutesAndCreateOptimalPath( | ||||
|         side, | ||||
|         samples, | ||||
|         nativeOrders, | ||||
| @@ -405,22 +358,58 @@ export function findOptimalRustPathFromSamples( | ||||
|         opts, | ||||
|         fees, | ||||
|         neonRouterNumSamples, | ||||
|         vipSourcesSet, | ||||
|     ); | ||||
|  | ||||
|     if (!paths) { | ||||
|         sendMetrics(); | ||||
|     // tslint:disable-next-line: no-unused-expression | ||||
|     samplerMetrics && | ||||
|         samplerMetrics.logRouterDetails({ | ||||
|             router: 'neon-router', | ||||
|             type: 'all', | ||||
|             timingMs: performance.now() - beforeTimeMs, | ||||
|         }); | ||||
|     if (!allSourcesPath) { | ||||
|         return undefined; | ||||
|     } | ||||
|  | ||||
|     const { allSourcesPath, vipSourcesPath } = paths; | ||||
|     const vipSources = VIP_ERC20_BRIDGE_SOURCES_BY_CHAIN_ID[chainId]; | ||||
|  | ||||
|     if (!allSourcesPath || vipSourcesPath?.isBetterThan(allSourcesPath)) { | ||||
|         sendMetrics(); | ||||
|         return vipSourcesPath; | ||||
|     // HACK(kimpers): The Rust router currently doesn't account for VIP sources correctly | ||||
|     // we need to try to route them in isolation and compare with the results all sources | ||||
|     if (vipSources.length > 0) { | ||||
|         beforeTimeMs = performance.now(); | ||||
|         const vipSourcesSet = new Set(vipSources); | ||||
|         const vipSourcesSamples = samples.filter(s => s[0] && vipSourcesSet.has(s[0].source)); | ||||
|  | ||||
|         if (vipSourcesSamples.length > 0) { | ||||
|             const vipSourcesPath = findRoutesAndCreateOptimalPath( | ||||
|                 side, | ||||
|                 vipSourcesSamples, | ||||
|                 [], | ||||
|                 input, | ||||
|                 opts, | ||||
|                 fees, | ||||
|                 neonRouterNumSamples, | ||||
|             ); | ||||
|             // tslint:disable-next-line: no-unused-expression | ||||
|             samplerMetrics && | ||||
|                 samplerMetrics.logRouterDetails({ | ||||
|                     router: 'neon-router', | ||||
|                     type: 'vip', | ||||
|                     timingMs: performance.now() - beforeTimeMs, | ||||
|                 }); | ||||
|  | ||||
|             if (vipSourcesPath?.isBetterThan(allSourcesPath)) { | ||||
|                 return vipSourcesPath; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     // tslint:disable-next-line: no-unused-expression | ||||
|     samplerMetrics && | ||||
|         samplerMetrics.logRouterDetails({ | ||||
|             router: 'neon-router', | ||||
|             type: 'total', | ||||
|             timingMs: performance.now() - beforeAllTimeMs, | ||||
|         }); | ||||
|  | ||||
|     sendMetrics(); | ||||
|     return allSourcesPath; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { getPoolsWithTokens, parsePoolData } from 'balancer-labs-sor-v1'; | ||||
| import { Pool } from 'balancer-labs-sor-v1/dist/types'; | ||||
| import { getPoolsWithTokens, parsePoolData } from '@balancer-labs/sor'; | ||||
| import { Pool } from '@balancer-labs/sor/dist/types'; | ||||
| import { gql, request } from 'graphql-request'; | ||||
|  | ||||
| import { BALANCER_MAX_POOLS_FETCHED, BALANCER_SUBGRAPH_URL, BALANCER_TOP_POOLS_FETCHED } from '../constants'; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| 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-v1/dist/types'; | ||||
| import { Pool } from '@balancer-labs/sor/dist/types'; | ||||
| import { gql, request } from 'graphql-request'; | ||||
|  | ||||
| import { DEFAULT_WARNING_LOGGER } from '../../../constants'; | ||||
| @@ -51,7 +51,7 @@ export class BalancerV2PoolsCache extends PoolsCache { | ||||
|  | ||||
|     constructor( | ||||
|         chainId: ChainId, | ||||
|         private readonly subgraphUrl: string = BALANCER_V2_SUBGRAPH_URL_BY_CHAIN[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, | ||||
|   | ||||
| @@ -1,190 +0,0 @@ | ||||
| import { ChainId } from '@0x/contract-addresses'; | ||||
| import { BigNumber } from '@0x/utils'; | ||||
| import { | ||||
|     BalancerSDK, | ||||
|     BalancerSdkConfig, | ||||
|     formatSequence, | ||||
|     getTokenAddressesForSwap, | ||||
|     NewPath, | ||||
|     parseToPoolsDict, | ||||
|     PoolDictionary, | ||||
|     RouteProposer, | ||||
|     SwapTypes, | ||||
| } from '@balancer-labs/sdk'; | ||||
|  | ||||
| import { DEFAULT_WARNING_LOGGER } from '../../../constants'; | ||||
| import { LogFunction } from '../../../types'; | ||||
| import { BALANCER_V2_SUBGRAPH_URL_BY_CHAIN, ONE_SECOND_MS } from '../constants'; | ||||
| import { BalancerSwapInfo, BalancerSwaps } from '../types'; | ||||
|  | ||||
| import { CacheValue, EMPTY_BALANCER_SWAPS, SwapInfoCache } from './pair_swaps_cache'; | ||||
| import { SubgraphPoolDataService } from './sgPoolDataService'; | ||||
|  | ||||
| // tslint:disable-next-line:custom-no-magic-numbers | ||||
| const ONE_DAY_MS = 24 * 60 * 60 * ONE_SECOND_MS; | ||||
|  | ||||
| export interface BalancerPoolResponse { | ||||
|     poolType: string; | ||||
|     id: string; | ||||
|     tokens: Array<{ address: string }>; | ||||
|     tokensList: string[]; | ||||
| } | ||||
|  | ||||
| export class BalancerV2SwapInfoCache extends SwapInfoCache { | ||||
|     private static readonly _MAX_POOLS_PER_PATH = 4; | ||||
|     private static readonly _MAX_CANDIDATE_PATHS_PER_PAIR = 2; | ||||
|     private readonly _routeProposer: RouteProposer; | ||||
|     private readonly _poolDataService: SubgraphPoolDataService; | ||||
|  | ||||
|     constructor( | ||||
|         chainId: ChainId, | ||||
|         subgraphUrl: string | null = BALANCER_V2_SUBGRAPH_URL_BY_CHAIN[chainId], | ||||
|         private readonly _warningLogger: LogFunction = DEFAULT_WARNING_LOGGER, | ||||
|         cache: { [key: string]: CacheValue } = {}, | ||||
|     ) { | ||||
|         super(cache); | ||||
|         const config: BalancerSdkConfig = { | ||||
|             network: chainId as number, // wtf TS | ||||
|             rpcUrl: '', // Not actually used by SDK for this. | ||||
|         }; | ||||
|         const balancerSdk = new BalancerSDK(config); | ||||
|         // The RouteProposer finds paths between a token pair using direct/multihop/linearPool routes | ||||
|         this._routeProposer = balancerSdk.sor.routeProposer; | ||||
|         // Uses Subgraph to retrieve up to date pool data required for routeProposer | ||||
|         this._poolDataService = new SubgraphPoolDataService({ | ||||
|             chainId, | ||||
|             subgraphUrl, | ||||
|         }); | ||||
|         void this._loadTopPoolsAsync(); | ||||
|         // Reload the top pools every 12 hours | ||||
|         setInterval(async () => void this._loadTopPoolsAsync(), ONE_DAY_MS / 2); | ||||
|     } | ||||
|  | ||||
|     protected async _loadTopPoolsAsync(): Promise<void> { | ||||
|         const fromToSwapInfo: { | ||||
|             [from: string]: { [to: string]: BalancerSwaps }; | ||||
|         } = {}; | ||||
|  | ||||
|         // Retrieve pool data from Subgraph | ||||
|         const pools = await this._poolDataService.getPools(); | ||||
|         // timestamp is used for Element pools | ||||
|         const timestamp = Math.floor(Date.now() / ONE_SECOND_MS); | ||||
|         const poolsDict = parseToPoolsDict(pools, timestamp); | ||||
|  | ||||
|         for (const pool of pools) { | ||||
|             const { tokensList } = pool; | ||||
|             // tslint:disable-next-line: await-promise | ||||
|             await null; // This loop can be CPU heavy so yield to event loop. | ||||
|             for (const from of tokensList) { | ||||
|                 for (const to of tokensList.filter(t => t.toLowerCase() !== from.toLowerCase())) { | ||||
|                     fromToSwapInfo[from] = fromToSwapInfo[from] || {}; | ||||
|                     // If a record for pair already exists skip as all paths alreay found | ||||
|                     if (fromToSwapInfo[from][to]) { | ||||
|                         continue; | ||||
|                     } else { | ||||
|                         try { | ||||
|                             const expiresAt = Date.now() + this._cacheTimeMs; | ||||
|                             // Retrieve swap steps and assets for a token pair | ||||
|                             // This only needs to be called once per pair as all paths will be created from single call | ||||
|                             const pairSwapInfo = this._getPoolPairSwapInfo(poolsDict, from, to); | ||||
|                             fromToSwapInfo[from][to] = pairSwapInfo; | ||||
|                             this._cacheSwapInfoForPair(from, to, fromToSwapInfo[from][to], expiresAt); | ||||
|                         } catch (err) { | ||||
|                             this._warningLogger(err, `Failed to load Balancer V2 top pools`); | ||||
|                             // soldier on | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Will retrieve fresh pair and path data from Subgraph and return and array of swap info for pair.. | ||||
|      * @param takerToken Address of takerToken. | ||||
|      * @param makerToken Address of makerToken. | ||||
|      * @returns Swap data for pair consisting of assets and swap steps for ExactIn and ExactOut swap types. | ||||
|      */ | ||||
|     protected async _fetchSwapInfoForPairAsync(takerToken: string, makerToken: string): Promise<BalancerSwaps> { | ||||
|         try { | ||||
|             // retrieve up to date pools from SG | ||||
|             const pools = await this._poolDataService.getPools(); | ||||
|  | ||||
|             // timestamp is used for Element pools | ||||
|             const timestamp = Math.floor(Date.now() / ONE_SECOND_MS); | ||||
|             const poolDictionary = parseToPoolsDict(pools, timestamp); | ||||
|             return this._getPoolPairSwapInfo(poolDictionary, takerToken, makerToken); | ||||
|         } catch (e) { | ||||
|             return EMPTY_BALANCER_SWAPS; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Uses pool data from provided dictionary to find top swap paths for token pair. | ||||
|      * @param pools Dictionary of pool data. | ||||
|      * @param takerToken Address of taker token. | ||||
|      * @param makerToken Address of maker token. | ||||
|      * @returns Swap data for pair consisting of assets and swap steps for ExactIn and ExactOut swap types. | ||||
|      */ | ||||
|     private _getPoolPairSwapInfo(pools: PoolDictionary, takerToken: string, makerToken: string): BalancerSwaps { | ||||
|         /* | ||||
|         Uses Balancer SDK to construct available paths for pair. | ||||
|         Paths can be direct, i.e. both tokens are in same pool or multihop. | ||||
|         Will also create paths for the new Balancer Linear pools. | ||||
|         These are returned in order of available liquidity which is useful for filtering. | ||||
|         */ | ||||
|         const paths = this._routeProposer.getCandidatePathsFromDict( | ||||
|             takerToken, | ||||
|             makerToken, | ||||
|             SwapTypes.SwapExactIn, | ||||
|             pools, | ||||
|             BalancerV2SwapInfoCache._MAX_POOLS_PER_PATH, | ||||
|         ); | ||||
|  | ||||
|         if (paths.length === 0) { | ||||
|             return EMPTY_BALANCER_SWAPS; | ||||
|         } | ||||
|  | ||||
|         // Convert paths data to swap information suitable for queryBatchSwap. Only use top 2 liquid paths | ||||
|         return formatSwaps(paths.slice(0, BalancerV2SwapInfoCache._MAX_CANDIDATE_PATHS_PER_PAIR)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Given an array of Balancer paths, returns swap information that can be passed to queryBatchSwap. | ||||
|  * @param paths Array of Balancer paths. | ||||
|  * @returns Formatted swap data consisting of assets and swap steps for ExactIn and ExactOut swap types. | ||||
|  */ | ||||
| function formatSwaps(paths: NewPath[]): BalancerSwaps { | ||||
|     const formattedSwapsExactIn: BalancerSwapInfo[] = []; | ||||
|     const formattedSwapsExactOut: BalancerSwapInfo[] = []; | ||||
|     let assets: string[]; | ||||
|     paths.forEach(path => { | ||||
|         // Add a swap amount for each swap so we can use formatSequence. (This will be overwritten with actual amount during query) | ||||
|         path.swaps.forEach(s => (s.swapAmount = '0')); | ||||
|         const tokenAddresses = getTokenAddressesForSwap(path.swaps); | ||||
|         // Formats for both ExactIn and ExactOut swap types | ||||
|         const swapsExactIn = formatSequence(SwapTypes.SwapExactIn, path.swaps, tokenAddresses); | ||||
|         const swapsExactOut = formatSequence(SwapTypes.SwapExactOut, path.swaps, tokenAddresses); | ||||
|         assets = tokenAddresses; | ||||
|         formattedSwapsExactIn.push({ | ||||
|             assets, | ||||
|             swapSteps: swapsExactIn.map(s => ({ | ||||
|                 ...s, | ||||
|                 amount: new BigNumber(s.amount), | ||||
|             })), | ||||
|         }); | ||||
|         formattedSwapsExactOut.push({ | ||||
|             assets, | ||||
|             swapSteps: swapsExactOut.map(s => ({ | ||||
|                 ...s, | ||||
|                 amount: new BigNumber(s.amount), | ||||
|             })), | ||||
|         }); | ||||
|     }); | ||||
|     const formattedSwaps: BalancerSwaps = { | ||||
|         swapInfoExactIn: formattedSwapsExactIn, | ||||
|         swapInfoExactOut: formattedSwapsExactOut, | ||||
|     }; | ||||
|     return formattedSwaps; | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Pool } from 'balancer-labs-sor-v1/dist/types'; | ||||
| import { Pool } from '@balancer-labs/sor/dist/types'; | ||||
| import { getPoolsWithTokens, parsePoolData } from 'cream-sor'; | ||||
|  | ||||
| import { BALANCER_MAX_POOLS_FETCHED } from '../constants'; | ||||
|   | ||||
| @@ -1,91 +0,0 @@ | ||||
| import { BalancerSwaps } from '../types'; | ||||
|  | ||||
| import { ONE_HOUR_IN_SECONDS, ONE_SECOND_MS } from '../constants'; | ||||
|  | ||||
| export interface CacheValue { | ||||
|     expiresAt: number; | ||||
|     balancerSwaps: BalancerSwaps; | ||||
| } | ||||
|  | ||||
| // tslint:disable:custom-no-magic-numbers | ||||
| // Cache results for 30mins | ||||
| const DEFAULT_CACHE_TIME_MS = (ONE_HOUR_IN_SECONDS / 2) * ONE_SECOND_MS; | ||||
| const DEFAULT_TIMEOUT_MS = ONE_SECOND_MS; | ||||
| export const EMPTY_BALANCER_SWAPS = { swapInfoExactIn: [], swapInfoExactOut: [] }; | ||||
| // tslint:enable:custom-no-magic-numbers | ||||
|  | ||||
| /** | ||||
|  * Caches SwapInfo for a pair of tokens. | ||||
|  * SwapInfo includes swap steps and asset information for those swap steps. | ||||
|  */ | ||||
| export abstract class SwapInfoCache { | ||||
|     protected static _isExpired(value: CacheValue): boolean { | ||||
|         return Date.now() >= value.expiresAt; | ||||
|     } | ||||
|     constructor( | ||||
|         protected readonly _cache: { [key: string]: CacheValue }, | ||||
|         protected readonly _cacheTimeMs: number = DEFAULT_CACHE_TIME_MS, | ||||
|     ) {} | ||||
|  | ||||
|     public async getFreshPoolsForPairAsync( | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         timeoutMs: number = DEFAULT_TIMEOUT_MS, | ||||
|     ): Promise<BalancerSwaps> { | ||||
|         const timeout = new Promise<BalancerSwaps>(resolve => setTimeout(resolve, timeoutMs, [])); | ||||
|         return Promise.race([this._getAndSaveFreshSwapInfoForPairAsync(takerToken, makerToken), timeout]); | ||||
|     } | ||||
|  | ||||
|     public getCachedSwapInfoForPair( | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         ignoreExpired: boolean = true, | ||||
|     ): BalancerSwaps | undefined { | ||||
|         const key = JSON.stringify([takerToken, makerToken]); | ||||
|         const value = this._cache[key]; | ||||
|         if (ignoreExpired) { | ||||
|             return value === undefined ? EMPTY_BALANCER_SWAPS : value.balancerSwaps; | ||||
|         } | ||||
|         if (!value) { | ||||
|             return undefined; | ||||
|         } | ||||
|         if (SwapInfoCache._isExpired(value)) { | ||||
|             return undefined; | ||||
|         } | ||||
|         return value.balancerSwaps; | ||||
|     } | ||||
|  | ||||
|     public isFresh(takerToken: string, makerToken: string): boolean { | ||||
|         const cached = this.getCachedSwapInfoForPair(takerToken, makerToken, false); | ||||
|         return cached !== undefined; | ||||
|     } | ||||
|  | ||||
|     protected async _getAndSaveFreshSwapInfoForPairAsync( | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|     ): Promise<BalancerSwaps> { | ||||
|         const key = JSON.stringify([takerToken, makerToken]); | ||||
|         const value = this._cache[key]; | ||||
|         if (value === undefined || value.expiresAt >= Date.now()) { | ||||
|             const swapInfo = await this._fetchSwapInfoForPairAsync(takerToken, makerToken); | ||||
|             const expiresAt = Date.now() + this._cacheTimeMs; | ||||
|             this._cacheSwapInfoForPair(takerToken, makerToken, swapInfo, expiresAt); | ||||
|         } | ||||
|         return this._cache[key].balancerSwaps; | ||||
|     } | ||||
|  | ||||
|     protected _cacheSwapInfoForPair( | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         swapInfo: BalancerSwaps, | ||||
|         expiresAt: number, | ||||
|     ): void { | ||||
|         const key = JSON.stringify([takerToken, makerToken]); | ||||
|         this._cache[key] = { | ||||
|             expiresAt, | ||||
|             balancerSwaps: swapInfo, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     protected abstract _fetchSwapInfoForPairAsync(takerToken: string, makerToken: string): Promise<BalancerSwaps>; | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Pool } from 'balancer-labs-sor-v1/dist/types'; | ||||
| import { Pool } from '@balancer-labs/sor/dist/types'; | ||||
|  | ||||
| import { ONE_HOUR_IN_SECONDS, ONE_SECOND_MS } from '../constants'; | ||||
| export { Pool }; | ||||
|   | ||||
| @@ -1,114 +0,0 @@ | ||||
| import { ChainId } from '@0x/contract-addresses'; | ||||
| import { logUtils } from '@0x/utils'; | ||||
| import { PoolDataService, SubgraphPoolBase } from '@balancer-labs/sdk'; | ||||
| import { gql, request } from 'graphql-request'; | ||||
|  | ||||
| const queryWithLinear = gql` | ||||
|     query fetchTopPoolsWithLinear($maxPoolsFetched: Int!) { | ||||
|         pools: pools( | ||||
|             first: $maxPoolsFetched | ||||
|             where: { swapEnabled: true } | ||||
|             orderBy: totalLiquidity | ||||
|             orderDirection: desc | ||||
|         ) { | ||||
|             id | ||||
|             address | ||||
|             poolType | ||||
|             swapFee | ||||
|             totalShares | ||||
|             tokens { | ||||
|                 address | ||||
|                 balance | ||||
|                 decimals | ||||
|                 weight | ||||
|                 priceRate | ||||
|             } | ||||
|             tokensList | ||||
|             totalWeight | ||||
|             amp | ||||
|             expiryTime | ||||
|             unitSeconds | ||||
|             principalToken | ||||
|             baseToken | ||||
|             swapEnabled | ||||
|             wrappedIndex | ||||
|             mainIndex | ||||
|             lowerTarget | ||||
|             upperTarget | ||||
|         } | ||||
|     } | ||||
| `; | ||||
|  | ||||
| const queryWithOutLinear = gql` | ||||
|     query fetchTopPoolsWithoutLinear($maxPoolsFetched: Int!) { | ||||
|         pools: pools( | ||||
|             first: $maxPoolsFetched | ||||
|             where: { swapEnabled: true } | ||||
|             orderBy: totalLiquidity | ||||
|             orderDirection: desc | ||||
|         ) { | ||||
|             id | ||||
|             address | ||||
|             poolType | ||||
|             swapFee | ||||
|             totalShares | ||||
|             tokens { | ||||
|                 address | ||||
|                 balance | ||||
|                 decimals | ||||
|                 weight | ||||
|                 priceRate | ||||
|             } | ||||
|             tokensList | ||||
|             totalWeight | ||||
|             amp | ||||
|             expiryTime | ||||
|             unitSeconds | ||||
|             principalToken | ||||
|             baseToken | ||||
|             swapEnabled | ||||
|         } | ||||
|     } | ||||
| `; | ||||
|  | ||||
| const QUERY_BY_CHAIN_ID: { [chainId: number]: string } = { | ||||
|     [ChainId.Mainnet]: queryWithLinear, | ||||
|     [ChainId.Polygon]: queryWithOutLinear, | ||||
| }; | ||||
|  | ||||
| const DEFAULT_MAX_POOLS_FETCHED = 96; | ||||
|  | ||||
| /** | ||||
|  * Simple service to query required info from Subgraph for Balancer Pools. | ||||
|  * Because Balancer Subgraphs have slightly different schema depending on network the queries are adjusted as needed. | ||||
|  */ | ||||
| export class SubgraphPoolDataService implements PoolDataService { | ||||
|     private readonly _gqlQuery: string | undefined; | ||||
|  | ||||
|     constructor( | ||||
|         private readonly _config: { | ||||
|             chainId: number; | ||||
|             subgraphUrl: string | null; | ||||
|             maxPoolsFetched?: number; | ||||
|         }, | ||||
|     ) { | ||||
|         this._config.maxPoolsFetched = this._config.maxPoolsFetched || DEFAULT_MAX_POOLS_FETCHED; | ||||
|         this._gqlQuery = QUERY_BY_CHAIN_ID[this._config.chainId]; | ||||
|     } | ||||
|  | ||||
|     // tslint:disable-next-line: async-suffix | ||||
|     public async getPools(): Promise<SubgraphPoolBase[]> { | ||||
|         if (!this._gqlQuery || !this._config.subgraphUrl) { | ||||
|             return []; | ||||
|         } | ||||
|         try { | ||||
|             const { pools } = await request<{ pools: SubgraphPoolBase[] }>(this._config.subgraphUrl, this._gqlQuery, { | ||||
|                 maxPoolsFetched: this._config.maxPoolsFetched, | ||||
|             }); | ||||
|             return pools; | ||||
|         } catch (err) { | ||||
|             logUtils.warn(`Failed to fetch BalancerV2 subgraph pools: ${err.message}`); | ||||
|             return []; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -5,8 +5,9 @@ import { SamplerOverrides } from '../../types'; | ||||
| import { ERC20BridgeSamplerContract } from '../../wrappers'; | ||||
|  | ||||
| import { BancorService } from './bancor_service'; | ||||
| import { PoolsCacheMap, SamplerOperations } from './sampler_operations'; | ||||
| import { BatchedOperation, LiquidityProviderRegistry, TokenAdjacencyGraph } from './types'; | ||||
| import { PoolsCache } from './pools_cache'; | ||||
| import { SamplerOperations } from './sampler_operations'; | ||||
| import { BatchedOperation, ERC20BridgeSource, LiquidityProviderRegistry, TokenAdjacencyGraph } from './types'; | ||||
|  | ||||
| /** | ||||
|  * Generate sample amounts up to `maxFillAmount`. | ||||
| @@ -36,7 +37,7 @@ export class DexOrderSampler extends SamplerOperations { | ||||
|         public readonly chainId: ChainId, | ||||
|         _samplerContract: ERC20BridgeSamplerContract, | ||||
|         private readonly _samplerOverrides?: SamplerOverrides, | ||||
|         poolsCaches?: PoolsCacheMap, | ||||
|         poolsCaches?: { [key in ERC20BridgeSource]: PoolsCache }, | ||||
|         tokenAdjacencyGraph?: TokenAdjacencyGraph, | ||||
|         liquidityProviderRegistry?: LiquidityProviderRegistry, | ||||
|         bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined, | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import { BigNumber, logUtils } from '@0x/utils'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { AaveV2Sampler } from '../../noop_samplers/AaveV2Sampler'; | ||||
| import { GeistSampler } from '../../noop_samplers/GeistSampler'; | ||||
| import { SamplerCallResult, SignedNativeOrder } from '../../types'; | ||||
| import { ERC20BridgeSamplerContract } from '../../wrappers'; | ||||
|  | ||||
| @@ -13,8 +12,9 @@ import { BancorService } from './bancor_service'; | ||||
| import { | ||||
|     getCurveLikeInfosForPair, | ||||
|     getDodoV2Offsets, | ||||
|     getPlatypusInfoForPair, | ||||
|     getKyberOffsets, | ||||
|     getShellLikeInfosForPair, | ||||
|     isAllowedKyberReserveId, | ||||
|     isBadTokenForSource, | ||||
|     isValidAddress, | ||||
|     uniswapV2LikeRouterAddress, | ||||
| @@ -22,21 +22,17 @@ import { | ||||
| import { CompoundCTokenCache } from './compound_ctoken_cache'; | ||||
| import { | ||||
|     AAVE_V2_SUBGRAPH_URL_BY_CHAIN_ID, | ||||
|     AVALANCHE_TOKENS, | ||||
|     BALANCER_V2_VAULT_ADDRESS_BY_CHAIN, | ||||
|     BANCOR_REGISTRY_BY_CHAIN_ID, | ||||
|     BANCORV3_NETWORK_BY_CHAIN_ID, | ||||
|     BANCORV3_NETWORK_INFO_BY_CHAIN_ID, | ||||
|     BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN, | ||||
|     BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN, | ||||
|     COMPOUND_API_URL_BY_CHAIN_ID, | ||||
|     DODOV1_CONFIG_BY_CHAIN_ID, | ||||
|     DODOV2_FACTORIES_BY_CHAIN_ID, | ||||
|     GMX_READER_BY_CHAIN_ID, | ||||
|     GMX_ROUTER_BY_CHAIN_ID, | ||||
|     GMX_VAULT_BY_CHAIN_ID, | ||||
|     KYBER_CONFIG_BY_CHAIN_ID, | ||||
|     KYBER_DMM_ROUTER_BY_CHAIN_ID, | ||||
|     LIDO_INFO_BY_CHAIN, | ||||
|     LINKSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     LIQUIDITY_PROVIDER_REGISTRY_BY_CHAIN_ID, | ||||
|     MAINNET_TOKENS, | ||||
|     MAKER_PSM_INFO_BY_CHAIN_ID, | ||||
| @@ -44,18 +40,15 @@ import { | ||||
|     MOONISWAP_REGISTRIES_BY_CHAIN_ID, | ||||
|     NATIVE_FEE_TOKEN_BY_CHAIN_ID, | ||||
|     NULL_ADDRESS, | ||||
|     PLATYPUS_ROUTER_BY_CHAIN_ID, | ||||
|     NULL_BYTES, | ||||
|     SELL_SOURCE_FILTER_BY_CHAIN_ID, | ||||
|     UNISWAPV1_ROUTER_BY_CHAIN_ID, | ||||
|     UNISWAPV3_CONFIG_BY_CHAIN_ID, | ||||
|     VELODROME_ROUTER_BY_CHAIN_ID, | ||||
|     ZERO_AMOUNT, | ||||
| } from './constants'; | ||||
| import { getGeistInfoForPair } from './geist_utils'; | ||||
| import { getLiquidityProvidersForPair } from './liquidity_provider_utils'; | ||||
| import { getIntermediateTokens } from './multihop_utils'; | ||||
| import { BalancerPoolsCache, BalancerV2PoolsCache, CreamPoolsCache, PoolsCache } from './pools_cache'; | ||||
| import { BalancerV2SwapInfoCache } from './pools_cache/balancer_v2_utils_new'; | ||||
| import { SamplerContractOperation } from './sampler_contract_operation'; | ||||
| import { SamplerNoOperation } from './sampler_no_operation'; | ||||
| import { SourceFilters } from './source_filters'; | ||||
| @@ -63,8 +56,6 @@ import { | ||||
|     AaveV2FillData, | ||||
|     AaveV2Info, | ||||
|     BalancerFillData, | ||||
|     BalancerSwapInfo, | ||||
|     BalancerV2BatchSwapFillData, | ||||
|     BalancerV2FillData, | ||||
|     BalancerV2PoolInfo, | ||||
|     BancorFillData, | ||||
| @@ -75,12 +66,11 @@ import { | ||||
|     DexSample, | ||||
|     DODOFillData, | ||||
|     ERC20BridgeSource, | ||||
|     GeistFillData, | ||||
|     GeistInfo, | ||||
|     GenericRouterFillData, | ||||
|     GMXFillData, | ||||
|     HopInfo, | ||||
|     KyberDmmFillData, | ||||
|     KyberFillData, | ||||
|     KyberSamplerOpts, | ||||
|     LidoFillData, | ||||
|     LidoInfo, | ||||
|     LiquidityProviderFillData, | ||||
| @@ -88,7 +78,6 @@ import { | ||||
|     MakerPsmFillData, | ||||
|     MooniswapFillData, | ||||
|     MultiHopFillData, | ||||
|     PlatypusFillData, | ||||
|     PsmInfo, | ||||
|     ShellFillData, | ||||
|     SourceQuoteOperation, | ||||
| @@ -96,7 +85,6 @@ import { | ||||
|     TokenAdjacencyGraph, | ||||
|     UniswapV2FillData, | ||||
|     UniswapV3FillData, | ||||
|     VelodromeFillData, | ||||
| } from './types'; | ||||
|  | ||||
| /** | ||||
| @@ -111,10 +99,6 @@ export const TWO_HOP_SOURCE_FILTERS = SourceFilters.all().exclude([ | ||||
|  */ | ||||
| export const BATCH_SOURCE_FILTERS = SourceFilters.all().exclude([ERC20BridgeSource.MultiHop, ERC20BridgeSource.Native]); | ||||
|  | ||||
| export type PoolsCacheMap = { [key in Exclude<SourcesWithPoolsCache, ERC20BridgeSource.BalancerV2>]: PoolsCache } & { | ||||
|     [ERC20BridgeSource.BalancerV2]: BalancerV2SwapInfoCache | undefined; | ||||
| }; | ||||
|  | ||||
| // tslint:disable:no-inferred-empty-object-type no-unbound-method | ||||
|  | ||||
| /** | ||||
| @@ -123,7 +107,7 @@ export type PoolsCacheMap = { [key in Exclude<SourcesWithPoolsCache, ERC20Bridge | ||||
|  */ | ||||
| export class SamplerOperations { | ||||
|     public readonly liquidityProviderRegistry: LiquidityProviderRegistry; | ||||
|     public readonly poolsCaches: PoolsCacheMap; | ||||
|     public readonly poolsCaches: { [key in SourcesWithPoolsCache]: PoolsCache }; | ||||
|     public readonly aaveReservesCache: AaveV2ReservesCache | undefined; | ||||
|     public readonly compoundCTokenCache: CompoundCTokenCache | undefined; | ||||
|     protected _bancorService?: BancorService; | ||||
| @@ -138,7 +122,7 @@ export class SamplerOperations { | ||||
|     constructor( | ||||
|         public readonly chainId: ChainId, | ||||
|         protected readonly _samplerContract: ERC20BridgeSamplerContract, | ||||
|         poolsCaches?: PoolsCacheMap, | ||||
|         poolsCaches?: { [key in SourcesWithPoolsCache]: PoolsCache }, | ||||
|         protected readonly tokenAdjacencyGraph: TokenAdjacencyGraph = { default: [] }, | ||||
|         liquidityProviderRegistry: LiquidityProviderRegistry = {}, | ||||
|         bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined, | ||||
| @@ -150,16 +134,13 @@ export class SamplerOperations { | ||||
|         this.poolsCaches = poolsCaches | ||||
|             ? poolsCaches | ||||
|             : { | ||||
|                   [ERC20BridgeSource.BalancerV2]: new BalancerV2PoolsCache(chainId), | ||||
|                   [ERC20BridgeSource.Beethovenx]: new BalancerV2PoolsCache( | ||||
|                       chainId, | ||||
|                       BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN[chainId], | ||||
|                   ), | ||||
|                   [ERC20BridgeSource.Balancer]: new BalancerPoolsCache(), | ||||
|                   [ERC20BridgeSource.Cream]: new CreamPoolsCache(), | ||||
|                   [ERC20BridgeSource.BalancerV2]: | ||||
|                       BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[chainId] === NULL_ADDRESS | ||||
|                           ? undefined | ||||
|                           : new BalancerV2SwapInfoCache(chainId), | ||||
|               }; | ||||
|  | ||||
|         const aaveSubgraphUrl = AAVE_V2_SUBGRAPH_URL_BY_CHAIN_ID[chainId]; | ||||
| @@ -265,6 +246,54 @@ export class SamplerOperations { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getKyberSellQuotes( | ||||
|         kyberOpts: KyberSamplerOpts, | ||||
|         reserveOffset: BigNumber, | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         takerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Kyber, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleSellsFromKyberNetwork, | ||||
|             params: [{ ...kyberOpts, reserveOffset, hint: NULL_BYTES }, takerToken, makerToken, takerFillAmounts], | ||||
|             callback: (callResults: string, fillData: KyberFillData): BigNumber[] => { | ||||
|                 const [reserveId, hint, samples] = this._samplerContract.getABIDecodedReturnData< | ||||
|                     [string, string, BigNumber[]] | ||||
|                 >('sampleSellsFromKyberNetwork', callResults); | ||||
|                 fillData.hint = hint; | ||||
|                 fillData.reserveId = reserveId; | ||||
|                 fillData.networkProxy = kyberOpts.networkProxy; | ||||
|                 return isAllowedKyberReserveId(reserveId) ? samples : []; | ||||
|             }, | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getKyberBuyQuotes( | ||||
|         kyberOpts: KyberSamplerOpts, | ||||
|         reserveOffset: BigNumber, | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Kyber, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleBuysFromKyberNetwork, | ||||
|             params: [{ ...kyberOpts, reserveOffset, hint: NULL_BYTES }, takerToken, makerToken, makerFillAmounts], | ||||
|             callback: (callResults: string, fillData: KyberFillData): BigNumber[] => { | ||||
|                 const [reserveId, hint, samples] = this._samplerContract.getABIDecodedReturnData< | ||||
|                     [string, string, BigNumber[]] | ||||
|                 >('sampleBuysFromKyberNetwork', callResults); | ||||
|                 fillData.hint = hint; | ||||
|                 fillData.reserveId = reserveId; | ||||
|                 fillData.networkProxy = kyberOpts.networkProxy; | ||||
|                 return isAllowedKyberReserveId(reserveId) ? samples : []; | ||||
|             }, | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getKyberDmmSellQuotes( | ||||
|         router: string, | ||||
|         tokenAddressPath: string[], | ||||
| @@ -531,49 +560,6 @@ export class SamplerOperations { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getBalancerV2MultihopSellQuotes( | ||||
|         vault: string, | ||||
|         quoteSwaps: BalancerSwapInfo, // Should always be sell swap steps. | ||||
|         fillSwaps: BalancerSwapInfo, // Should always be sell swap steps. | ||||
|         takerFillAmounts: BigNumber[], | ||||
|         source: ERC20BridgeSource, | ||||
|     ): SourceQuoteOperation<BalancerV2BatchSwapFillData> { | ||||
|         const quoteSwapSteps = quoteSwaps.swapSteps.map(s => ({ | ||||
|             ...s, | ||||
|             assetInIndex: new BigNumber(s.assetInIndex), | ||||
|             assetOutIndex: new BigNumber(s.assetOutIndex), | ||||
|         })); | ||||
|         return new SamplerContractOperation({ | ||||
|             source, | ||||
|             fillData: { vault, swapSteps: fillSwaps.swapSteps, assets: fillSwaps.assets }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleMultihopSellsFromBalancerV2, | ||||
|             params: [vault, quoteSwapSteps, quoteSwaps.assets, takerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getBalancerV2MultihopBuyQuotes( | ||||
|         vault: string, | ||||
|         quoteSwaps: BalancerSwapInfo, // Should always be buy swap steps. | ||||
|         fillSwaps: BalancerSwapInfo, // Should always be a sell quote. | ||||
|         makerFillAmounts: BigNumber[], | ||||
|         source: ERC20BridgeSource, | ||||
|     ): SourceQuoteOperation<BalancerV2BatchSwapFillData> { | ||||
|         const quoteSwapSteps = quoteSwaps.swapSteps.map(s => ({ | ||||
|             ...s, | ||||
|             assetInIndex: new BigNumber(s.assetInIndex), | ||||
|             assetOutIndex: new BigNumber(s.assetOutIndex), | ||||
|         })); | ||||
|         return new SamplerContractOperation({ | ||||
|             source, | ||||
|             // NOTE: fillData is set up for sells but quote function is set up for buys. | ||||
|             fillData: { vault, swapSteps: fillSwaps.swapSteps, assets: fillSwaps.assets }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleMultihopBuysFromBalancerV2, | ||||
|             params: [vault, quoteSwapSteps, quoteSwaps.assets, makerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getBalancerV2SellQuotes( | ||||
|         poolInfo: BalancerV2PoolInfo, | ||||
|         makerToken: string, | ||||
| @@ -714,36 +700,6 @@ export class SamplerOperations { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getBancorV3SellQuotes( | ||||
|         networkAddress: string, | ||||
|         networkInfoAddress: string, | ||||
|         path: string[], | ||||
|         takerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<BancorFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.BancorV3, | ||||
|             fillData: { networkAddress, path }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleSellsFromBancorV3, | ||||
|             params: [MAINNET_TOKENS.WETH, networkInfoAddress, path, takerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getBancorV3BuyQuotes( | ||||
|         networkAddress: string, | ||||
|         networkInfoAddress: string, | ||||
|         path: string[], | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<BancorFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.BancorV3, | ||||
|             fillData: { networkAddress, path }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleBuysFromBancorV3, | ||||
|             params: [MAINNET_TOKENS.WETH, networkInfoAddress, path, makerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getMooniswapSellQuotes( | ||||
|         registry: string, | ||||
|         makerToken: string, | ||||
| @@ -811,17 +767,16 @@ export class SamplerOperations { | ||||
|             function: this._samplerContract.sampleSellsFromUniswapV3, | ||||
|             params: [quoter, tokenAddressPath, takerFillAmounts], | ||||
|             callback: (callResults: string, fillData: UniswapV3FillData): BigNumber[] => { | ||||
|                 const [paths, gasUsed, samples] = this._samplerContract.getABIDecodedReturnData< | ||||
|                     [string[], BigNumber[], BigNumber[]] | ||||
|                 >('sampleSellsFromUniswapV3', callResults); | ||||
|                 const [paths, samples] = this._samplerContract.getABIDecodedReturnData<[string[], BigNumber[]]>( | ||||
|                     'sampleSellsFromUniswapV3', | ||||
|                     callResults, | ||||
|                 ); | ||||
|                 fillData.router = router; | ||||
|                 fillData.tokenAddressPath = tokenAddressPath; | ||||
|                 fillData.pathAmounts = paths.map((uniswapPath, i) => ({ | ||||
|                     uniswapPath, | ||||
|                     inputAmount: takerFillAmounts[i], | ||||
|                     gasUsed: gasUsed[i].toNumber(), | ||||
|                 })); | ||||
|  | ||||
|                 return samples; | ||||
|             }, | ||||
|         }); | ||||
| @@ -840,15 +795,15 @@ export class SamplerOperations { | ||||
|             function: this._samplerContract.sampleBuysFromUniswapV3, | ||||
|             params: [quoter, tokenAddressPath, makerFillAmounts], | ||||
|             callback: (callResults: string, fillData: UniswapV3FillData): BigNumber[] => { | ||||
|                 const [paths, gasUsed, samples] = this._samplerContract.getABIDecodedReturnData< | ||||
|                     [string[], BigNumber[], BigNumber[]] | ||||
|                 >('sampleBuysFromUniswapV3', callResults); | ||||
|                 const [paths, samples] = this._samplerContract.getABIDecodedReturnData<[string[], BigNumber[]]>( | ||||
|                     'sampleBuysFromUniswapV3', | ||||
|                     callResults, | ||||
|                 ); | ||||
|                 fillData.router = router; | ||||
|                 fillData.tokenAddressPath = tokenAddressPath; | ||||
|                 fillData.pathAmounts = paths.map((uniswapPath, i) => ({ | ||||
|                     uniswapPath, | ||||
|                     inputAmount: makerFillAmounts[i], | ||||
|                     gasUsed: gasUsed[i].toNumber(), | ||||
|                 })); | ||||
|                 return samples; | ||||
|             }, | ||||
| @@ -1141,10 +1096,8 @@ export class SamplerOperations { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Lido, | ||||
|             fillData: { | ||||
|                 makerToken, | ||||
|                 takerToken, | ||||
|                 stEthTokenAddress: lidoInfo.stEthToken, | ||||
|                 wstEthTokenAddress: lidoInfo.wstEthToken, | ||||
|             }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleSellsFromLido, | ||||
| @@ -1161,10 +1114,8 @@ export class SamplerOperations { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Lido, | ||||
|             fillData: { | ||||
|                 makerToken, | ||||
|                 takerToken, | ||||
|                 stEthTokenAddress: lidoInfo.stEthToken, | ||||
|                 wstEthTokenAddress: lidoInfo.wstEthToken, | ||||
|             }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleBuysFromLido, | ||||
| @@ -1200,34 +1151,6 @@ export class SamplerOperations { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // tslint:disable-next-line:prefer-function-over-method | ||||
|     public getGeistSellQuotes( | ||||
|         geistInfo: GeistInfo, | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         takerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<GeistFillData> { | ||||
|         return new SamplerNoOperation({ | ||||
|             source: ERC20BridgeSource.Geist, | ||||
|             fillData: { ...geistInfo, takerToken }, | ||||
|             callback: () => GeistSampler.sampleSellsFromGeist(geistInfo, takerToken, makerToken, takerFillAmounts), | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // tslint:disable-next-line:prefer-function-over-method | ||||
|     public getGeistBuyQuotes( | ||||
|         geistInfo: GeistInfo, | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<GeistFillData> { | ||||
|         return new SamplerNoOperation({ | ||||
|             source: ERC20BridgeSource.Geist, | ||||
|             fillData: { ...geistInfo, takerToken }, | ||||
|             callback: () => GeistSampler.sampleBuysFromGeist(geistInfo, takerToken, makerToken, makerFillAmounts), | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getCompoundSellQuotes( | ||||
|         cToken: string, | ||||
|         makerToken: string, | ||||
| @@ -1258,113 +1181,6 @@ export class SamplerOperations { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getGMXSellQuotes( | ||||
|         router: string, | ||||
|         reader: string, | ||||
|         vault: string, | ||||
|         tokenAddressPath: string[], | ||||
|         takerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<GMXFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.GMX, | ||||
|             fillData: { router, reader, vault, tokenAddressPath }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleSellsFromGMX, | ||||
|             params: [reader, vault, tokenAddressPath, takerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|     public getGMXBuyQuotes( | ||||
|         router: string, | ||||
|         reader: string, | ||||
|         vault: string, | ||||
|         tokenAddressPath: string[], | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<GMXFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.GMX, | ||||
|             fillData: { router, reader, vault, tokenAddressPath }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleBuysFromGMX, | ||||
|             params: [reader, vault, tokenAddressPath, makerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getPlatypusSellQuotes( | ||||
|         router: string, | ||||
|         pool: string[], | ||||
|         tokenAddressPath: string[], | ||||
|         takerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<PlatypusFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Platypus, | ||||
|             fillData: { router, pool, tokenAddressPath }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleSellsFromPlatypus, | ||||
|             params: [pool[0], tokenAddressPath, takerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getPlatypusBuyQuotes( | ||||
|         router: string, | ||||
|         pool: string[], | ||||
|         tokenAddressPath: string[], | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<PlatypusFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Platypus, | ||||
|             fillData: { router, pool, tokenAddressPath }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleBuysFromPlatypus, | ||||
|             params: [pool[0], tokenAddressPath, makerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getVelodromeSellQuotes( | ||||
|         router: string, | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         takerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<VelodromeFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Velodrome, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleSellsFromVelodrome, | ||||
|             params: [router, takerToken, makerToken, takerFillAmounts], | ||||
|             callback: (callResults: string, fillData: VelodromeFillData): BigNumber[] => { | ||||
|                 const [isStable, samples] = this._samplerContract.getABIDecodedReturnData<[boolean, BigNumber[]]>( | ||||
|                     'sampleSellsFromVelodrome', | ||||
|                     callResults, | ||||
|                 ); | ||||
|                 fillData.router = router; | ||||
|                 fillData.stable = isStable; | ||||
|                 return samples; | ||||
|             }, | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getVelodromeBuyQuotes( | ||||
|         router: string, | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<VelodromeFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Velodrome, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleBuysFromVelodrome, | ||||
|             params: [router, takerToken, makerToken, makerFillAmounts], | ||||
|             callback: (callResults: string, fillData: VelodromeFillData): BigNumber[] => { | ||||
|                 const [isStable, samples] = this._samplerContract.getABIDecodedReturnData<[boolean, BigNumber[]]>( | ||||
|                     'sampleBuysFromVelodrome', | ||||
|                     callResults, | ||||
|                 ); | ||||
|                 fillData.router = router; | ||||
|                 fillData.stable = isStable; | ||||
|                 return samples; | ||||
|             }, | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getMedianSellRate( | ||||
|         sources: ERC20BridgeSource[], | ||||
|         makerToken: string, | ||||
| @@ -1450,7 +1266,7 @@ export class SamplerOperations { | ||||
|         takerFillAmounts: BigNumber[], | ||||
|         tokenAdjacencyGraph: TokenAdjacencyGraph = this.tokenAdjacencyGraph, | ||||
|     ): SourceQuoteOperation[] { | ||||
|         // Find the adjacent tokens in the provided token adjacency graph, | ||||
|         // Find the adjacent tokens in the provided tooken adjacency graph, | ||||
|         // e.g if this is DAI->USDC we may check for DAI->WETH->USDC | ||||
|         const intermediateTokens = getIntermediateTokens(makerToken, takerToken, tokenAdjacencyGraph); | ||||
|         // Drop out MultiHop and Native as we do not query those here. | ||||
| @@ -1463,6 +1279,8 @@ export class SamplerOperations { | ||||
|                     return []; | ||||
|                 } | ||||
|                 switch (source) { | ||||
|                     case ERC20BridgeSource.Eth2Dai: | ||||
|                         return []; | ||||
|                     case ERC20BridgeSource.Uniswap: | ||||
|                         return isValidAddress(UNISWAPV1_ROUTER_BY_CHAIN_ID[this.chainId]) | ||||
|                             ? this.getUniswapSellQuotes( | ||||
| @@ -1479,23 +1297,22 @@ export class SamplerOperations { | ||||
|                     case ERC20BridgeSource.PancakeSwapV2: | ||||
|                     case ERC20BridgeSource.BakerySwap: | ||||
|                     case ERC20BridgeSource.ApeSwap: | ||||
|                     case ERC20BridgeSource.CafeSwap: | ||||
|                     case ERC20BridgeSource.CheeseSwap: | ||||
|                     case ERC20BridgeSource.JulSwap: | ||||
|                     case ERC20BridgeSource.QuickSwap: | ||||
|                     case ERC20BridgeSource.ComethSwap: | ||||
|                     case ERC20BridgeSource.Dfyn: | ||||
|                     case ERC20BridgeSource.WaultSwap: | ||||
|                     case ERC20BridgeSource.Polydex: | ||||
|                     case ERC20BridgeSource.ShibaSwap: | ||||
|                     case ERC20BridgeSource.JetSwap: | ||||
|                     case ERC20BridgeSource.Pangolin: | ||||
|                     case ERC20BridgeSource.TraderJoe: | ||||
|                     case ERC20BridgeSource.UbeSwap: | ||||
|                     case ERC20BridgeSource.SpiritSwap: | ||||
|                     case ERC20BridgeSource.SpookySwap: | ||||
|                     case ERC20BridgeSource.Yoshi: | ||||
|                     case ERC20BridgeSource.MorpheusSwap: | ||||
|                     case ERC20BridgeSource.BiSwap: | ||||
|                     case ERC20BridgeSource.MDex: | ||||
|                     case ERC20BridgeSource.KnightSwap: | ||||
|                     case ERC20BridgeSource.MeshSwap: | ||||
|                         const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); | ||||
|                         if (!isValidAddress(uniLikeRouter)) { | ||||
|                             return []; | ||||
| @@ -1510,8 +1327,20 @@ export class SamplerOperations { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return this.getKyberDmmSellQuotes(kyberDmmRouter, [takerToken, makerToken], takerFillAmounts); | ||||
|                     case ERC20BridgeSource.Kyber: | ||||
|                         return getKyberOffsets().map(offset => | ||||
|                             this.getKyberSellQuotes( | ||||
|                                 KYBER_CONFIG_BY_CHAIN_ID[this.chainId], | ||||
|                                 offset, | ||||
|                                 makerToken, | ||||
|                                 takerToken, | ||||
|                                 takerFillAmounts, | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.Curve: | ||||
|                     case ERC20BridgeSource.CurveV2: | ||||
|                     case ERC20BridgeSource.Swerve: | ||||
|                     case ERC20BridgeSource.SnowSwap: | ||||
|                     case ERC20BridgeSource.Nerve: | ||||
|                     case ERC20BridgeSource.Synapse: | ||||
|                     case ERC20BridgeSource.Belt: | ||||
| @@ -1521,7 +1350,6 @@ export class SamplerOperations { | ||||
|                     case ERC20BridgeSource.FirebirdOneSwap: | ||||
|                     case ERC20BridgeSource.IronSwap: | ||||
|                     case ERC20BridgeSource.ACryptos: | ||||
|                     case ERC20BridgeSource.MobiusMoney: | ||||
|                         return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool => | ||||
|                             this.getCurveSellQuotes( | ||||
|                                 pool, | ||||
| @@ -1586,27 +1414,15 @@ export class SamplerOperations { | ||||
|                                 ERC20BridgeSource.Balancer, | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.BalancerV2: { | ||||
|                         const cache = this.poolsCaches[source]; | ||||
|                         if (!cache) { | ||||
|                             return []; | ||||
|                         } | ||||
|  | ||||
|                         const swaps = cache.getCachedSwapInfoForPair(takerToken, makerToken); | ||||
|                         const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         if (!swaps || vault === NULL_ADDRESS) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         // Changed to retrieve queryBatchSwap for swap steps > 1 of length | ||||
|                         return swaps.swapInfoExactIn.map(swapInfo => | ||||
|                             this.getBalancerV2MultihopSellQuotes(vault, swapInfo, swapInfo, takerFillAmounts, source), | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Beethovenx: { | ||||
|                     case ERC20BridgeSource.BalancerV2: | ||||
|                     case ERC20BridgeSource.Beethovenx: | ||||
|                         const poolIds = | ||||
|                             this.poolsCaches[source].getCachedPoolAddressesForPair(takerToken, makerToken) || []; | ||||
|  | ||||
|                         const vault = BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         const vault = | ||||
|                             source === ERC20BridgeSource.BalancerV2 | ||||
|                                 ? BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId] | ||||
|                                 : BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         if (vault === NULL_ADDRESS) { | ||||
|                             return []; | ||||
|                         } | ||||
| @@ -1619,7 +1435,6 @@ export class SamplerOperations { | ||||
|                                 source, | ||||
|                             ), | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Cream: | ||||
|                         return ( | ||||
|                             this.poolsCaches[ERC20BridgeSource.Cream].getCachedPoolAddressesForPair( | ||||
| @@ -1671,6 +1486,23 @@ export class SamplerOperations { | ||||
|                             takerToken, | ||||
|                             takerFillAmounts, | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.Linkswap: | ||||
|                         if (!isValidAddress(LINKSWAP_ROUTER_BY_CHAIN_ID[this.chainId])) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return [ | ||||
|                             [takerToken, makerToken], | ||||
|                             ...getIntermediateTokens(makerToken, takerToken, { | ||||
|                                 default: [MAINNET_TOKENS.LINK, MAINNET_TOKENS.WETH], | ||||
|                             }).map(t => [takerToken, t, makerToken]), | ||||
|                         ].map(path => | ||||
|                             this.getUniswapV2SellQuotes( | ||||
|                                 LINKSWAP_ROUTER_BY_CHAIN_ID[this.chainId], | ||||
|                                 path, | ||||
|                                 takerFillAmounts, | ||||
|                                 ERC20BridgeSource.Linkswap, | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.MakerPsm: | ||||
|                         const psmInfo = MAKER_PSM_INFO_BY_CHAIN_ID[this.chainId]; | ||||
|                         if (!isValidAddress(psmInfo.psmAddress)) { | ||||
| @@ -1688,10 +1520,16 @@ export class SamplerOperations { | ||||
|                         ].map(path => this.getUniswapV3SellQuotes(router, quoter, path, takerFillAmounts)); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Lido: { | ||||
|                         if (!this._isLidoSupported(takerToken, makerToken)) { | ||||
|                         const lidoInfo = LIDO_INFO_BY_CHAIN[this.chainId]; | ||||
|                         if ( | ||||
|                             lidoInfo.stEthToken === NULL_ADDRESS || | ||||
|                             lidoInfo.wethToken === NULL_ADDRESS || | ||||
|                             takerToken.toLowerCase() !== lidoInfo.wethToken.toLowerCase() || | ||||
|                             makerToken.toLowerCase() !== lidoInfo.stEthToken.toLowerCase() | ||||
|                         ) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         const lidoInfo = LIDO_INFO_BY_CHAIN[this.chainId]; | ||||
|  | ||||
|                         return this.getLidoSellQuotes(lidoInfo, makerToken, takerToken, takerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.AaveV2: { | ||||
| @@ -1710,13 +1548,6 @@ export class SamplerOperations { | ||||
|                         }; | ||||
|                         return this.getAaveV2SellQuotes(info, makerToken, takerToken, takerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Geist: { | ||||
|                         const info: GeistInfo | undefined = getGeistInfoForPair(takerToken, makerToken); | ||||
|                         if (!info) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return this.getGeistSellQuotes(info, makerToken, takerToken, takerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Compound: { | ||||
|                         if (!this.compoundCTokenCache) { | ||||
|                             return []; | ||||
| @@ -1733,45 +1564,6 @@ export class SamplerOperations { | ||||
|                             takerFillAmounts, | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.GMX: { | ||||
|                         // low liquidity mim pool dont quote | ||||
|                         if (takerToken === AVALANCHE_TOKENS.MIM || makerToken === 'AVALANCHE_TOKENS.MIM') { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return this.getGMXSellQuotes( | ||||
|                             GMX_ROUTER_BY_CHAIN_ID[this.chainId], | ||||
|                             GMX_READER_BY_CHAIN_ID[this.chainId], | ||||
|                             GMX_VAULT_BY_CHAIN_ID[this.chainId], | ||||
|                             [takerToken, makerToken], | ||||
|                             takerFillAmounts, | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Platypus: { | ||||
|                         return getPlatypusInfoForPair(this.chainId, takerToken, makerToken).map(pool => | ||||
|                             this.getPlatypusSellQuotes( | ||||
|                                 PLATYPUS_ROUTER_BY_CHAIN_ID[this.chainId], | ||||
|                                 [pool.poolAddress], | ||||
|                                 [takerToken, makerToken], | ||||
|                                 takerFillAmounts, | ||||
|                             ), | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.BancorV3: { | ||||
|                         return this.getBancorV3SellQuotes( | ||||
|                             BANCORV3_NETWORK_BY_CHAIN_ID[this.chainId], | ||||
|                             BANCORV3_NETWORK_INFO_BY_CHAIN_ID[this.chainId], | ||||
|                             [takerToken, makerToken], | ||||
|                             takerFillAmounts, | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Velodrome: { | ||||
|                         return this.getVelodromeSellQuotes( | ||||
|                             VELODROME_ROUTER_BY_CHAIN_ID[this.chainId], | ||||
|                             takerToken, | ||||
|                             makerToken, | ||||
|                             takerFillAmounts, | ||||
|                         ); | ||||
|                     } | ||||
|                     default: | ||||
|                         throw new Error(`Unsupported sell sample source: ${source}`); | ||||
|                 } | ||||
| @@ -1780,37 +1572,21 @@ export class SamplerOperations { | ||||
|         return allOps; | ||||
|     } | ||||
|  | ||||
|     private _isLidoSupported(takerTokenAddress: string, makerTokenAddress: string): boolean { | ||||
|         const lidoInfo = LIDO_INFO_BY_CHAIN[this.chainId]; | ||||
|         if (lidoInfo.wethToken === NULL_ADDRESS) { | ||||
|             return false; | ||||
|         } | ||||
|         const takerToken = takerTokenAddress.toLowerCase(); | ||||
|         const makerToken = makerTokenAddress.toLowerCase(); | ||||
|         const wethToken = lidoInfo.wethToken.toLowerCase(); | ||||
|         const stEthToken = lidoInfo.stEthToken.toLowerCase(); | ||||
|         const wstEthToken = lidoInfo.wstEthToken.toLowerCase(); | ||||
|  | ||||
|         if (takerToken === wethToken && makerToken === stEthToken) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return _.difference([stEthToken, wstEthToken], [takerToken, makerToken]).length === 0; | ||||
|     } | ||||
|  | ||||
|     private _getBuyQuoteOperations( | ||||
|         sources: ERC20BridgeSource[], | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation[] { | ||||
|         // Find the adjacent tokens in the provided token adjacency graph, | ||||
|         // Find the adjacent tokens in the provided tooken adjacency graph, | ||||
|         // e.g if this is DAI->USDC we may check for DAI->WETH->USDC | ||||
|         const intermediateTokens = getIntermediateTokens(makerToken, takerToken, this.tokenAdjacencyGraph); | ||||
|         const _sources = BATCH_SOURCE_FILTERS.getAllowed(sources); | ||||
|         return _.flatten( | ||||
|             _sources.map((source): SourceQuoteOperation | SourceQuoteOperation[] => { | ||||
|                 switch (source) { | ||||
|                     case ERC20BridgeSource.Eth2Dai: | ||||
|                         return []; | ||||
|                     case ERC20BridgeSource.Uniswap: | ||||
|                         return isValidAddress(UNISWAPV1_ROUTER_BY_CHAIN_ID[this.chainId]) | ||||
|                             ? this.getUniswapBuyQuotes( | ||||
| @@ -1827,23 +1603,22 @@ export class SamplerOperations { | ||||
|                     case ERC20BridgeSource.PancakeSwapV2: | ||||
|                     case ERC20BridgeSource.BakerySwap: | ||||
|                     case ERC20BridgeSource.ApeSwap: | ||||
|                     case ERC20BridgeSource.CafeSwap: | ||||
|                     case ERC20BridgeSource.CheeseSwap: | ||||
|                     case ERC20BridgeSource.JulSwap: | ||||
|                     case ERC20BridgeSource.QuickSwap: | ||||
|                     case ERC20BridgeSource.ComethSwap: | ||||
|                     case ERC20BridgeSource.Dfyn: | ||||
|                     case ERC20BridgeSource.WaultSwap: | ||||
|                     case ERC20BridgeSource.Polydex: | ||||
|                     case ERC20BridgeSource.ShibaSwap: | ||||
|                     case ERC20BridgeSource.JetSwap: | ||||
|                     case ERC20BridgeSource.Pangolin: | ||||
|                     case ERC20BridgeSource.TraderJoe: | ||||
|                     case ERC20BridgeSource.UbeSwap: | ||||
|                     case ERC20BridgeSource.SpiritSwap: | ||||
|                     case ERC20BridgeSource.SpookySwap: | ||||
|                     case ERC20BridgeSource.Yoshi: | ||||
|                     case ERC20BridgeSource.MorpheusSwap: | ||||
|                     case ERC20BridgeSource.BiSwap: | ||||
|                     case ERC20BridgeSource.MDex: | ||||
|                     case ERC20BridgeSource.KnightSwap: | ||||
|                     case ERC20BridgeSource.MeshSwap: | ||||
|                         const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); | ||||
|                         if (!isValidAddress(uniLikeRouter)) { | ||||
|                             return []; | ||||
| @@ -1858,8 +1633,20 @@ export class SamplerOperations { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return this.getKyberDmmBuyQuotes(kyberDmmRouter, [takerToken, makerToken], makerFillAmounts); | ||||
|                     case ERC20BridgeSource.Kyber: | ||||
|                         return getKyberOffsets().map(offset => | ||||
|                             this.getKyberBuyQuotes( | ||||
|                                 KYBER_CONFIG_BY_CHAIN_ID[this.chainId], | ||||
|                                 offset, | ||||
|                                 makerToken, | ||||
|                                 takerToken, | ||||
|                                 makerFillAmounts, | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.Curve: | ||||
|                     case ERC20BridgeSource.CurveV2: | ||||
|                     case ERC20BridgeSource.Swerve: | ||||
|                     case ERC20BridgeSource.SnowSwap: | ||||
|                     case ERC20BridgeSource.Nerve: | ||||
|                     case ERC20BridgeSource.Synapse: | ||||
|                     case ERC20BridgeSource.Belt: | ||||
| @@ -1869,7 +1656,6 @@ export class SamplerOperations { | ||||
|                     case ERC20BridgeSource.FirebirdOneSwap: | ||||
|                     case ERC20BridgeSource.IronSwap: | ||||
|                     case ERC20BridgeSource.ACryptos: | ||||
|                     case ERC20BridgeSource.MobiusMoney: | ||||
|                         return getCurveLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool => | ||||
|                             this.getCurveBuyQuotes( | ||||
|                                 pool, | ||||
| @@ -1934,33 +1720,15 @@ export class SamplerOperations { | ||||
|                                 ERC20BridgeSource.Balancer, | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.BalancerV2: { | ||||
|                         const cache = this.poolsCaches[source]; | ||||
|                         if (!cache) { | ||||
|                             return []; | ||||
|                         } | ||||
|  | ||||
|                         const swaps = cache.getCachedSwapInfoForPair(takerToken, makerToken); | ||||
|                         const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         if (!swaps || vault === NULL_ADDRESS) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         // Changed to retrieve queryBatchSwap for swap steps > 1 of length | ||||
|                         return swaps.swapInfoExactOut.map((quoteSwapInfo, i) => | ||||
|                             this.getBalancerV2MultihopBuyQuotes( | ||||
|                                 vault, | ||||
|                                 quoteSwapInfo, | ||||
|                                 swaps.swapInfoExactIn[i], | ||||
|                                 makerFillAmounts, | ||||
|                                 source, | ||||
|                             ), | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Beethovenx: { | ||||
|                     case ERC20BridgeSource.BalancerV2: | ||||
|                     case ERC20BridgeSource.Beethovenx: | ||||
|                         const poolIds = | ||||
|                             this.poolsCaches[source].getCachedPoolAddressesForPair(takerToken, makerToken) || []; | ||||
|  | ||||
|                         const vault = BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         const vault = | ||||
|                             source === ERC20BridgeSource.BalancerV2 | ||||
|                                 ? BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId] | ||||
|                                 : BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         if (vault === NULL_ADDRESS) { | ||||
|                             return []; | ||||
|                         } | ||||
| @@ -1973,7 +1741,6 @@ export class SamplerOperations { | ||||
|                                 source, | ||||
|                             ), | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Cream: | ||||
|                         return ( | ||||
|                             this.poolsCaches[ERC20BridgeSource.Cream].getCachedPoolAddressesForPair( | ||||
| @@ -2019,6 +1786,24 @@ export class SamplerOperations { | ||||
|                         // Unimplemented | ||||
|                         // return this.getBancorBuyQuotes(makerToken, takerToken, makerFillAmounts); | ||||
|                         return []; | ||||
|                     case ERC20BridgeSource.Linkswap: | ||||
|                         if (!isValidAddress(LINKSWAP_ROUTER_BY_CHAIN_ID[this.chainId])) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return [ | ||||
|                             [takerToken, makerToken], | ||||
|                             // LINK is the base asset in many of the pools on Linkswap | ||||
|                             ...getIntermediateTokens(makerToken, takerToken, { | ||||
|                                 default: [MAINNET_TOKENS.LINK, MAINNET_TOKENS.WETH], | ||||
|                             }).map(t => [takerToken, t, makerToken]), | ||||
|                         ].map(path => | ||||
|                             this.getUniswapV2BuyQuotes( | ||||
|                                 LINKSWAP_ROUTER_BY_CHAIN_ID[this.chainId], | ||||
|                                 path, | ||||
|                                 makerFillAmounts, | ||||
|                                 ERC20BridgeSource.Linkswap, | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.MakerPsm: | ||||
|                         const psmInfo = MAKER_PSM_INFO_BY_CHAIN_ID[this.chainId]; | ||||
|                         if (!isValidAddress(psmInfo.psmAddress)) { | ||||
| @@ -2036,10 +1821,17 @@ export class SamplerOperations { | ||||
|                         ].map(path => this.getUniswapV3BuyQuotes(router, quoter, path, makerFillAmounts)); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Lido: { | ||||
|                         if (!this._isLidoSupported(takerToken, makerToken)) { | ||||
|                         const lidoInfo = LIDO_INFO_BY_CHAIN[this.chainId]; | ||||
|  | ||||
|                         if ( | ||||
|                             lidoInfo.stEthToken === NULL_ADDRESS || | ||||
|                             lidoInfo.wethToken === NULL_ADDRESS || | ||||
|                             takerToken.toLowerCase() !== lidoInfo.wethToken.toLowerCase() || | ||||
|                             makerToken.toLowerCase() !== lidoInfo.stEthToken.toLowerCase() | ||||
|                         ) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         const lidoInfo = LIDO_INFO_BY_CHAIN[this.chainId]; | ||||
|  | ||||
|                         return this.getLidoBuyQuotes(lidoInfo, makerToken, takerToken, makerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.AaveV2: { | ||||
| @@ -2057,13 +1849,6 @@ export class SamplerOperations { | ||||
|                         }; | ||||
|                         return this.getAaveV2BuyQuotes(info, makerToken, takerToken, makerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Geist: { | ||||
|                         const info: GeistInfo | undefined = getGeistInfoForPair(takerToken, makerToken); | ||||
|                         if (!info) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return this.getGeistBuyQuotes(info, makerToken, takerToken, makerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Compound: { | ||||
|                         if (!this.compoundCTokenCache) { | ||||
|                             return []; | ||||
| @@ -2075,45 +1860,6 @@ export class SamplerOperations { | ||||
|                         } | ||||
|                         return this.getCompoundBuyQuotes(cToken.tokenAddress, makerToken, takerToken, makerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.GMX: { | ||||
|                         // bad mim pool dont quote | ||||
|                         if (takerToken === 'AVALANCHE_TOKENS.MIM' || makerToken === 'AVALANCHE_TOKENS.MIM') { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return this.getGMXBuyQuotes( | ||||
|                             GMX_ROUTER_BY_CHAIN_ID[this.chainId], | ||||
|                             GMX_READER_BY_CHAIN_ID[this.chainId], | ||||
|                             GMX_VAULT_BY_CHAIN_ID[this.chainId], | ||||
|                             [takerToken, makerToken], | ||||
|                             makerFillAmounts, | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Platypus: { | ||||
|                         return getPlatypusInfoForPair(this.chainId, takerToken, makerToken).map(pool => | ||||
|                             this.getPlatypusBuyQuotes( | ||||
|                                 PLATYPUS_ROUTER_BY_CHAIN_ID[this.chainId], | ||||
|                                 [pool.poolAddress], | ||||
|                                 [takerToken, makerToken], | ||||
|                                 makerFillAmounts, | ||||
|                             ), | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.BancorV3: { | ||||
|                         return this.getBancorV3BuyQuotes( | ||||
|                             BANCORV3_NETWORK_BY_CHAIN_ID[this.chainId], | ||||
|                             BANCORV3_NETWORK_INFO_BY_CHAIN_ID[this.chainId], | ||||
|                             [takerToken, makerToken], | ||||
|                             makerFillAmounts, | ||||
|                         ); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Velodrome: { | ||||
|                         return this.getVelodromeBuyQuotes( | ||||
|                             VELODROME_ROUTER_BY_CHAIN_ID[this.chainId], | ||||
|                             takerToken, | ||||
|                             makerToken, | ||||
|                             makerFillAmounts, | ||||
|                         ); | ||||
|                     } | ||||
|                     default: | ||||
|                         throw new Error(`Unsupported buy sample source: ${source}`); | ||||
|                 } | ||||
|   | ||||
| @@ -8,9 +8,9 @@ import { BigNumber } from '@0x/utils'; | ||||
|  | ||||
| import { NativeOrderWithFillableAmounts, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types'; | ||||
| import { QuoteRequestor, V4RFQIndicativeQuoteMM } from '../../utils/quote_requestor'; | ||||
| import { IRfqClient } from '../irfq_client'; | ||||
| import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from '../quote_report_generator'; | ||||
|  | ||||
| import { CollapsedPath } from './path'; | ||||
| import { SourceFilters } from './source_filters'; | ||||
|  | ||||
| /** | ||||
| @@ -38,6 +38,8 @@ export enum ERC20BridgeSource { | ||||
|     Native = 'Native', | ||||
|     Uniswap = 'Uniswap', | ||||
|     UniswapV2 = 'Uniswap_V2', | ||||
|     Eth2Dai = 'Eth2Dai', | ||||
|     Kyber = 'Kyber', | ||||
|     Curve = 'Curve', | ||||
|     LiquidityProvider = 'LiquidityProvider', | ||||
|     MultiBridge = 'MultiBridge', | ||||
| @@ -50,10 +52,13 @@ export enum ERC20BridgeSource { | ||||
|     Mooniswap = 'Mooniswap', | ||||
|     MultiHop = 'MultiHop', | ||||
|     Shell = 'Shell', | ||||
|     Swerve = 'Swerve', | ||||
|     SnowSwap = 'SnowSwap', | ||||
|     SushiSwap = 'SushiSwap', | ||||
|     Dodo = 'DODO', | ||||
|     DodoV2 = 'DODO_V2', | ||||
|     CryptoCom = 'CryptoCom', | ||||
|     Linkswap = 'Linkswap', | ||||
|     KyberDmm = 'KyberDMM', | ||||
|     Smoothy = 'Smoothy', | ||||
|     Component = 'Component', | ||||
| @@ -66,46 +71,37 @@ export enum ERC20BridgeSource { | ||||
|     AaveV2 = 'Aave_V2', | ||||
|     Compound = 'Compound', | ||||
|     Synapse = 'Synapse', | ||||
|     BancorV3 = 'BancorV3', | ||||
|     // BSC only | ||||
|     PancakeSwap = 'PancakeSwap', | ||||
|     PancakeSwapV2 = 'PancakeSwap_V2', | ||||
|     BiSwap = 'BiSwap', | ||||
|     MDex = 'MDex', | ||||
|     KnightSwap = 'KnightSwap', | ||||
|     BakerySwap = 'BakerySwap', | ||||
|     Nerve = 'Nerve', | ||||
|     Belt = 'Belt', | ||||
|     Ellipsis = 'Ellipsis', | ||||
|     ApeSwap = 'ApeSwap', | ||||
|     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', | ||||
|     MeshSwap = 'MeshSwap', | ||||
|     // Avalanche | ||||
|     Pangolin = 'Pangolin', | ||||
|     TraderJoe = 'TraderJoe', | ||||
|     Platypus = 'Platypus', | ||||
|     // tslint:disable: enum-naming | ||||
|     GMX = 'GMX', | ||||
|     // Celo only | ||||
|     UbeSwap = 'UbeSwap', | ||||
|     MobiusMoney = 'MobiusMoney', | ||||
|     // Fantom | ||||
|     SpiritSwap = 'SpiritSwap', | ||||
|     SpookySwap = 'SpookySwap', | ||||
|     Beethovenx = 'Beethovenx', | ||||
|     MorpheusSwap = 'MorpheusSwap', | ||||
|     Yoshi = 'Yoshi', | ||||
|     Geist = 'Geist', | ||||
|     // Optimism | ||||
|     Velodrome = 'Velodrome', | ||||
| } | ||||
| export type SourcesWithPoolsCache = | ||||
|     | ERC20BridgeSource.Balancer | ||||
| @@ -169,7 +165,6 @@ export interface PsmInfo { | ||||
| export interface LidoInfo { | ||||
|     stEthToken: string; | ||||
|     wethToken: string; | ||||
|     wstEthToken: string; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -186,12 +181,6 @@ export interface AaveV2Info { | ||||
|     underlyingToken: string; | ||||
| } | ||||
|  | ||||
| export interface GeistInfo { | ||||
|     lendingPool: string; | ||||
|     gToken: string; | ||||
|     underlyingToken: string; | ||||
| } | ||||
|  | ||||
| // Internal `fillData` field for `Fill` objects. | ||||
| export interface FillData {} | ||||
|  | ||||
| @@ -213,23 +202,6 @@ export interface CurveFillData extends FillData { | ||||
|     pool: CurveInfo; | ||||
| } | ||||
|  | ||||
| export interface BalancerBatchSwapStep { | ||||
|     poolId: string; | ||||
|     assetInIndex: number; | ||||
|     assetOutIndex: number; | ||||
|     amount: BigNumber; | ||||
|     userData: string; | ||||
| } | ||||
|  | ||||
| export interface BalancerSwaps { | ||||
|     swapInfoExactIn: BalancerSwapInfo[]; | ||||
|     swapInfoExactOut: BalancerSwapInfo[]; | ||||
| } | ||||
| export interface BalancerSwapInfo { | ||||
|     assets: string[]; | ||||
|     swapSteps: BalancerBatchSwapStep[]; | ||||
| } | ||||
|  | ||||
| export interface BalancerFillData extends FillData { | ||||
|     poolAddress: string; | ||||
| } | ||||
| @@ -239,12 +211,6 @@ export interface BalancerV2FillData extends FillData { | ||||
|     poolId: string; | ||||
| } | ||||
|  | ||||
| export interface BalancerV2BatchSwapFillData extends FillData { | ||||
|     vault: string; | ||||
|     swapSteps: BalancerBatchSwapStep[]; | ||||
|     assets: string[]; | ||||
| } | ||||
|  | ||||
| export interface UniswapV2FillData extends FillData { | ||||
|     tokenAddressPath: string[]; | ||||
|     router: string; | ||||
| @@ -264,9 +230,10 @@ export interface BancorFillData extends FillData { | ||||
|     networkAddress: string; | ||||
| } | ||||
|  | ||||
| export interface BancorV3FillData extends FillData { | ||||
|     path: string[]; | ||||
|     networkAddress: string; | ||||
| export interface KyberFillData extends FillData { | ||||
|     hint: string; | ||||
|     reserveId: string; | ||||
|     networkProxy: string; | ||||
| } | ||||
|  | ||||
| export interface MooniswapFillData extends FillData { | ||||
| @@ -301,41 +268,24 @@ export interface HopInfo { | ||||
|     returnData: string; | ||||
| } | ||||
|  | ||||
| export interface UniswapV3PathAmount { | ||||
|     uniswapPath: string; | ||||
|     inputAmount: BigNumber; | ||||
|     gasUsed: number; | ||||
| } | ||||
| export interface UniswapV3FillData extends FillData { | ||||
|     tokenAddressPath: string[]; | ||||
|     router: string; | ||||
|     pathAmounts: UniswapV3PathAmount[]; | ||||
|     pathAmounts: Array<{ uniswapPath: string; inputAmount: BigNumber }>; | ||||
| } | ||||
|  | ||||
| export interface KyberDmmFillData extends UniswapV2FillData { | ||||
|     poolsPath: string[]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Determines whether FillData is UniswapV3FillData or FinalUniswapV3FillData | ||||
|  */ | ||||
| export function isFinalUniswapV3FillData( | ||||
|     data: UniswapV3FillData | FinalUniswapV3FillData, | ||||
| ): data is FinalUniswapV3FillData { | ||||
|     return !!(data as FinalUniswapV3FillData).uniswapPath; | ||||
| } | ||||
|  | ||||
| export interface FinalUniswapV3FillData extends Omit<UniswapV3FillData, 'pathAmounts'> { | ||||
| export interface FinalUniswapV3FillData extends Omit<UniswapV3FillData, 'uniswapPaths'> { | ||||
|     // The uniswap-encoded path that can fll the maximum input amount. | ||||
|     uniswapPath: string; | ||||
|     gasUsed: number; | ||||
| } | ||||
|  | ||||
| export interface LidoFillData extends FillData { | ||||
|     stEthTokenAddress: string; | ||||
|     wstEthTokenAddress: string; | ||||
|     takerToken: string; | ||||
|     makerToken: string; | ||||
| } | ||||
|  | ||||
| export interface AaveV2FillData extends FillData { | ||||
| @@ -351,37 +301,6 @@ export interface CompoundFillData extends FillData { | ||||
|     makerToken: string; | ||||
| } | ||||
|  | ||||
| export interface GeistFillData extends FillData { | ||||
|     lendingPool: string; | ||||
|     gToken: string; | ||||
|     underlyingToken: string; | ||||
|     takerToken: string; | ||||
| } | ||||
|  | ||||
| export interface PlatypusInfo { | ||||
|     poolAddress: string; | ||||
|     tokens: string[]; | ||||
|     gasSchedule: number; | ||||
| } | ||||
|  | ||||
| export interface GMXFillData extends FillData { | ||||
|     router: string; | ||||
|     reader: string; | ||||
|     vault: string; | ||||
|     tokenAddressPath: string[]; | ||||
| } | ||||
|  | ||||
| export interface PlatypusFillData extends FillData { | ||||
|     router: string; | ||||
|     pool: string[]; | ||||
|     tokenAddressPath: string[]; | ||||
| } | ||||
|  | ||||
| export interface VelodromeFillData extends FillData { | ||||
|     router: string; | ||||
|     stable: boolean; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Represents a node on a fill path. | ||||
|  */ | ||||
| @@ -401,7 +320,7 @@ export interface Fill<TFillData extends FillData = FillData> { | ||||
|     input: BigNumber; | ||||
|     // Output fill amount (maker asset amount in a sell, taker asset amount in a buy). | ||||
|     output: BigNumber; | ||||
|     // The output fill amount, adjusted by fees. | ||||
|     // The output fill amount, ajdusted by fees. | ||||
|     adjustedOutput: BigNumber; | ||||
|     // Fill that must precede this one. This enforces certain fills to be contiguous. | ||||
|     parent?: Fill; | ||||
| @@ -479,7 +398,6 @@ export type OptimizedMarketOrder = | ||||
|     | OptimizedMarketOrderBase<NativeRfqOrderFillData>; | ||||
|  | ||||
| export interface GetMarketOrdersRfqOpts extends RfqRequestOpts { | ||||
|     rfqClient?: IRfqClient; | ||||
|     quoteRequestor?: QuoteRequestor; | ||||
|     firmQuoteValidator?: RfqFirmQuoteValidator; | ||||
| } | ||||
| @@ -632,6 +550,7 @@ export interface OptimizerResult { | ||||
|     liquidityDelivered: CollapsedFill[] | DexSample<MultiHopFillData>; | ||||
|     marketSideLiquidity: MarketSideLiquidity; | ||||
|     adjustedRate: BigNumber; | ||||
|     unoptimizedPath?: CollapsedPath; | ||||
|     takerAmountPerEth: BigNumber; | ||||
|     makerAmountPerEth: BigNumber; | ||||
| } | ||||
| @@ -663,7 +582,6 @@ export interface MarketSideLiquidity { | ||||
|     takerTokenDecimals: number; | ||||
|     quotes: RawQuotes; | ||||
|     isRfqSupported: boolean; | ||||
|     blockNumber: number; | ||||
| } | ||||
|  | ||||
| export interface RawQuotes { | ||||
| @@ -702,3 +620,9 @@ export interface GenerateOptimizedOrdersOpts { | ||||
| export interface ComparisonPrice { | ||||
|     wholeOrder: BigNumber | undefined; | ||||
| } | ||||
|  | ||||
| export interface KyberSamplerOpts { | ||||
|     networkProxy: string; | ||||
|     hintHandler: string; | ||||
|     weth: string; | ||||
| } | ||||
|   | ||||
| @@ -106,8 +106,6 @@ export interface ExtendedQuoteReport { | ||||
|     decodedUniqueId?: string; | ||||
|     sourcesConsidered: ExtendedQuoteReportIndexedEntryOutbound[]; | ||||
|     sourcesDelivered: ExtendedQuoteReportIndexedEntryOutbound[] | undefined; | ||||
|     blockNumber: number | undefined; | ||||
|     estimatedGas: string; | ||||
| } | ||||
|  | ||||
| export interface PriceComparisonsReport { | ||||
| @@ -207,7 +205,7 @@ export function generateExtendedQuoteReportSources( | ||||
|         ..._.flatten( | ||||
|             quotes.dexQuotes.map(dex => | ||||
|                 dex | ||||
|                     .filter(quote => isDexSampleFilter(quote, amount)) | ||||
|                     .filter(quote => isDexSampleForTotalAmount(quote, marketOperation, amount)) | ||||
|                     .map(quote => dexSampleToReportSource(quote, marketOperation)), | ||||
|             ), | ||||
|         ), | ||||
| @@ -306,9 +304,16 @@ export function dexSampleToReportSource(ds: DexSample, marketOperation: MarketOp | ||||
|  * Checks if a DEX sample is the one that represents the whole amount requested by taker | ||||
|  * NOTE: this is used for the QuoteReport to filter samples | ||||
|  */ | ||||
| function isDexSampleFilter(ds: DexSample, amount: BigNumber): boolean { | ||||
|     // The entry is for the total amont, not a sampler entry && there was liquidity in the source | ||||
|     return ds.input.eq(amount) && ds.output.isGreaterThan(0); | ||||
| function isDexSampleForTotalAmount(ds: DexSample, marketOperation: MarketOperation, amount: BigNumber): boolean { | ||||
|     // input and output map to different values | ||||
|     // based on the market operation | ||||
|     if (marketOperation === MarketOperation.Buy) { | ||||
|         return ds.input === amount; | ||||
|     } else if (marketOperation === MarketOperation.Sell) { | ||||
|         return ds.output === amount; | ||||
|     } else { | ||||
|         throw new Error(`Unexpected marketOperation ${marketOperation}`); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,16 +0,0 @@ | ||||
| import { FillQuoteTransformerOrderType } from '@0x/protocol-utils'; | ||||
|  | ||||
| import { SignedNativeOrder } from '../types'; | ||||
|  | ||||
| import { RfqClientV1Quote } from './irfq_client'; | ||||
|  | ||||
| /** | ||||
|  * Converts a RfqClientRfqOrderFirmQuote to a SignedNativeOrder | ||||
|  */ | ||||
| export const toSignedNativeOrder = (quote: RfqClientV1Quote): SignedNativeOrder => { | ||||
|     return { | ||||
|         type: FillQuoteTransformerOrderType.Rfq, | ||||
|         order: quote.order, | ||||
|         signature: quote.signature, | ||||
|     }; | ||||
| }; | ||||
| @@ -8,74 +8,66 @@ import { ContractArtifact } from 'ethereum-types'; | ||||
| import * as ApproximateBuys from '../test/generated-artifacts/ApproximateBuys.json'; | ||||
| import * as BalanceChecker from '../test/generated-artifacts/BalanceChecker.json'; | ||||
| import * as BalancerSampler from '../test/generated-artifacts/BalancerSampler.json'; | ||||
| import * as BalancerV2BatchSampler from '../test/generated-artifacts/BalancerV2BatchSampler.json'; | ||||
| import * as BalancerV2Common from '../test/generated-artifacts/BalancerV2Common.json'; | ||||
| import * as BalancerV2Sampler from '../test/generated-artifacts/BalancerV2Sampler.json'; | ||||
| import * as BancorSampler from '../test/generated-artifacts/BancorSampler.json'; | ||||
| import * as BancorV3Sampler from '../test/generated-artifacts/BancorV3Sampler.json'; | ||||
| import * as CompoundSampler from '../test/generated-artifacts/CompoundSampler.json'; | ||||
| import * as CurveSampler from '../test/generated-artifacts/CurveSampler.json'; | ||||
| import * as DODOSampler from '../test/generated-artifacts/DODOSampler.json'; | ||||
| import * as DODOV2Sampler from '../test/generated-artifacts/DODOV2Sampler.json'; | ||||
| import * as DummyLiquidityProvider from '../test/generated-artifacts/DummyLiquidityProvider.json'; | ||||
| import * as ERC20BridgeSampler from '../test/generated-artifacts/ERC20BridgeSampler.json'; | ||||
| import * as FakeTaker from '../test/generated-artifacts/FakeTaker.json'; | ||||
| import * as GMXSampler from '../test/generated-artifacts/GMXSampler.json'; | ||||
| import * as IBalancer from '../test/generated-artifacts/IBalancer.json'; | ||||
| import * as IBalancerV2Vault from '../test/generated-artifacts/IBalancerV2Vault.json'; | ||||
| import * as IBancor from '../test/generated-artifacts/IBancor.json'; | ||||
| import * as IBancorV3 from '../test/generated-artifacts/IBancorV3.json'; | ||||
| import * as ICurve from '../test/generated-artifacts/ICurve.json'; | ||||
| import * as IGMX from '../test/generated-artifacts/IGMX.json'; | ||||
| import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json'; | ||||
| import * as IMooniswap from '../test/generated-artifacts/IMooniswap.json'; | ||||
| import * as IMStable from '../test/generated-artifacts/IMStable.json'; | ||||
| import * as IMultiBridge from '../test/generated-artifacts/IMultiBridge.json'; | ||||
| import * as IPlatypus from '../test/generated-artifacts/IPlatypus.json'; | ||||
| import * as IShell from '../test/generated-artifacts/IShell.json'; | ||||
| import * as ISmoothy from '../test/generated-artifacts/ISmoothy.json'; | ||||
| import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json'; | ||||
| import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json'; | ||||
| import * as KyberDmmSampler from '../test/generated-artifacts/KyberDmmSampler.json'; | ||||
| import * as KyberSampler from '../test/generated-artifacts/KyberSampler.json'; | ||||
| import * as LidoSampler from '../test/generated-artifacts/LidoSampler.json'; | ||||
| import * as LiquidityProviderSampler from '../test/generated-artifacts/LiquidityProviderSampler.json'; | ||||
| import * as MakerPSMSampler from '../test/generated-artifacts/MakerPSMSampler.json'; | ||||
| import * as MooniswapSampler from '../test/generated-artifacts/MooniswapSampler.json'; | ||||
| import * as MStableSampler from '../test/generated-artifacts/MStableSampler.json'; | ||||
| import * as MultiBridgeSampler from '../test/generated-artifacts/MultiBridgeSampler.json'; | ||||
| import * as NativeOrderSampler from '../test/generated-artifacts/NativeOrderSampler.json'; | ||||
| import * as PlatypusSampler from '../test/generated-artifacts/PlatypusSampler.json'; | ||||
| import * as SamplerUtils from '../test/generated-artifacts/SamplerUtils.json'; | ||||
| import * as ShellSampler from '../test/generated-artifacts/ShellSampler.json'; | ||||
| import * as SmoothySampler from '../test/generated-artifacts/SmoothySampler.json'; | ||||
| import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json'; | ||||
| import * as TestNativeOrderSampler from '../test/generated-artifacts/TestNativeOrderSampler.json'; | ||||
| import * as TwoHopSampler from '../test/generated-artifacts/TwoHopSampler.json'; | ||||
| import * as UniswapSampler from '../test/generated-artifacts/UniswapSampler.json'; | ||||
| import * as UniswapV2Sampler from '../test/generated-artifacts/UniswapV2Sampler.json'; | ||||
| import * as UniswapV3Sampler from '../test/generated-artifacts/UniswapV3Sampler.json'; | ||||
| import * as UtilitySampler from '../test/generated-artifacts/UtilitySampler.json'; | ||||
| import * as VelodromeSampler from '../test/generated-artifacts/VelodromeSampler.json'; | ||||
| export const artifacts = { | ||||
|     ApproximateBuys: ApproximateBuys as ContractArtifact, | ||||
|     BalanceChecker: BalanceChecker as ContractArtifact, | ||||
|     BalancerSampler: BalancerSampler as ContractArtifact, | ||||
|     BalancerV2BatchSampler: BalancerV2BatchSampler as ContractArtifact, | ||||
|     BalancerV2Common: BalancerV2Common as ContractArtifact, | ||||
|     BalancerV2Sampler: BalancerV2Sampler as ContractArtifact, | ||||
|     BancorSampler: BancorSampler as ContractArtifact, | ||||
|     BancorV3Sampler: BancorV3Sampler as ContractArtifact, | ||||
|     CompoundSampler: CompoundSampler as ContractArtifact, | ||||
|     CurveSampler: CurveSampler as ContractArtifact, | ||||
|     DODOSampler: DODOSampler as ContractArtifact, | ||||
|     DODOV2Sampler: DODOV2Sampler as ContractArtifact, | ||||
|     ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact, | ||||
|     FakeTaker: FakeTaker as ContractArtifact, | ||||
|     GMXSampler: GMXSampler as ContractArtifact, | ||||
|     KyberDmmSampler: KyberDmmSampler as ContractArtifact, | ||||
|     KyberSampler: KyberSampler as ContractArtifact, | ||||
|     LidoSampler: LidoSampler as ContractArtifact, | ||||
|     LiquidityProviderSampler: LiquidityProviderSampler as ContractArtifact, | ||||
|     MStableSampler: MStableSampler as ContractArtifact, | ||||
|     MakerPSMSampler: MakerPSMSampler as ContractArtifact, | ||||
|     MooniswapSampler: MooniswapSampler as ContractArtifact, | ||||
|     MultiBridgeSampler: MultiBridgeSampler as ContractArtifact, | ||||
|     NativeOrderSampler: NativeOrderSampler as ContractArtifact, | ||||
|     PlatypusSampler: PlatypusSampler as ContractArtifact, | ||||
|     SamplerUtils: SamplerUtils as ContractArtifact, | ||||
|     ShellSampler: ShellSampler as ContractArtifact, | ||||
|     SmoothySampler: SmoothySampler as ContractArtifact, | ||||
| @@ -84,20 +76,18 @@ export const artifacts = { | ||||
|     UniswapV2Sampler: UniswapV2Sampler as ContractArtifact, | ||||
|     UniswapV3Sampler: UniswapV3Sampler as ContractArtifact, | ||||
|     UtilitySampler: UtilitySampler as ContractArtifact, | ||||
|     VelodromeSampler: VelodromeSampler as ContractArtifact, | ||||
|     IBalancer: IBalancer as ContractArtifact, | ||||
|     IBalancerV2Vault: IBalancerV2Vault as ContractArtifact, | ||||
|     IBancor: IBancor as ContractArtifact, | ||||
|     IBancorV3: IBancorV3 as ContractArtifact, | ||||
|     ICurve: ICurve as ContractArtifact, | ||||
|     IGMX: IGMX as ContractArtifact, | ||||
|     IKyberNetwork: IKyberNetwork as ContractArtifact, | ||||
|     IMStable: IMStable as ContractArtifact, | ||||
|     IMooniswap: IMooniswap as ContractArtifact, | ||||
|     IMultiBridge: IMultiBridge as ContractArtifact, | ||||
|     IPlatypus: IPlatypus as ContractArtifact, | ||||
|     IShell: IShell as ContractArtifact, | ||||
|     ISmoothy: ISmoothy as ContractArtifact, | ||||
|     IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact, | ||||
|     IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact, | ||||
|     DummyLiquidityProvider: DummyLiquidityProvider as ContractArtifact, | ||||
|     TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact, | ||||
|     TestNativeOrderSampler: TestNativeOrderSampler as ContractArtifact, | ||||
| }; | ||||
|   | ||||
| @@ -21,8 +21,8 @@ const GAS_PRICE = new BigNumber(50e9); // 50 gwei | ||||
| const NATIVE_ORDER_FEE = new BigNumber(220e3); // 220K gas | ||||
|  | ||||
| // DEX samples to fill in MarketSideLiquidity | ||||
| const curveSample: DexSample = { | ||||
|     source: ERC20BridgeSource.Curve, | ||||
| const kyberSample1: DexSample = { | ||||
|     source: ERC20BridgeSource.Kyber, | ||||
|     input: new BigNumber(10000), | ||||
|     output: new BigNumber(10001), | ||||
|     fillData: {}, | ||||
| @@ -33,7 +33,7 @@ const uniswapSample1: DexSample = { | ||||
|     output: new BigNumber(10004), | ||||
|     fillData: {}, | ||||
| }; | ||||
| const dexQuotes: DexSample[] = [curveSample, uniswapSample1]; | ||||
| const dexQuotes: DexSample[] = [kyberSample1, uniswapSample1]; | ||||
|  | ||||
| const feeSchedule = { | ||||
|     [ERC20BridgeSource.Native]: _.constant(GAS_PRICE.times(NATIVE_ORDER_FEE)), | ||||
| @@ -66,7 +66,6 @@ const buyMarketSideLiquidity: MarketSideLiquidity = { | ||||
|     }, | ||||
|     quoteSourceFilters: new SourceFilters(), | ||||
|     isRfqSupported: false, | ||||
|     blockNumber: 1337420, | ||||
| }; | ||||
|  | ||||
| const sellMarketSideLiquidity: MarketSideLiquidity = { | ||||
| @@ -88,7 +87,6 @@ const sellMarketSideLiquidity: MarketSideLiquidity = { | ||||
|     }, | ||||
|     quoteSourceFilters: new SourceFilters(), | ||||
|     isRfqSupported: false, | ||||
|     blockNumber: 1337420, | ||||
| }; | ||||
|  | ||||
| describe('getComparisonPrices', async () => { | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user