Compare commits

...

32 Commits

Author SHA1 Message Date
Github Actions
8e9699c340 Publish
- @0x/contracts-erc20@3.3.36
 - @0x/contracts-test-utils@5.4.27
 - @0x/contracts-treasury@1.4.19
 - @0x/contracts-utils@4.8.17
 - @0x/contracts-zero-ex@0.36.3
 - @0x/asset-swapper@16.66.3
 - @0x/contract-addresses@6.19.2
 - @0x/contract-wrappers@13.20.8
 - @0x/protocol-utils@11.16.3
2022-08-10 01:12:34 +00:00
Github Actions
939b708e63 Updated CHANGELOGS & MD docs 2022-08-10 01:12:31 +00:00
Kyu
1617e3fc44 Fix Polygon and Ganache FillQuoteTransformer addresses (#547)
* Revert Ganache (1337) FQT address as it was mistakenly updated.
* Update Polygon (137) FQT address with the new one.
2022-08-10 09:43:42 +09:00
Github Actions
e0d705703d Publish
- @0x/contracts-erc20@3.3.35
 - @0x/contracts-test-utils@5.4.26
 - @0x/contracts-treasury@1.4.18
 - @0x/contracts-utils@4.8.16
 - @0x/contracts-zero-ex@0.36.2
 - @0x/asset-swapper@16.66.2
 - @0x/contract-addresses@6.19.1
 - @0x/contract-wrappers@13.20.7
 - @0x/protocol-utils@11.16.2
2022-08-09 19:27:28 +00:00
Github Actions
01a6d933ca Updated CHANGELOGS & MD docs 2022-08-09 19:27:24 +00:00
Kyu
9b9f0b91d7 Move woofi tokens to constant.ts and run prettier (#544) 2022-08-09 13:31:37 +09:00
Ido Kleinman
0d0fef841d PR # 2022-08-08 19:04:04 -05:00
Ido Kleinman
17adfbea32 changelogs 2022-08-08 19:04:04 -05:00
Noah Khamliche
80594622b2 empty commit to run workflow 2022-08-08 18:55:39 -05:00
Ido Kleinman
0dba5a5a3a lowercase addresses (#542) 2022-08-08 16:40:31 -07:00
phil-ociraptor
4dae8de1b6 feat: add Foundry support to contracts/zero-ex (#534)
Co-authored-by: Michael Zhu <mchl.zhu.96@gmail.com>
2022-08-08 11:46:50 -05:00
eobbad
0046bb26d8 Update WooFi sampler logicand addresses.json w/ new FQT's 2022-08-08 12:27:45 -04:00
Kyu
fe935f787c Use @0x/fast-abi instead of deprecated fast-abi (#540) 2022-08-08 14:34:48 +09:00
Kyu
1b527ffcd8 Clean up Mirror and UST related stuff (#539) 2022-08-08 12:29:33 +09:00
Github Actions
9f5324d9c3 Publish
- @0x/asset-swapper@16.66.1
2022-08-08 02:47:26 +00:00
Github Actions
3647392a04 Updated CHANGELOGS & MD docs 2022-08-08 02:47:21 +00:00
Kyu
1d49662c58 Upgrade fast-abi (#538) 2022-08-08 11:27:44 +09:00
Github Actions
6324b08b4d Publish
- @0x/contracts-erc20@3.3.34
 - @0x/contracts-test-utils@5.4.25
 - @0x/contracts-treasury@1.4.17
 - @0x/contracts-utils@4.8.15
 - @0x/contracts-zero-ex@0.36.1
 - @0x/asset-swapper@16.66.0
 - @0x/contract-addresses@6.19.0
 - @0x/contract-wrappers@13.20.6
 - @0x/protocol-utils@11.16.1
2022-08-06 01:52:58 +00:00
Github Actions
fe73b63aaa Updated CHANGELOGS & MD docs 2022-08-06 01:52:55 +00:00
Kyu
192d0b17d9 Empty commit to trigger CI (something is wrong with Ido's account lol) 2022-08-06 10:34:15 +09:00
Ido Kleinman
aa74d04083 new contract address for goerli verified deploy (#537)
* new contract address for goerli verified deploy

* v6.18.0

* updated addresses for goerli + mumbai to verified contracts

* contract addresses changelog update

* unbump package version
2022-08-05 18:22:06 -07:00
Kyu
d586f5727d Rename Balancer pool cache files (#536) 2022-08-05 17:53:55 +09:00
Kyu
98fc79a085 Upgrade dependencies in asset-swapper to match the versions used in 0x-api [TKR-484] (#535)
* Upgrade dependencies to match the versions used in 0x-api

* Fix/disable tslint issues from the new version
2022-08-05 14:26:18 +09:00
eobbad
c12a10b96e Add WooFI support (#513)
* Add WooFI interface for sampling

* WooFi Sampler

* Add mixin

* Update bridge adapters

* fix some bugs

* update transformer_utils

* Add BSC support

* yarn prettier

* Capitalize WOOFI in bridge adapters

* Put rebateAddress in a constant, fixed some other stylistic errors

* bug fixes

* Updated CHANGELOGS & MD docs

* Publish

 - @0x/contracts-erc20@3.3.33
 - @0x/contracts-test-utils@5.4.24
 - @0x/contracts-treasury@1.4.16
 - @0x/contracts-utils@4.8.14
 - @0x/contracts-zero-ex@0.36.0
 - @0x/asset-swapper@16.64.0
 - @0x/contract-addresses@6.17.0
 - @0x/contract-wrappers@13.20.5
 - @0x/protocol-utils@11.16.0

* Update reference.mdx (#531)

Align with `DEFAULT_QUOTE_SLIPPAGE_PERCENTAGE` value from c74e31c219/src/constants.ts (L26)

* code cleanup

* remove deusdc curve pool from this pr

* Refactor PoolsCache (part 1) [TKR-500] (#525)

* Make _refreshPoolCacheIfRequiredAsync type-safe and remove Promise.all

* Factor out PoolsCache key logic into a function

* Use Map instead of object in PoolsCache and increase the default timeout

* Clean up PoolsCache and simplify its public interface

* Refactor PoolsCache (part 2) [TKR-500]  (#526)

* Introduce NoOpPoolsCache and use it in unsupported chains for BeethovenX

* Use `NoOpPoolsCache` for `CreamPoolsCache` and `BalancerPoolsCache` on unsupported chains

* Remove `getBidAskLiquidityForMakerTakerAssetPairAsync` (#528)

* Add transfer approval for quote token for multi-hops and fix buy sampler typo

* Use 0x gas api instead of eth gas station api [TKR-502] (#532)

* Use 0x gas api instead of eth gas station api

* Add integration test for `ProtocolFeeUtils`

* Update CHANGELOG.json

* Add polygon, fantom, avalanche support

* yarn prettier

* Updated CHANGELOGS & MD docs

* Publish

 - @0x/asset-swapper@16.65.0

* Remove references to `custom-no-magic-numbers` ts lint rule [TKR-484] (#533)

* Remove references to `custom-no-magic-numbers ts` lint rule

* Run prettier

* resolve Kyu's comments

* remove fqt change

* Add WooFI interface for sampling

* WooFi Sampler

* Add mixin

* Update bridge adapters

* fix some bugs

* update transformer_utils

* Add BSC support

* yarn prettier

* Capitalize WOOFI in bridge adapters

* Put rebateAddress in a constant, fixed some other stylistic errors

* bug fixes

* code cleanup

* remove deusdc curve pool from this pr

* Add transfer approval for quote token for multi-hops and fix buy sampler typo

* Add polygon, fantom, avalanche support

* yarn prettier

* resolve Kyu's comments

* remove fqt change

* merge types.ts

* WOOFi -> WOOFI

* fix lerna run lint

* Changelog

* nit changes

Co-authored-by: Github Actions <github-actions@github.com>
Co-authored-by: Pavel <51318041+pavel-bc@users.noreply.github.com>
Co-authored-by: Kyu <kyuhyun217@gmail.com>
2022-08-03 15:54:09 -04:00
Kyu
d3d4a08f91 Remove references to custom-no-magic-numbers ts lint rule [TKR-484] (#533)
* Remove references to `custom-no-magic-numbers ts` lint rule

* Run prettier
2022-08-01 17:50:40 -07:00
Github Actions
9ce090c8cd Publish
- @0x/asset-swapper@16.65.0
2022-08-01 22:10:47 +00:00
Github Actions
980d60deb8 Updated CHANGELOGS & MD docs 2022-08-01 22:10:42 +00:00
Kyu
d6d79e51e7 Use 0x gas api instead of eth gas station api [TKR-502] (#532)
* Use 0x gas api instead of eth gas station api

* Add integration test for `ProtocolFeeUtils`

* Update CHANGELOG.json
2022-08-01 14:42:45 -07:00
Kyu
3ef5de93bb Remove getBidAskLiquidityForMakerTakerAssetPairAsync (#528) 2022-07-28 09:26:07 -07:00
Kyu
ab7dc33ca4 Refactor PoolsCache (part 2) [TKR-500] (#526)
* Introduce NoOpPoolsCache and use it in unsupported chains for BeethovenX

* Use `NoOpPoolsCache` for `CreamPoolsCache` and `BalancerPoolsCache` on unsupported chains
2022-07-28 09:12:02 -07:00
Kyu
14dcee5bb6 Refactor PoolsCache (part 1) [TKR-500] (#525)
* Make _refreshPoolCacheIfRequiredAsync type-safe and remove Promise.all

* Factor out PoolsCache key logic into a function

* Use Map instead of object in PoolsCache and increase the default timeout

* Clean up PoolsCache and simplify its public interface
2022-07-28 09:04:42 -07:00
Pavel
9856e78609 Update reference.mdx (#531)
Align with `DEFAULT_QUOTE_SLIPPAGE_PERCENTAGE` value from c74e31c219/src/constants.ts (L26)
2022-07-27 12:35:16 -07:00
79 changed files with 2448 additions and 411 deletions

View File

@@ -10,6 +10,7 @@ jobs:
working_directory: ~/repo working_directory: ~/repo
steps: steps:
- checkout - checkout
- run: git submodule update --init --recursive
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV - run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
- run: - run:
name: install-yarn name: install-yarn
@@ -77,6 +78,17 @@ jobs:
keys: keys:
- repo-{{ .Environment.CIRCLE_SHA1 }} - repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun -p @0x/contracts-multisig -p @0x/contracts-utils -p @0x/contracts-exchange-libs -p @0x/contracts-erc20 -p @0x/contracts-erc721 -p @0x/contracts-erc1155 -p @0x/contracts-asset-proxy -p @0x/contracts-broker -p @0x/contracts-zero-ex -m --serial -c test:circleci - run: yarn wsrun -p @0x/contracts-multisig -p @0x/contracts-utils -p @0x/contracts-exchange-libs -p @0x/contracts-erc20 -p @0x/contracts-erc721 -p @0x/contracts-erc1155 -p @0x/contracts-asset-proxy -p @0x/contracts-broker -p @0x/contracts-zero-ex -m --serial -c test:circleci
test-foundry:
resource_class: medium+
docker:
- image: ghcr.io/foundry-rs/foundry:latest
working_directory: ~/repo/contracts/zero-ex
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
# - run: forge install
- run: forge test
test-publish: test-publish:
resource_class: large resource_class: large
environment: environment:
@@ -181,6 +193,9 @@ workflows:
# - test-contracts-extra-ganache: # - test-contracts-extra-ganache:
# requires: # requires:
# - build # - build
- test-foundry:
requires:
- build
- test-contracts-rest-ganache: - test-contracts-rest-ganache:
requires: requires:
- build - build

9
.gitignore vendored
View File

@@ -173,6 +173,15 @@ contracts/zero-ex/test/generated-wrappers/
contracts/treasury/generated-wrappers/ contracts/treasury/generated-wrappers/
contracts/treasury/test/generated-wrappers/ contracts/treasury/test/generated-wrappers/
# foundry artifacts
contracts/zero-ex/foundry-artifacts/
# foundry cache
contracts/zero-ex/foundry-cache/
# typechain wrappers
contracts/zero-ex/typechain-wrappers/
# Doc README copy # Doc README copy
packages/*/docs/README.md packages/*/docs/README.md

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "contracts/zero-ex/contracts/deps/forge-std"]
path = contracts/zero-ex/contracts/deps/forge-std
url = https://github.com/foundry-rs/forge-std

View File

@@ -1,4 +1,31 @@
[ [
{
"timestamp": 1660093941,
"version": "3.3.36",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1660073235,
"version": "3.3.35",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1659750766,
"version": "3.3.34",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1658950329, "timestamp": 1658950329,
"version": "3.3.33", "version": "3.3.33",

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v3.3.36 - _August 10, 2022_
* Dependencies updated
## v3.3.35 - _August 9, 2022_
* Dependencies updated
## v3.3.34 - _August 6, 2022_
* Dependencies updated
## v3.3.33 - _July 27, 2022_ ## v3.3.33 - _July 27, 2022_
* Dependencies updated * Dependencies updated

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contracts-erc20", "name": "@0x/contracts-erc20",
"version": "3.3.33", "version": "3.3.36",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -53,8 +53,8 @@
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^5.8.0", "@0x/abi-gen": "^5.8.0",
"@0x/contracts-gen": "^2.0.46", "@0x/contracts-gen": "^2.0.46",
"@0x/contracts-test-utils": "^5.4.24", "@0x/contracts-test-utils": "^5.4.27",
"@0x/contracts-utils": "^4.8.14", "@0x/contracts-utils": "^4.8.17",
"@0x/dev-utils": "^4.2.14", "@0x/dev-utils": "^4.2.14",
"@0x/sol-compiler": "^4.8.1", "@0x/sol-compiler": "^4.8.1",
"@0x/ts-doc-gen": "^0.0.28", "@0x/ts-doc-gen": "^0.0.28",

View File

@@ -1,4 +1,31 @@
[ [
{
"timestamp": 1660093941,
"version": "5.4.27",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1660073235,
"version": "5.4.26",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1659750766,
"version": "5.4.25",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1658950329, "timestamp": 1658950329,
"version": "5.4.24", "version": "5.4.24",

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v5.4.27 - _August 10, 2022_
* Dependencies updated
## v5.4.26 - _August 9, 2022_
* Dependencies updated
## v5.4.25 - _August 6, 2022_
* Dependencies updated
## v5.4.24 - _July 27, 2022_ ## v5.4.24 - _July 27, 2022_
* Dependencies updated * Dependencies updated

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contracts-test-utils", "name": "@0x/contracts-test-utils",
"version": "5.4.24", "version": "5.4.27",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -44,7 +44,7 @@
"dependencies": { "dependencies": {
"@0x/assert": "^3.0.34", "@0x/assert": "^3.0.34",
"@0x/base-contract": "^6.5.0", "@0x/base-contract": "^6.5.0",
"@0x/contract-addresses": "^6.17.0", "@0x/contract-addresses": "^6.19.2",
"@0x/dev-utils": "^4.2.14", "@0x/dev-utils": "^4.2.14",
"@0x/json-schemas": "^6.4.4", "@0x/json-schemas": "^6.4.4",
"@0x/order-utils": "^10.4.28", "@0x/order-utils": "^10.4.28",

View File

@@ -1,4 +1,31 @@
[ [
{
"timestamp": 1660093941,
"version": "1.4.19",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1660073235,
"version": "1.4.18",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1659750766,
"version": "1.4.17",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1658950329, "timestamp": 1658950329,
"version": "1.4.16", "version": "1.4.16",

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.4.19 - _August 10, 2022_
* Dependencies updated
## v1.4.18 - _August 9, 2022_
* Dependencies updated
## v1.4.17 - _August 6, 2022_
* Dependencies updated
## v1.4.16 - _July 27, 2022_ ## v1.4.16 - _July 27, 2022_
* Dependencies updated * Dependencies updated

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contracts-treasury", "name": "@0x/contracts-treasury",
"version": "1.4.16", "version": "1.4.19",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -47,12 +47,12 @@
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury", "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury",
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^5.8.0", "@0x/abi-gen": "^5.8.0",
"@0x/contract-addresses": "^6.17.0", "@0x/contract-addresses": "^6.19.2",
"@0x/contracts-asset-proxy": "^3.7.19", "@0x/contracts-asset-proxy": "^3.7.19",
"@0x/contracts-erc20": "^3.3.33", "@0x/contracts-erc20": "^3.3.36",
"@0x/contracts-gen": "^2.0.46", "@0x/contracts-gen": "^2.0.46",
"@0x/contracts-staking": "^2.0.45", "@0x/contracts-staking": "^2.0.45",
"@0x/contracts-test-utils": "^5.4.24", "@0x/contracts-test-utils": "^5.4.27",
"@0x/sol-compiler": "^4.8.1", "@0x/sol-compiler": "^4.8.1",
"@0x/ts-doc-gen": "^0.0.28", "@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.4", "@0x/tslint-config": "^4.1.4",
@@ -73,7 +73,7 @@
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^6.5.0", "@0x/base-contract": "^6.5.0",
"@0x/protocol-utils": "^11.16.0", "@0x/protocol-utils": "^11.16.3",
"@0x/subproviders": "^6.6.5", "@0x/subproviders": "^6.6.5",
"@0x/types": "^3.3.6", "@0x/types": "^3.3.6",
"@0x/typescript-typings": "^5.3.1", "@0x/typescript-typings": "^5.3.1",

View File

@@ -1,4 +1,31 @@
[ [
{
"timestamp": 1660093941,
"version": "4.8.17",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1660073235,
"version": "4.8.16",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1659750766,
"version": "4.8.15",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1658950329, "timestamp": 1658950329,
"version": "4.8.14", "version": "4.8.14",

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v4.8.17 - _August 10, 2022_
* Dependencies updated
## v4.8.16 - _August 9, 2022_
* Dependencies updated
## v4.8.15 - _August 6, 2022_
* Dependencies updated
## v4.8.14 - _July 27, 2022_ ## v4.8.14 - _July 27, 2022_
* Dependencies updated * Dependencies updated

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contracts-utils", "name": "@0x/contracts-utils",
"version": "4.8.14", "version": "4.8.17",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -52,7 +52,7 @@
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^5.8.0", "@0x/abi-gen": "^5.8.0",
"@0x/contracts-gen": "^2.0.46", "@0x/contracts-gen": "^2.0.46",
"@0x/contracts-test-utils": "^5.4.24", "@0x/contracts-test-utils": "^5.4.27",
"@0x/dev-utils": "^4.2.14", "@0x/dev-utils": "^4.2.14",
"@0x/order-utils": "^10.4.28", "@0x/order-utils": "^10.4.28",
"@0x/sol-compiler": "^4.8.1", "@0x/sol-compiler": "^4.8.1",

View File

@@ -1,4 +1,32 @@
[ [
{
"timestamp": 1660093941,
"version": "0.36.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.36.2",
"changes": [
{
"note": "Add Foundry support",
"pr": 534
}
],
"timestamp": 1659976271
},
{
"timestamp": 1659750766,
"version": "0.36.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"version": "0.36.0", "version": "0.36.0",
"changes": [ "changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v0.36.3 - _August 10, 2022_
* Dependencies updated
## v0.36.2 - _August 8, 2022_
* Add Foundry support (#534)
## v0.36.1 - _August 6, 2022_
* Dependencies updated
## v0.36.0 - _July 27, 2022_ ## v0.36.0 - _July 27, 2022_
* Add Synthetix support in Ethereum and Optimism bridge adapters (#518) * Add Synthetix support in Ethereum and Optimism bridge adapters (#518)

View File

@@ -2,6 +2,10 @@
This package contains contracts for the ZeroEx extensible contract architecture. This package contains contracts for the ZeroEx extensible contract architecture.
> **_NOTE:_** This repo is undergoing a tooling change. If adding a contract, you will need to
> add it to `compiler.json`. You can generate the entire list by running the following:
> `find . -type f -name "*.sol" | grep -v foundry | grep -v "contracts/dep" | grep -v "node_modules"`
## Installation ## Installation
**Install** **Install**

View File

@@ -1,6 +1,212 @@
{ {
"artifactsDir": "./test/generated-artifacts", "artifactsDir": "./test/generated-artifacts",
"contractsDir": "./contracts", "contractsDir": "./contracts",
"contracts": [
"./contracts/src/IZeroEx.sol",
"./contracts/src/ZeroEx.sol",
"./contracts/src/ZeroExOptimized.sol",
"./contracts/src/errors/LibCommonRichErrors.sol",
"./contracts/src/errors/LibLiquidityProviderRichErrors.sol",
"./contracts/src/errors/LibMetaTransactionsRichErrors.sol",
"./contracts/src/errors/LibNFTOrdersRichErrors.sol",
"./contracts/src/errors/LibNativeOrdersRichErrors.sol",
"./contracts/src/errors/LibOwnableRichErrors.sol",
"./contracts/src/errors/LibProxyRichErrors.sol",
"./contracts/src/errors/LibSignatureRichErrors.sol",
"./contracts/src/errors/LibSimpleFunctionRegistryRichErrors.sol",
"./contracts/src/errors/LibTransformERC20RichErrors.sol",
"./contracts/src/errors/LibWalletRichErrors.sol",
"./contracts/src/external/FeeCollector.sol",
"./contracts/src/external/FeeCollectorController.sol",
"./contracts/src/external/FlashWallet.sol",
"./contracts/src/external/IFlashWallet.sol",
"./contracts/src/external/ILiquidityProviderSandbox.sol",
"./contracts/src/external/LibFeeCollector.sol",
"./contracts/src/external/LiquidityProviderSandbox.sol",
"./contracts/src/external/PermissionlessTransformerDeployer.sol",
"./contracts/src/external/TransformerDeployer.sol",
"./contracts/src/features/BatchFillNativeOrdersFeature.sol",
"./contracts/src/features/BootstrapFeature.sol",
"./contracts/src/features/ERC165Feature.sol",
"./contracts/src/features/FundRecoveryFeature.sol",
"./contracts/src/features/LiquidityProviderFeature.sol",
"./contracts/src/features/MetaTransactionsFeature.sol",
"./contracts/src/features/NativeOrdersFeature.sol",
"./contracts/src/features/OtcOrdersFeature.sol",
"./contracts/src/features/OwnableFeature.sol",
"./contracts/src/features/PancakeSwapFeature.sol",
"./contracts/src/features/SimpleFunctionRegistryFeature.sol",
"./contracts/src/features/TransformERC20Feature.sol",
"./contracts/src/features/UniswapFeature.sol",
"./contracts/src/features/UniswapV3Feature.sol",
"./contracts/src/features/interfaces/IBatchFillNativeOrdersFeature.sol",
"./contracts/src/features/interfaces/IBootstrapFeature.sol",
"./contracts/src/features/interfaces/IERC1155OrdersFeature.sol",
"./contracts/src/features/interfaces/IERC165Feature.sol",
"./contracts/src/features/interfaces/IERC721OrdersFeature.sol",
"./contracts/src/features/interfaces/IFeature.sol",
"./contracts/src/features/interfaces/IFundRecoveryFeature.sol",
"./contracts/src/features/interfaces/ILiquidityProviderFeature.sol",
"./contracts/src/features/interfaces/IMetaTransactionsFeature.sol",
"./contracts/src/features/interfaces/IMultiplexFeature.sol",
"./contracts/src/features/interfaces/INativeOrdersEvents.sol",
"./contracts/src/features/interfaces/INativeOrdersFeature.sol",
"./contracts/src/features/interfaces/IOtcOrdersFeature.sol",
"./contracts/src/features/interfaces/IOwnableFeature.sol",
"./contracts/src/features/interfaces/IPancakeSwapFeature.sol",
"./contracts/src/features/interfaces/ISimpleFunctionRegistryFeature.sol",
"./contracts/src/features/interfaces/ITokenSpenderFeature.sol",
"./contracts/src/features/interfaces/ITransformERC20Feature.sol",
"./contracts/src/features/interfaces/IUniswapFeature.sol",
"./contracts/src/features/interfaces/IUniswapV3Feature.sol",
"./contracts/src/features/libs/LibNFTOrder.sol",
"./contracts/src/features/libs/LibNativeOrder.sol",
"./contracts/src/features/libs/LibSignature.sol",
"./contracts/src/features/multiplex/MultiplexFeature.sol",
"./contracts/src/features/multiplex/MultiplexLiquidityProvider.sol",
"./contracts/src/features/multiplex/MultiplexOtc.sol",
"./contracts/src/features/multiplex/MultiplexRfq.sol",
"./contracts/src/features/multiplex/MultiplexTransformERC20.sol",
"./contracts/src/features/multiplex/MultiplexUniswapV2.sol",
"./contracts/src/features/multiplex/MultiplexUniswapV3.sol",
"./contracts/src/features/native_orders/NativeOrdersCancellation.sol",
"./contracts/src/features/native_orders/NativeOrdersInfo.sol",
"./contracts/src/features/native_orders/NativeOrdersProtocolFees.sol",
"./contracts/src/features/native_orders/NativeOrdersSettlement.sol",
"./contracts/src/features/nft_orders/ERC1155OrdersFeature.sol",
"./contracts/src/features/nft_orders/ERC721OrdersFeature.sol",
"./contracts/src/features/nft_orders/NFTOrders.sol",
"./contracts/src/fixins/FixinCommon.sol",
"./contracts/src/fixins/FixinEIP712.sol",
"./contracts/src/fixins/FixinERC1155Spender.sol",
"./contracts/src/fixins/FixinERC721Spender.sol",
"./contracts/src/fixins/FixinProtocolFees.sol",
"./contracts/src/fixins/FixinReentrancyGuard.sol",
"./contracts/src/fixins/FixinTokenSpender.sol",
"./contracts/src/liquidity-providers/CurveLiquidityProvider.sol",
"./contracts/src/liquidity-providers/MooniswapLiquidityProvider.sol",
"./contracts/src/migrations/FullMigration.sol",
"./contracts/src/migrations/InitialMigration.sol",
"./contracts/src/migrations/LibBootstrap.sol",
"./contracts/src/migrations/LibMigrate.sol",
"./contracts/src/storage/LibERC1155OrdersStorage.sol",
"./contracts/src/storage/LibERC721OrdersStorage.sol",
"./contracts/src/storage/LibMetaTransactionsStorage.sol",
"./contracts/src/storage/LibNativeOrdersStorage.sol",
"./contracts/src/storage/LibOtcOrdersStorage.sol",
"./contracts/src/storage/LibOwnableStorage.sol",
"./contracts/src/storage/LibProxyStorage.sol",
"./contracts/src/storage/LibReentrancyGuardStorage.sol",
"./contracts/src/storage/LibSimpleFunctionRegistryStorage.sol",
"./contracts/src/storage/LibStorage.sol",
"./contracts/src/storage/LibTransformERC20Storage.sol",
"./contracts/src/transformers/AffiliateFeeTransformer.sol",
"./contracts/src/transformers/FillQuoteTransformer.sol",
"./contracts/src/transformers/IERC20Transformer.sol",
"./contracts/src/transformers/LibERC20Transformer.sol",
"./contracts/src/transformers/LogMetadataTransformer.sol",
"./contracts/src/transformers/PayTakerTransformer.sol",
"./contracts/src/transformers/PositiveSlippageFeeTransformer.sol",
"./contracts/src/transformers/Transformer.sol",
"./contracts/src/transformers/WethTransformer.sol",
"./contracts/src/transformers/bridges/AbstractBridgeAdapter.sol",
"./contracts/src/transformers/bridges/AvalancheBridgeAdapter.sol",
"./contracts/src/transformers/bridges/BSCBridgeAdapter.sol",
"./contracts/src/transformers/bridges/BridgeProtocols.sol",
"./contracts/src/transformers/bridges/CeloBridgeAdapter.sol",
"./contracts/src/transformers/bridges/EthereumBridgeAdapter.sol",
"./contracts/src/transformers/bridges/FantomBridgeAdapter.sol",
"./contracts/src/transformers/bridges/IBridgeAdapter.sol",
"./contracts/src/transformers/bridges/OptimismBridgeAdapter.sol",
"./contracts/src/transformers/bridges/PolygonBridgeAdapter.sol",
"./contracts/src/transformers/bridges/mixins/MixinAaveV2.sol",
"./contracts/src/transformers/bridges/mixins/MixinBalancer.sol",
"./contracts/src/transformers/bridges/mixins/MixinBalancerV2.sol",
"./contracts/src/transformers/bridges/mixins/MixinBalancerV2Batch.sol",
"./contracts/src/transformers/bridges/mixins/MixinBancor.sol",
"./contracts/src/transformers/bridges/mixins/MixinBancorV3.sol",
"./contracts/src/transformers/bridges/mixins/MixinCompound.sol",
"./contracts/src/transformers/bridges/mixins/MixinCryptoCom.sol",
"./contracts/src/transformers/bridges/mixins/MixinCurve.sol",
"./contracts/src/transformers/bridges/mixins/MixinCurveV2.sol",
"./contracts/src/transformers/bridges/mixins/MixinDodo.sol",
"./contracts/src/transformers/bridges/mixins/MixinDodoV2.sol",
"./contracts/src/transformers/bridges/mixins/MixinGMX.sol",
"./contracts/src/transformers/bridges/mixins/MixinKyberDmm.sol",
"./contracts/src/transformers/bridges/mixins/MixinLido.sol",
"./contracts/src/transformers/bridges/mixins/MixinMStable.sol",
"./contracts/src/transformers/bridges/mixins/MixinMakerPSM.sol",
"./contracts/src/transformers/bridges/mixins/MixinMooniswap.sol",
"./contracts/src/transformers/bridges/mixins/MixinNerve.sol",
"./contracts/src/transformers/bridges/mixins/MixinPlatypus.sol",
"./contracts/src/transformers/bridges/mixins/MixinShell.sol",
"./contracts/src/transformers/bridges/mixins/MixinSynthetix.sol",
"./contracts/src/transformers/bridges/mixins/MixinUniswap.sol",
"./contracts/src/transformers/bridges/mixins/MixinUniswapV2.sol",
"./contracts/src/transformers/bridges/mixins/MixinUniswapV3.sol",
"./contracts/src/transformers/bridges/mixins/MixinVelodrome.sol",
"./contracts/src/transformers/bridges/mixins/MixinZeroExBridge.sol",
"./contracts/src/vendor/IERC1155Token.sol",
"./contracts/src/vendor/IERC721Token.sol",
"./contracts/src/vendor/IFeeRecipient.sol",
"./contracts/src/vendor/ILiquidityProvider.sol",
"./contracts/src/vendor/IMooniswapPool.sol",
"./contracts/src/vendor/IPropertyValidator.sol",
"./contracts/src/vendor/ITakerCallback.sol",
"./contracts/src/vendor/IUniswapV2Pair.sol",
"./contracts/src/vendor/IUniswapV3Pool.sol",
"./contracts/src/vendor/v3/IERC20Bridge.sol",
"./contracts/src/vendor/v3/IStaking.sol",
"./contracts/test/ITestSimpleFunctionRegistryFeature.sol",
"./contracts/test/TestBridge.sol",
"./contracts/test/TestCallTarget.sol",
"./contracts/test/TestDelegateCaller.sol",
"./contracts/test/TestFeeCollectorController.sol",
"./contracts/test/TestFeeRecipient.sol",
"./contracts/test/TestFillQuoteTransformerBridge.sol",
"./contracts/test/TestFillQuoteTransformerExchange.sol",
"./contracts/test/TestFillQuoteTransformerHost.sol",
"./contracts/test/TestFixinProtocolFees.sol",
"./contracts/test/TestFixinTokenSpender.sol",
"./contracts/test/TestFullMigration.sol",
"./contracts/test/TestInitialMigration.sol",
"./contracts/test/TestLibNativeOrder.sol",
"./contracts/test/TestLibSignature.sol",
"./contracts/test/TestMetaTransactionsNativeOrdersFeature.sol",
"./contracts/test/TestMetaTransactionsTransformERC20Feature.sol",
"./contracts/test/TestMigrator.sol",
"./contracts/test/TestMintTokenERC20Transformer.sol",
"./contracts/test/TestNFTOrderPresigner.sol",
"./contracts/test/TestNativeOrdersFeature.sol",
"./contracts/test/TestNoEthRecipient.sol",
"./contracts/test/TestOrderSignerRegistryWithContractWallet.sol",
"./contracts/test/TestPermissionlessTransformerDeployerSuicidal.sol",
"./contracts/test/TestPermissionlessTransformerDeployerTransformer.sol",
"./contracts/test/TestPropertyValidator.sol",
"./contracts/test/TestRfqOriginRegistration.sol",
"./contracts/test/TestSimpleFunctionRegistryFeatureImpl1.sol",
"./contracts/test/TestSimpleFunctionRegistryFeatureImpl2.sol",
"./contracts/test/TestStaking.sol",
"./contracts/test/TestTransformERC20.sol",
"./contracts/test/TestTransformerBase.sol",
"./contracts/test/TestTransformerDeployerTransformer.sol",
"./contracts/test/TestTransformerHost.sol",
"./contracts/test/TestUniswapV3Feature.sol",
"./contracts/test/TestWethTransformerHost.sol",
"./contracts/test/TestZeroExFeature.sol",
"./contracts/test/integration/TestCurve.sol",
"./contracts/test/integration/TestLiquidityProvider.sol",
"./contracts/test/integration/TestMooniswap.sol",
"./contracts/test/integration/TestUniswapV2Factory.sol",
"./contracts/test/integration/TestUniswapV2Pool.sol",
"./contracts/test/integration/TestUniswapV3Factory.sol",
"./contracts/test/integration/TestUniswapV3Pool.sol",
"./contracts/test/tokens/TestMintableERC1155Token.sol",
"./contracts/test/tokens/TestMintableERC20Token.sol",
"./contracts/test/tokens/TestMintableERC721Token.sol",
"./contracts/test/tokens/TestTokenSpenderERC20Token.sol",
"./contracts/test/tokens/TestWeth.sol"
],
"useDockerisedSolc": false, "useDockerisedSolc": false,
"isOfflineMode": false, "isOfflineMode": false,
"shouldSaveStandardInput": true, "shouldSaveStandardInput": true,

View File

@@ -313,7 +313,7 @@ contract FillQuoteTransformer is
if (success) { if (success) {
results.makerTokenBoughtAmount = abi.decode(resultData, (uint256)); results.makerTokenBoughtAmount = abi.decode(resultData, (uint256));
results.takerTokenSoldAmount = takerTokenFillAmount; results.takerTokenSoldAmount = takerTokenFillAmount;
} }
} }
// Fill a single limit order. // Fill a single limit order.

View File

@@ -30,6 +30,7 @@ import "./mixins/MixinAaveV2.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
import "./mixins/MixinPlatypus.sol"; import "./mixins/MixinPlatypus.sol";
import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinWOOFi.sol";
import "./mixins/MixinZeroExBridge.sol"; import "./mixins/MixinZeroExBridge.sol";
contract AvalancheBridgeAdapter is contract AvalancheBridgeAdapter is
@@ -42,6 +43,7 @@ contract AvalancheBridgeAdapter is
MixinNerve, MixinNerve,
MixinPlatypus, MixinPlatypus,
MixinUniswapV2, MixinUniswapV2,
MixinWOOFi,
MixinZeroExBridge MixinZeroExBridge
{ {
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
@@ -120,6 +122,14 @@ contract AvalancheBridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.WOOFI) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeWOOFi(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) { } else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); } if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(

View File

@@ -29,6 +29,7 @@ import "./mixins/MixinKyberDmm.sol";
import "./mixins/MixinMooniswap.sol"; import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinWOOFi.sol";
import "./mixins/MixinZeroExBridge.sol"; import "./mixins/MixinZeroExBridge.sol";
contract BSCBridgeAdapter is contract BSCBridgeAdapter is
@@ -40,6 +41,7 @@ contract BSCBridgeAdapter is
MixinMooniswap, MixinMooniswap,
MixinNerve, MixinNerve,
MixinUniswapV2, MixinUniswapV2,
MixinWOOFi,
MixinZeroExBridge MixinZeroExBridge
{ {
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
@@ -111,6 +113,14 @@ contract BSCBridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.WOOFI) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeWOOFi(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) { } else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); } if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(

View File

@@ -58,4 +58,5 @@ library BridgeProtocols {
uint128 internal constant BANCORV3 = 28; uint128 internal constant BANCORV3 = 28;
uint128 internal constant VELODROME = 29; uint128 internal constant VELODROME = 29;
uint128 internal constant SYNTHETIX = 30; uint128 internal constant SYNTHETIX = 30;
uint128 internal constant WOOFI = 31;
} }

View File

@@ -28,6 +28,7 @@ import "./mixins/MixinCurve.sol";
import "./mixins/MixinCurveV2.sol"; import "./mixins/MixinCurveV2.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinWOOFi.sol";
import "./mixins/MixinZeroExBridge.sol"; import "./mixins/MixinZeroExBridge.sol";
contract FantomBridgeAdapter is contract FantomBridgeAdapter is
@@ -38,6 +39,7 @@ contract FantomBridgeAdapter is
MixinCurveV2, MixinCurveV2,
MixinNerve, MixinNerve,
MixinUniswapV2, MixinUniswapV2,
MixinWOOFi,
MixinZeroExBridge MixinZeroExBridge
{ {
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
@@ -103,6 +105,14 @@ contract FantomBridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.WOOFI) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeWOOFi(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) { } else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); } if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(

View File

@@ -34,6 +34,7 @@ import "./mixins/MixinMStable.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinUniswapV3.sol"; import "./mixins/MixinUniswapV3.sol";
import "./mixins/MixinWOOFi.sol";
import "./mixins/MixinZeroExBridge.sol"; import "./mixins/MixinZeroExBridge.sol";
contract PolygonBridgeAdapter is contract PolygonBridgeAdapter is
@@ -50,6 +51,7 @@ contract PolygonBridgeAdapter is
MixinNerve, MixinNerve,
MixinUniswapV2, MixinUniswapV2,
MixinUniswapV3, MixinUniswapV3,
MixinWOOFi,
MixinZeroExBridge MixinZeroExBridge
{ {
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
@@ -157,6 +159,14 @@ contract PolygonBridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.WOOFI) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeWOOFi(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) { } else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); } if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(

View File

@@ -0,0 +1,136 @@
// 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 "@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";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
/// @dev WooFI pool interface.
interface IWooPP {
function quoteToken() external view returns (address);
function sellBase(
address baseToken,
uint256 baseAmount,
uint256 minQuoteAmount,
address to,
address rebateTo
) external returns (uint256 quoteAmount);
function sellQuote(
address baseToken,
uint256 quoteAmount,
uint256 minBaseAmount,
address to,
address rebateTo
) external returns (uint256 baseAmount);
/// @dev Query the amount for selling the base token amount.
/// @param baseToken the base token to sell
/// @param baseAmount the amount to sell
/// @return quoteAmount the swapped quote amount
function querySellBase(
address baseToken,
uint256 baseAmount
) external view returns (uint256 quoteAmount);
}
contract MixinWOOFi{
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20TokenV06 for IEtherTokenV06;
using LibSafeMathV06 for uint256;
address constant rebateAddress = 0xBfdcBB4C05843163F491C24f9c0019c510786304;
// /// @dev Swaps an exact amount of input tokens for as many output tokens as possible.
// /// @param _amountIn Amount of input tokens to send
// /// @param _minAmountOut The minimum amount of output tokens that must be received for the transaction not to revert.
// /// @param _tokenIn Input token
// /// @param _tokenOut Output token
// /// @param _to recipient of tokens
// /// @param pool WOOFi pool where the swap will happen
function _tradeWOOFi(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
public
returns (uint256 boughtAmount)
{
(IWooPP _pool) = abi.decode(bridgeData, (IWooPP));
uint256 beforeBalance = buyToken.balanceOf(address(this));
sellToken.approveIfBelow(address(_pool), sellAmount);
_swap(
sellAmount,
address(sellToken),
address(buyToken),
_pool
);
boughtAmount = buyToken.balanceOf(address(this)).safeSub(beforeBalance);
}
function _swap(
uint _amountIn,
address _tokenIn,
address _tokenOut,
IWooPP pool
) internal {
address quoteToken = pool.quoteToken();
if (_tokenIn == quoteToken) {
pool.sellQuote(
_tokenOut,
_amountIn,
1,
address(this),
rebateAddress
);
} else if (_tokenOut == quoteToken) {
pool.sellBase(
_tokenIn,
_amountIn,
1,
address(this),
rebateAddress
);
} else {
uint256 quoteAmount = pool.sellBase(
_tokenIn,
_amountIn,
0,
address(this),
rebateAddress
);
IERC20TokenV06(pool.quoteToken()).approveIfBelow(address(pool), quoteAmount);
pool.sellQuote(
_tokenOut,
quoteAmount,
1,
address(this),
rebateAddress
);
}
}
}

View File

@@ -0,0 +1,30 @@
// 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;
import "forge-std/Test.sol";
contract ContractTest is Test {
function setUp() public {}
function testExample() public {
assertTrue(true);
}
}

View File

@@ -0,0 +1,8 @@
[default]
src = 'contracts/src'
out = 'foundry-artifacts'
test = 'contracts/test/foundry'
libs = ["contracts/deps/", "../utils/contracts/src/"]
remappings = ['@0x/contracts-utils/=../utils/', '@0x/contracts-erc20/=../erc20/', 'src/=./contracts/src']
cache_path = 'foundry-cache'
optimizer_runs = 1000000

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contracts-zero-ex", "name": "@0x/contracts-zero-ex",
"version": "0.36.0", "version": "0.36.3",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -38,7 +38,8 @@
"docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json", "docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json",
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES", "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES",
"publish:private": "yarn build && gitpkg publish", "publish:private": "yarn build && gitpkg publish",
"rollback": "node ./lib/scripts/rollback.js" "rollback": "node ./lib/scripts/rollback.js",
"typechain": "typechain --target=ethers-v5 --out-dir='typechain-wrappers' './foundry-artifacts/**/*.json'"
}, },
"config": { "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,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature,AvalancheBridgeAdapter,BSCBridgeAdapter,CeloBridgeAdapter,EthereumBridgeAdapter,FantomBridgeAdapter,OptimismBridgeAdapter,PolygonBridgeAdapter",
@@ -56,15 +57,16 @@
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex", "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex",
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^5.8.0", "@0x/abi-gen": "^5.8.0",
"@0x/contract-addresses": "^6.17.0", "@0x/contract-addresses": "^6.19.2",
"@0x/contracts-erc20": "^3.3.33", "@0x/contracts-erc20": "^3.3.36",
"@0x/contracts-gen": "^2.0.46", "@0x/contracts-gen": "^2.0.46",
"@0x/contracts-test-utils": "^5.4.24", "@0x/contracts-test-utils": "^5.4.27",
"@0x/dev-utils": "^4.2.14", "@0x/dev-utils": "^4.2.14",
"@0x/order-utils": "^10.4.28", "@0x/order-utils": "^10.4.28",
"@0x/sol-compiler": "^4.8.1", "@0x/sol-compiler": "^4.8.1",
"@0x/ts-doc-gen": "^0.0.28", "@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.4", "@0x/tslint-config": "^4.1.4",
"@typechain/ethers-v5": "^10.0.0",
"@types/isomorphic-fetch": "^0.0.35", "@types/isomorphic-fetch": "^0.0.35",
"@types/lodash": "4.14.104", "@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",
@@ -78,12 +80,13 @@
"solhint": "^1.4.1", "solhint": "^1.4.1",
"truffle": "^5.0.32", "truffle": "^5.0.32",
"tslint": "5.11.0", "tslint": "5.11.0",
"typechain": "^8.0.0",
"typedoc": "~0.16.11", "typedoc": "~0.16.11",
"typescript": "4.6.3" "typescript": "4.6.3"
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^6.5.0", "@0x/base-contract": "^6.5.0",
"@0x/protocol-utils": "^11.16.0", "@0x/protocol-utils": "^11.16.3",
"@0x/subproviders": "^6.6.5", "@0x/subproviders": "^6.6.5",
"@0x/types": "^3.3.6", "@0x/types": "^3.3.6",
"@0x/typescript-typings": "^5.3.1", "@0x/typescript-typings": "^5.3.1",

View File

@@ -1,4 +1,53 @@
[ [
{
"timestamp": 1660093941,
"version": "16.66.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "16.66.2",
"changes": [
{
"note": "Upgrade dependency",
"pr": 543
}
],
"timestamp": 1660073235
},
{
"version": "16.66.1",
"changes": [
{
"note": "Upgrade dependency",
"pr": 538
}
],
"timestamp": 1659926840
},
{
"version": "16.66.0",
"changes": [
{
"note": "Add WOOFi support",
"pr": 513
}
],
"timestamp": 1659750766
},
{
"version": "16.65.0",
"changes": [
{
"note": "Use 0x gas api instead of eth gas station api",
"pr": 532
}
],
"timestamp": 1659391840
},
{ {
"version": "16.64.0", "version": "16.64.0",
"changes": [ "changes": [

View File

@@ -5,6 +5,26 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v16.66.3 - _August 10, 2022_
* Dependencies updated
## v16.66.2 - _August 9, 2022_
* Upgrade dependency (#543)
## v16.66.1 - _August 8, 2022_
* Upgrade dependency (#538)
## v16.66.0 - _August 6, 2022_
* Add WOOFi support (#513)
## v16.65.0 - _August 1, 2022_
* Use 0x gas api instead of eth gas station api (#532)
## v16.64.0 - _July 27, 2022_ ## v16.64.0 - _July 27, 2022_
* Refactor `TokenAdjacency` and `TokenAdjacencyBuilder` (#517) * Refactor `TokenAdjacency` and `TokenAdjacencyBuilder` (#517)

View File

@@ -45,6 +45,7 @@ import "./UniswapSampler.sol";
import "./UniswapV2Sampler.sol"; import "./UniswapV2Sampler.sol";
import "./UniswapV3Sampler.sol"; import "./UniswapV3Sampler.sol";
import "./VelodromeSampler.sol"; import "./VelodromeSampler.sol";
import "./WooPPSampler.sol";
import "./UtilitySampler.sol"; import "./UtilitySampler.sol";
@@ -74,6 +75,7 @@ contract ERC20BridgeSampler is
UniswapV2Sampler, UniswapV2Sampler,
UniswapV3Sampler, UniswapV3Sampler,
VelodromeSampler, VelodromeSampler,
WooPPSampler,
UtilitySampler UtilitySampler
{ {

View File

@@ -0,0 +1,121 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./SamplerUtils.sol";
import "./ApproximateBuys.sol";
interface IWooPP {
/// @dev get the quote token address (immutable)
/// @return address of quote token
function quoteToken() external view returns (address);
/// @dev Query the amount for selling the base token amount.
/// @param baseToken the base token to sell
/// @param baseAmount the amount to sell
/// @return quoteAmount the swapped quote amount
function querySellBase(address baseToken, uint256 baseAmount) external view returns (uint256 quoteAmount);
/// @dev Query the amount for selling the quote token.
/// @param baseToken the base token to receive (buy)
/// @param quoteAmount the amount to sell
/// @return baseAmount the swapped base token amount
function querySellQuote(address baseToken, uint256 quoteAmount) external view returns (uint256 baseAmount);
}
contract WooPPSampler is SamplerUtils, ApproximateBuys{
function query(
uint amountIn,
address tokenIn,
address tokenOut,
address pool
) internal view returns (uint256 amountOut) {
if (amountIn == 0) {
return 0;
}
address quoteToken = IWooPP(pool).quoteToken();
if (tokenIn == quoteToken) {
amountOut = IWooPP(pool).querySellQuote(tokenOut, amountIn);
} else if (tokenOut == quoteToken) {
amountOut = IWooPP(pool).querySellBase(tokenIn, amountIn);
} else {
uint quoteAmount = IWooPP(pool).querySellBase(tokenIn, amountIn);
amountOut = IWooPP(pool).querySellQuote(tokenOut, quoteAmount);
}
}
/// @dev Sample sell quotes from WooFI.
/// @param pool Address of the pool we are sampling from
/// @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 makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromWooPP(
address pool,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
makerTokenAmounts[i] = query(takerTokenAmounts[i], takerToken, makerToken, pool);
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from WooFI.
/// @param pool Address of the pool we are sampling from
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token sell amount for each sample (sorted in ascending order).
/// @return takerTokenAmounts Taker amounts bought at each taker token
/// amount.
function sampleBuysFromWooPP(
address pool,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
takerTokenData: abi.encode(pool,takerToken, makerToken),
makerTokenData: abi.encode(pool, makerToken, takerToken),
getSellQuoteCallback: _sampleSellForApproximateBuyFromWoofi
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromWoofi(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
) internal view returns (uint256) {
(address _pool, address _takerToken, address _makerToken) = abi.decode(takerTokenData, (address, address, address));
(bool success, bytes memory resultData) = address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromWooPP.selector,
_pool,
_takerToken,
_makerToken,
_toSingleValueArray(sellAmount)
));
if(!success) {
return 0;
}
return abi.decode(resultData, (uint256[]))[0];
}
}

View File

@@ -1897,7 +1897,7 @@ ___
# Interface: SwapQuoteRequestOpts # Interface: SwapQuoteRequestOpts
slippagePercentage: The percentage buffer to add to account for slippage. Affects max ETH price estimates. Defaults to 0.2 (20%). slippagePercentage: The percentage buffer to add to account for slippage. Affects max ETH price estimates. Defaults to 0.01 (1%).
gasPrice: gas price to determine protocolFee amount, default to ethGasStation fast amount gasPrice: gas price to determine protocolFee amount, default to ethGasStation fast amount

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/asset-swapper", "name": "@0x/asset-swapper",
"version": "16.64.0", "version": "16.66.3",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -40,7 +40,7 @@
"config": { "config": {
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker", "publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", "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|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|NativeOrderSampler|PlatypusSampler|SamplerUtils|ShellSampler|SynthetixSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler|VelodromeSampler).json", "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|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|NativeOrderSampler|PlatypusSampler|SamplerUtils|ShellSampler|SynthetixSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler|VelodromeSampler|WooPPSampler).json",
"postpublish": { "postpublish": {
"assets": [] "assets": []
} }
@@ -61,15 +61,16 @@
"dependencies": { "dependencies": {
"@0x/assert": "^3.0.34", "@0x/assert": "^3.0.34",
"@0x/base-contract": "^6.5.0", "@0x/base-contract": "^6.5.0",
"@0x/contract-addresses": "^6.17.0", "@0x/contract-addresses": "^6.19.2",
"@0x/contract-wrappers": "^13.20.5", "@0x/contract-wrappers": "^13.20.8",
"@0x/contracts-erc20": "^3.3.33", "@0x/contracts-erc20": "^3.3.36",
"@0x/contracts-zero-ex": "^0.36.0", "@0x/contracts-zero-ex": "^0.36.3",
"@0x/dev-utils": "^4.2.14", "@0x/dev-utils": "^4.2.14",
"@0x/fast-abi": "^0.0.5",
"@0x/json-schemas": "^6.4.4", "@0x/json-schemas": "^6.4.4",
"@0x/neon-router": "^0.3.5", "@0x/neon-router": "^0.3.5",
"@0x/protocol-utils": "^11.16.0", "@0x/protocol-utils": "^11.16.3",
"@0x/quote-server": "^6.0.6", "@0x/quote-server": "^8.0.0",
"@0x/types": "^3.3.6", "@0x/types": "^3.3.6",
"@0x/utils": "^6.5.3", "@0x/utils": "^6.5.3",
"@0x/web3-wrapper": "^7.6.5", "@0x/web3-wrapper": "^7.6.5",
@@ -85,22 +86,21 @@
"balancer-labs-sor-v1": "npm:@balancer-labs/sor@0.3.2", "balancer-labs-sor-v1": "npm:@balancer-labs/sor@0.3.2",
"cream-sor": "^0.3.3", "cream-sor": "^0.3.3",
"ethereum-types": "^3.7.0", "ethereum-types": "^3.7.0",
"fast-abi": "^0.0.4",
"graphql": "^15.4.0", "graphql": "^15.4.0",
"graphql-request": "^3.4.0", "graphql-request": "^3.4.0",
"heartbeats": "^5.0.1", "heartbeats": "^5.0.1",
"lodash": "^4.17.11" "lodash": "^4.17.15",
"msw": "^0.44.2"
}, },
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^5.8.0", "@0x/abi-gen": "^5.8.0",
"@0x/contracts-gen": "^2.0.46", "@0x/contracts-gen": "^2.0.46",
"@0x/contracts-test-utils": "^5.4.24", "@0x/contracts-test-utils": "^5.4.27",
"@0x/sol-compiler": "^4.8.1", "@0x/sol-compiler": "^4.8.1",
"@0x/subproviders": "^6.6.5", "@0x/subproviders": "^6.6.5",
"@0x/ts-doc-gen": "^0.0.28", "@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.4", "@0x/tslint-config": "^4.1.4",
"@0x/types": "^3.3.6", "@types/lodash": "4.14.137",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",
"@types/node": "12.12.54", "@types/node": "12.12.54",
"chai": "^4.0.1", "chai": "^4.0.1",
@@ -112,7 +112,7 @@
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"nyc": "^11.0.1", "nyc": "^11.0.1",
"shx": "^0.2.2", "shx": "^0.2.2",
"tslint": "5.11.0", "tslint": "^6.1.3",
"typedoc": "~0.16.11", "typedoc": "~0.16.11",
"typemoq": "^2.1.0", "typemoq": "^2.1.0",
"typescript": "4.6.3" "typescript": "4.6.3"

View File

@@ -19,7 +19,7 @@ import {
DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID, DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID,
} from './utils/market_operation_utils/constants'; } from './utils/market_operation_utils/constants';
const ETH_GAS_STATION_API_URL = 'https://ethgasstation.info/api/ethgasAPI.json'; const ZERO_EX_GAS_API_URL = 'https://gas.api.0x.org/source/median';
const NULL_BYTES = '0x'; const NULL_BYTES = '0x';
const NULL_ERC20_ASSET_DATA = '0xf47261b00000000000000000000000000000000000000000000000000000000000000000'; const NULL_ERC20_ASSET_DATA = '0xf47261b00000000000000000000000000000000000000000000000000000000000000000';
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
@@ -48,7 +48,7 @@ const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = {
orderRefreshIntervalMs: 10000, // 10 seconds orderRefreshIntervalMs: 10000, // 10 seconds
...DEFAULT_ORDER_PRUNER_OPTS, ...DEFAULT_ORDER_PRUNER_OPTS,
samplerGasLimit: 500e6, samplerGasLimit: 500e6,
ethGasStationUrl: ETH_GAS_STATION_API_URL, zeroExGasApiUrl: ZERO_EX_GAS_API_URL,
rfqt: { rfqt: {
integratorsWhitelist: [], integratorsWhitelist: [],
makerAssetOfferings: {}, makerAssetOfferings: {},
@@ -95,11 +95,10 @@ export { DEFAULT_FEE_SCHEDULE, DEFAULT_GAS_SCHEDULE } from './utils/market_opera
export const POSITIVE_SLIPPAGE_FEE_TRANSFORMER_GAS = new BigNumber(30000); export const POSITIVE_SLIPPAGE_FEE_TRANSFORMER_GAS = new BigNumber(30000);
// tslint:disable-next-line: custom-no-magic-numbers
export const KEEP_ALIVE_TTL = 5 * 60 * ONE_SECOND_MS; export const KEEP_ALIVE_TTL = 5 * 60 * ONE_SECOND_MS;
export const constants = { export const constants = {
ETH_GAS_STATION_API_URL, ZERO_EX_GAS_API_URL,
PROTOCOL_FEE_MULTIPLIER, PROTOCOL_FEE_MULTIPLIER,
POSITIVE_SLIPPAGE_FEE_TRANSFORMER_GAS, POSITIVE_SLIPPAGE_FEE_TRANSFORMER_GAS,
NULL_BYTES, NULL_BYTES,

View File

@@ -157,8 +157,6 @@ export {
GetMarketOrdersRfqOpts, GetMarketOrdersRfqOpts,
LiquidityProviderFillData, LiquidityProviderFillData,
LiquidityProviderRegistry, LiquidityProviderRegistry,
MarketDepth,
MarketDepthSide,
MooniswapFillData, MooniswapFillData,
MultiHopFillData, MultiHopFillData,
NativeRfqOrderFillData, NativeRfqOrderFillData,

View File

@@ -61,7 +61,6 @@ import {
requiresTransformERC20, requiresTransformERC20,
} from './quote_consumer_utils'; } from './quote_consumer_utils';
// tslint:disable-next-line:custom-no-magic-numbers
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1); const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants; const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants;

View File

@@ -1,9 +1,9 @@
import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addresses'; import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { FastABI } from '@0x/fast-abi';
import { FillQuoteTransformerOrderType, LimitOrder } from '@0x/protocol-utils'; import { FillQuoteTransformerOrderType, LimitOrder } from '@0x/protocol-utils';
import { BigNumber, providerUtils } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import Axios, { AxiosInstance } from 'axios'; import Axios, { AxiosInstance } from 'axios';
import { BlockParamLiteral, MethodAbi, SupportedProvider, ZeroExProvider } from 'ethereum-types'; import { BlockParamLiteral, MethodAbi, SupportedProvider, ZeroExProvider } from 'ethereum-types';
import { FastABI } from 'fast-abi';
import { Agent as HttpAgent } from 'http'; import { Agent as HttpAgent } from 'http';
import { Agent as HttpsAgent } from 'https'; import { Agent as HttpsAgent } from 'https';
import * as _ from 'lodash'; import * as _ from 'lodash';
@@ -36,9 +36,6 @@ import {
FillData, FillData,
GasSchedule, GasSchedule,
GetMarketOrdersOpts, GetMarketOrdersOpts,
MarketDepth,
MarketDepthSide,
MarketSideLiquidity,
OptimizedMarketOrder, OptimizedMarketOrder,
OptimizerResultWithReport, OptimizerResultWithReport,
} from './utils/market_operation_utils/types'; } from './utils/market_operation_utils/types';
@@ -112,7 +109,7 @@ export class SwapQuoter {
}; };
this._protocolFeeUtils = ProtocolFeeUtils.getInstance( this._protocolFeeUtils = ProtocolFeeUtils.getInstance(
constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS, constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS,
options.ethGasStationUrl, options.zeroExGasApiUrl,
); );
// Allow the sampler bytecode to be overwritten using geths override functionality // Allow the sampler bytecode to be overwritten using geths override functionality
const samplerBytecode = _.get(artifacts.ERC20BridgeSampler, 'compilerOutput.evm.deployedBytecode.object'); const samplerBytecode = _.get(artifacts.ERC20BridgeSampler, 'compilerOutput.evm.deployedBytecode.object');
@@ -228,67 +225,6 @@ export class SwapQuoter {
return batchSwapQuotes.filter(x => x !== undefined) as MarketBuySwapQuote[]; return batchSwapQuotes.filter(x => x !== undefined) as MarketBuySwapQuote[];
} }
/**
* Returns the bids and asks liquidity for the entire market.
* For certain sources (like AMM's) it is recommended to provide a practical maximum takerAssetAmount.
* @param makerTokenAddress The address of the maker asset
* @param takerTokenAddress The address of the taker asset
* @param takerAssetAmount The amount to sell and buy for the bids and asks.
*
* @return An object that conforms to MarketDepth that contains all of the samples and liquidity
* information for the source.
*/
public async getBidAskLiquidityForMakerTakerAssetPairAsync(
makerToken: string,
takerToken: string,
takerAssetAmount: BigNumber,
options: Partial<SwapQuoteRequestOpts> = {},
): Promise<MarketDepth> {
assert.isString('makerToken', makerToken);
assert.isString('takerToken', takerToken);
const sourceFilters = new SourceFilters([], options.excludedSources, options.includedSources);
let [sellOrders, buyOrders] = !sourceFilters.isAllowed(ERC20BridgeSource.Native)
? [[], []]
: await Promise.all([
this.orderbook.getOrdersAsync(makerToken, takerToken),
this.orderbook.getOrdersAsync(takerToken, makerToken),
]);
if (!sellOrders || sellOrders.length === 0) {
sellOrders = [createDummyOrder(makerToken, takerToken)];
}
if (!buyOrders || buyOrders.length === 0) {
buyOrders = [createDummyOrder(takerToken, makerToken)];
}
const getMarketDepthSide = (marketSideLiquidity: MarketSideLiquidity): MarketDepthSide => {
const { dexQuotes, nativeOrders } = marketSideLiquidity.quotes;
const { side } = marketSideLiquidity;
return [
...dexQuotes,
nativeOrders.map(o => {
return {
input: side === MarketOperation.Sell ? o.fillableTakerAmount : o.fillableMakerAmount,
output: side === MarketOperation.Sell ? o.fillableMakerAmount : o.fillableTakerAmount,
fillData: o,
source: ERC20BridgeSource.Native,
};
}),
];
};
const [bids, asks] = await Promise.all([
this._marketOperationUtils.getMarketBuyLiquidityAsync(buyOrders, takerAssetAmount, options),
this._marketOperationUtils.getMarketSellLiquidityAsync(sellOrders, takerAssetAmount, options),
]);
return {
bids: getMarketDepthSide(bids),
asks: getMarketDepthSide(asks),
makerTokenDecimals: asks.makerTokenDecimals,
takerTokenDecimals: asks.takerTokenDecimals,
};
}
/** /**
* Returns the recommended gas price for a fast transaction * Returns the recommended gas price for a fast transaction
*/ */

View File

@@ -18,10 +18,10 @@ import {
LiquidityProviderRegistry, LiquidityProviderRegistry,
OptimizedMarketOrder, OptimizedMarketOrder,
} from './utils/market_operation_utils/types'; } from './utils/market_operation_utils/types';
export { SamplerMetrics } from './utils/market_operation_utils/types';
import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from './utils/quote_report_generator'; import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from './utils/quote_report_generator';
import { MetricsProxy } from './utils/quote_requestor'; import { MetricsProxy } from './utils/quote_requestor';
import { TokenAdjacencyGraph } from './utils/token_adjacency_graph'; import { TokenAdjacencyGraph } from './utils/token_adjacency_graph';
export { SamplerMetrics } from './utils/market_operation_utils/types';
export type Address = string; export type Address = string;
@@ -337,7 +337,7 @@ export interface SwapQuoterOpts extends OrderPrunerOpts {
contractAddresses?: AssetSwapperContractAddresses; contractAddresses?: AssetSwapperContractAddresses;
samplerGasLimit?: number; samplerGasLimit?: number;
multiBridgeAddress?: string; multiBridgeAddress?: string;
ethGasStationUrl?: string; zeroExGasApiUrl?: string;
rfqt?: SwapQuoterRfqOpts; rfqt?: SwapQuoterRfqOpts;
samplerOverrides?: SamplerOverrides; samplerOverrides?: SamplerOverrides;
tokenAdjacencyGraph?: TokenAdjacencyGraph; tokenAdjacencyGraph?: TokenAdjacencyGraph;

View File

@@ -104,11 +104,9 @@ function parseIndicativeQuoteResponseFromAltMM(
takerAmount, takerAmount,
// HACK: alt implementation does not return an expiration with indicative quotes // HACK: alt implementation does not return an expiration with indicative quotes
// return now + { IMPUTED EXPIRY SECONDS } to have it included after order checks // return now + { IMPUTED EXPIRY SECONDS } to have it included after order checks
expiry: expiry: new BigNumber(Date.now() / 1000)
// tslint:disable-next-line:custom-no-magic-numbers .integerValue(BigNumber.ROUND_DOWN)
new BigNumber(Date.now() / 1000) .plus(constants.ALT_MM_IMPUTED_INDICATIVE_EXPIRY_SECONDS),
.integerValue(BigNumber.ROUND_DOWN)
.plus(constants.ALT_MM_IMPUTED_INDICATIVE_EXPIRY_SECONDS),
}; };
} }
@@ -243,7 +241,6 @@ export async function returnQuoteFromAltMMAsync<ResponseT>(
// empty response will get filtered out in validation // empty response will get filtered out in validation
const emptyResponse = {}; const emptyResponse = {};
// tslint:disable-next-line:custom-no-magic-numbers
if (response.status !== SUCCESS_CODE) { if (response.status !== SUCCESS_CODE) {
const rejectedRequestInfo = { const rejectedRequestInfo = {
status: response.status, status: response.status,

View File

@@ -40,7 +40,6 @@ interface Cache {
[key: string]: AaveReserve[]; [key: string]: AaveReserve[];
} }
// tslint:disable-next-line:custom-no-magic-numbers
const RESERVES_REFRESH_INTERVAL_MS = 30 * constants.ONE_MINUTE_MS; const RESERVES_REFRESH_INTERVAL_MS = 30 * constants.ONE_MINUTE_MS;
/** /**

View File

@@ -33,8 +33,8 @@ import {
MSTABLE_POOLS_BY_CHAIN_ID, MSTABLE_POOLS_BY_CHAIN_ID,
NERVE_BSC_INFOS, NERVE_BSC_INFOS,
NULL_ADDRESS, NULL_ADDRESS,
PANCAKESWAP_ROUTER_BY_CHAIN_ID,
PANCAKESWAPV2_ROUTER_BY_CHAIN_ID, PANCAKESWAPV2_ROUTER_BY_CHAIN_ID,
PANCAKESWAP_ROUTER_BY_CHAIN_ID,
PANGOLIN_ROUTER_BY_CHAIN_ID, PANGOLIN_ROUTER_BY_CHAIN_ID,
PLATYPUS_AVALANCHE_INFOS, PLATYPUS_AVALANCHE_INFOS,
QUICKSWAP_ROUTER_BY_CHAIN_ID, QUICKSWAP_ROUTER_BY_CHAIN_ID,

View File

@@ -19,7 +19,6 @@ interface Cache {
[key: string]: CToken; [key: string]: CToken;
} }
// tslint:disable-next-line:custom-no-magic-numbers
const CTOKEN_REFRESH_INTERVAL_MS = 30 * constants.ONE_MINUTE_MS; const CTOKEN_REFRESH_INTERVAL_MS = 30 * constants.ONE_MINUTE_MS;
/** /**

View File

@@ -35,9 +35,10 @@ import {
SynthetixFillData, SynthetixFillData,
UniswapV2FillData, UniswapV2FillData,
UniswapV3FillData, UniswapV3FillData,
WOOFiFillData,
} from './types'; } from './types';
// tslint:disable: custom-no-magic-numbers no-bitwise // tslint:disable: no-bitwise
export const ERC20_PROXY_ID = '0xf47261b0'; export const ERC20_PROXY_ID = '0xf47261b0';
export const WALLET_SIGNATURE = '0x04'; export const WALLET_SIGNATURE = '0x04';
@@ -154,6 +155,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.BiSwap, ERC20BridgeSource.BiSwap,
ERC20BridgeSource.MDex, ERC20BridgeSource.MDex,
ERC20BridgeSource.KnightSwap, ERC20BridgeSource.KnightSwap,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Polygon]: new SourceFilters([ [ChainId.Polygon]: new SourceFilters([
ERC20BridgeSource.SushiSwap, ERC20BridgeSource.SushiSwap,
@@ -176,6 +178,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.UniswapV3, ERC20BridgeSource.UniswapV3,
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.MeshSwap, ERC20BridgeSource.MeshSwap,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Avalanche]: new SourceFilters([ [ChainId.Avalanche]: new SourceFilters([
ERC20BridgeSource.MultiHop, ERC20BridgeSource.MultiHop,
@@ -189,6 +192,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.GMX, ERC20BridgeSource.GMX,
ERC20BridgeSource.Platypus, ERC20BridgeSource.Platypus,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Fantom]: new SourceFilters([ [ChainId.Fantom]: new SourceFilters([
ERC20BridgeSource.MultiHop, ERC20BridgeSource.MultiHop,
@@ -202,6 +206,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.SushiSwap, ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.Yoshi, ERC20BridgeSource.Yoshi,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Celo]: new SourceFilters([ [ChainId.Celo]: new SourceFilters([
ERC20BridgeSource.UbeSwap, ERC20BridgeSource.UbeSwap,
@@ -302,6 +307,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.BiSwap, ERC20BridgeSource.BiSwap,
ERC20BridgeSource.MDex, ERC20BridgeSource.MDex,
ERC20BridgeSource.KnightSwap, ERC20BridgeSource.KnightSwap,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Polygon]: new SourceFilters([ [ChainId.Polygon]: new SourceFilters([
ERC20BridgeSource.SushiSwap, ERC20BridgeSource.SushiSwap,
@@ -324,6 +330,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.UniswapV3, ERC20BridgeSource.UniswapV3,
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.MeshSwap, ERC20BridgeSource.MeshSwap,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Avalanche]: new SourceFilters([ [ChainId.Avalanche]: new SourceFilters([
ERC20BridgeSource.MultiHop, ERC20BridgeSource.MultiHop,
@@ -337,6 +344,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.GMX, ERC20BridgeSource.GMX,
ERC20BridgeSource.Platypus, ERC20BridgeSource.Platypus,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Fantom]: new SourceFilters([ [ChainId.Fantom]: new SourceFilters([
ERC20BridgeSource.MultiHop, ERC20BridgeSource.MultiHop,
@@ -350,6 +358,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.SushiSwap, ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.Yoshi, ERC20BridgeSource.Yoshi,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Celo]: new SourceFilters([ [ChainId.Celo]: new SourceFilters([
ERC20BridgeSource.UbeSwap, ERC20BridgeSource.UbeSwap,
@@ -406,23 +415,6 @@ export const SOURCE_FLAGS: { [key in ERC20BridgeSource]: bigint } & {
})), })),
); );
const MIRROR_WRAPPED_TOKENS = {
mAAPL: '0xd36932143f6ebdedd872d5fb0651f4b72fd15a84',
mSLV: '0x9d1555d8cb3c846bb4f7d5b1b1080872c3166676',
mIAU: '0x1d350417d9787e000cc1b95d70e9536dcd91f373',
mAMZN: '0x0cae9e4d663793c2a2a0b211c1cf4bbca2b9caa7',
mGOOGL: '0x4b70ccd1cf9905be1faed025eadbd3ab124efe9a',
mTSLA: '0x21ca39943e91d704678f5d00b6616650f066fd63',
mQQQ: '0x13b02c8de71680e71f0820c996e4be43c2f57d15',
mTWTR: '0xedb0414627e6f1e3f082de65cd4f9c693d78cca9',
mMSFT: '0x41bbedd7286daab5910a1f15d12cbda839852bd7',
mNFLX: '0xc8d674114bac90148d11d3c1d33c61835a0f9dcd',
mBABA: '0x676ce85f66adb8d7b8323aeefe17087a3b8cb363',
mUSO: '0x31c63146a635eb7465e5853020b39713ac356991',
mVIXY: '0xf72fcd9dcf0190923fadd44811e240ef4533fc86',
mLUNA: '0xd2877702675e6ceb975b4a1dff9fb7baf4c91ea9',
};
// Mainnet tokens // Mainnet tokens
// Not an exhaustive list, just enough so we don't repeat ourselves // Not an exhaustive list, just enough so we don't repeat ourselves
export const MAINNET_TOKENS = { export const MAINNET_TOKENS = {
@@ -486,10 +478,7 @@ export const MAINNET_TOKENS = {
vETH: '0x898bad2774eb97cf6b94605677f43b41871410b1', vETH: '0x898bad2774eb97cf6b94605677f43b41871410b1',
alETH: '0x0100546f2cd4c9d97f798ffc9755e47865ff7ee6', alETH: '0x0100546f2cd4c9d97f798ffc9755e47865ff7ee6',
HT: '0x6f259637dcD74C767781E37Bc6133cd6A68aa161', HT: '0x6f259637dcD74C767781E37Bc6133cd6A68aa161',
// Mirror Protocol
UST: '0xa47c8bf37f92abed4a126bda807a7b7498661acd', UST: '0xa47c8bf37f92abed4a126bda807a7b7498661acd',
MIR: '0x09a3ecafa817268f77be1283176b946c4ff2e608',
...MIRROR_WRAPPED_TOKENS,
// StableSwap "open pools" (crv.finance) // StableSwap "open pools" (crv.finance)
STABLEx: '0xcd91538b91b4ba7797d39a2f66e63810b50a33d0', STABLEx: '0xcd91538b91b4ba7797d39a2f66e63810b50a33d0',
alUSD: '0xbc6da0fe9ad5f3b0d58160288917aa56653660e9', alUSD: '0xbc6da0fe9ad5f3b0d58160288917aa56653660e9',
@@ -542,6 +531,7 @@ export const BSC_TOKENS = {
pBTC: '0xed28a457a5a76596ac48d87c0f577020f6ea1c4c', pBTC: '0xed28a457a5a76596ac48d87c0f577020f6ea1c4c',
nUSD: '0x23b891e5c62e0955ae2bd185990103928ab817b3', nUSD: '0x23b891e5c62e0955ae2bd185990103928ab817b3',
BSW: '0x965F527D9159dCe6288a2219DB51fc6Eef120dD1', BSW: '0x965F527D9159dCe6288a2219DB51fc6Eef120dD1',
WOO: '0x4691937a7508860f876c9c0a2a617e7d9e945d4b',
}; };
export const POLYGON_TOKENS = { export const POLYGON_TOKENS = {
@@ -561,6 +551,7 @@ export const POLYGON_TOKENS = {
WEXPOLY: '0x4c4bf319237d98a30a929a96112effa8da3510eb', WEXPOLY: '0x4c4bf319237d98a30a929a96112effa8da3510eb',
nUSD: '0xb6c473756050de474286bed418b77aeac39b02af', nUSD: '0xb6c473756050de474286bed418b77aeac39b02af',
ANY: '0x6aB6d61428fde76768D7b45D8BFeec19c6eF91A8', ANY: '0x6aB6d61428fde76768D7b45D8BFeec19c6eF91A8',
WOO: '0x1b815d120b3ef02039ee11dc2d33de7aa4a8c603',
}; };
export const AVALANCHE_TOKENS = { export const AVALANCHE_TOKENS = {
@@ -587,6 +578,7 @@ export const AVALANCHE_TOKENS = {
UST: '0xb599c3590f42f8f995ecfa0f85d2980b76862fc1', UST: '0xb599c3590f42f8f995ecfa0f85d2980b76862fc1',
FRAX: '0xd24c2ad096400b6fbcd2ad8b24e7acbc21a1da64', FRAX: '0xd24c2ad096400b6fbcd2ad8b24e7acbc21a1da64',
YUSD: '0x111111111111ed1d73f860f57b2798b683f2d325', YUSD: '0x111111111111ed1d73f860f57b2798b683f2d325',
WOO: '0xabc9547b534519ff73921b1fba6e672b5f58d083',
}; };
export const CELO_TOKENS = { export const CELO_TOKENS = {
@@ -646,6 +638,7 @@ export const FANTOM_TOKENS = {
gWBTC: '0x38aca5484b8603373acc6961ecd57a6a594510a3', gWBTC: '0x38aca5484b8603373acc6961ecd57a6a594510a3',
gCRV: '0x690754a168b022331caa2467207c61919b3f8a98', gCRV: '0x690754a168b022331caa2467207c61919b3f8a98',
gMIM: '0xc664fc7b8487a3e10824cda768c1d239f2403bbe', gMIM: '0xc664fc7b8487a3e10824cda768c1d239f2403bbe',
WOO: '0x6626c47c00f1d87902fc13eecfac3ed06d5e8d8a',
}; };
export const OPTIMISM_TOKENS = { export const OPTIMISM_TOKENS = {
@@ -722,8 +715,6 @@ export const CURVE_POOLS = {
eurt: '0xfd5db7463a3ab53fd211b4af195c5bccc1a03890', eurt: '0xfd5db7463a3ab53fd211b4af195c5bccc1a03890',
ethcrv: '0x8301ae4fc9c624d1d396cbdaa1ed877821d7c511', ethcrv: '0x8301ae4fc9c624d1d396cbdaa1ed877821d7c511',
ethcvx: '0xb576491f1e6e5e62f1d8f26062ee822b40b0e0d4', ethcvx: '0xb576491f1e6e5e62f1d8f26062ee822b40b0e0d4',
mimust: '0x55a8a39bc9694714e2874c1ce77aa1e599461e18',
usttri_wormhole: '0xceaf7747579696a2f0bb206a14210e3c9e6fb269',
fei_tri: '0x06cb22615ba53e60d67bf6c341a0fd5e718e1655', fei_tri: '0x06cb22615ba53e60d67bf6c341a0fd5e718e1655',
rai_tri: '0x618788357d0ebd8a37e763adab3bc575d54c2c7d', rai_tri: '0x618788357d0ebd8a37e763adab3bc575d54c2c7d',
DOLA_tri: '0xaa5a67c256e27a5d80712c51971408db3370927d', DOLA_tri: '0xaa5a67c256e27a5d80712c51971408db3370927d',
@@ -864,6 +855,39 @@ export const PLATYPUS_AVALANCHE_POOLS = {
sAVAX: '0x4658ea7e9960d6158a261104aaa160cc953bb6ba', sAVAX: '0x4658ea7e9960d6158a261104aaa160cc953bb6ba',
}; };
export const WOOFI_POOL_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0xbf365ce9cfcb2d5855521985e351ba3bcf77fd3f',
[ChainId.Fantom]: '0x9503e7517d3c5bc4f9e4a1c6ae4f8b33ac2546f2',
[ChainId.Avalanche]: '0x1df3009c57a8b143c6246149f00b090bce3b8f88',
[ChainId.Polygon]: '0x7400b665c8f4f3a951a99f1ee9872efb8778723d',
},
NULL_ADDRESS,
);
export const WOOFI_SUPPORTED_TOKENS = new Set([
BSC_TOKENS.USDT,
BSC_TOKENS.WBNB,
BSC_TOKENS.WOO,
BSC_TOKENS.WETH,
BSC_TOKENS.BTCB,
AVALANCHE_TOKENS.nUSDC,
AVALANCHE_TOKENS.WAVAX,
AVALANCHE_TOKENS.WBTC,
AVALANCHE_TOKENS.WETH,
AVALANCHE_TOKENS.WOO,
FANTOM_TOKENS.USDC,
FANTOM_TOKENS.WFTM,
FANTOM_TOKENS.WETH,
FANTOM_TOKENS.WBTC,
FANTOM_TOKENS.WOO,
POLYGON_TOKENS.USDC,
POLYGON_TOKENS.WMATIC,
POLYGON_TOKENS.WBTC,
POLYGON_TOKENS.WETH,
POLYGON_TOKENS.WOO,
]);
export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>( export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
{ {
[ChainId.Mainnet]: [ [ChainId.Mainnet]: [
@@ -949,8 +973,6 @@ export const DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID = valueByChainId<TokenAdj
{ {
[ChainId.Mainnet]: new TokenAdjacencyGraphBuilder(DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID[ChainId.Mainnet]) [ChainId.Mainnet]: new TokenAdjacencyGraphBuilder(DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID[ChainId.Mainnet])
.tap(builder => { .tap(builder => {
// Mirror Protocol
builder.add(MAINNET_TOKENS.MIR, MAINNET_TOKENS.UST);
// Convex and Curve // Convex and Curve
builder.addBidirectional(MAINNET_TOKENS.cvxCRV, MAINNET_TOKENS.CRV); builder.addBidirectional(MAINNET_TOKENS.cvxCRV, MAINNET_TOKENS.CRV);
// Convex and FXS // Convex and FXS
@@ -1358,16 +1380,6 @@ export const CURVE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_uint256, sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_uint256,
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying_uint256, exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying_uint256,
}, },
[CURVE_POOLS.mimust]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.MIM, MAINNET_TOKENS.UST],
pool: CURVE_POOLS.mimust,
gasSchedule: 105e3,
}),
[CURVE_POOLS.usttri_wormhole]: createCurveMetaTriPool({
tokens: [MAINNET_TOKENS.UST_WORMHOLE],
pool: CURVE_POOLS.usttri_wormhole,
gasSchedule: 340e3,
}),
[CURVE_POOLS.fei_tri]: createCurveMetaTriPool({ [CURVE_POOLS.fei_tri]: createCurveMetaTriPool({
tokens: [MAINNET_TOKENS.FEI], tokens: [MAINNET_TOKENS.FEI],
pool: CURVE_POOLS.fei_tri, pool: CURVE_POOLS.fei_tri,
@@ -2176,7 +2188,6 @@ export const LIDO_INFO_BY_CHAIN = valueByChainId<LidoInfo>(
}, },
); );
export const BALANCER_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer';
export const BALANCER_TOP_POOLS_FETCHED = 250; export const BALANCER_TOP_POOLS_FETCHED = 250;
export const BALANCER_MAX_POOLS_FETCHED = 3; export const BALANCER_MAX_POOLS_FETCHED = 3;
@@ -2473,7 +2484,6 @@ const uniswapV2CloneGasSchedule = (fillData?: FillData) => {
* I.e remove the overhead cost of ExchangeProxy (130k) and * I.e remove the overhead cost of ExchangeProxy (130k) and
* the ethereum transaction cost (21k) * the ethereum transaction cost (21k)
*/ */
// tslint:disable:custom-no-magic-numbers
export const DEFAULT_GAS_SCHEDULE: Required<GasSchedule> = { export const DEFAULT_GAS_SCHEDULE: Required<GasSchedule> = {
[ERC20BridgeSource.Native]: fillData => { [ERC20BridgeSource.Native]: fillData => {
// TODO jacob re-order imports so there is no circular rependency with SignedNativeOrder // TODO jacob re-order imports so there is no circular rependency with SignedNativeOrder
@@ -2647,7 +2657,19 @@ export const DEFAULT_GAS_SCHEDULE: Required<GasSchedule> = {
[ERC20BridgeSource.CheeseSwap]: uniswapV2CloneGasSchedule, [ERC20BridgeSource.CheeseSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.WaultSwap]: uniswapV2CloneGasSchedule, [ERC20BridgeSource.WaultSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.ACryptos]: fillData => (fillData as CurveFillData).pool.gasSchedule, [ERC20BridgeSource.ACryptos]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.WOOFi]: (fillData?: FillData) => {
const woofiFillData = fillData as WOOFiFillData;
const quoteTokenAddresses = [BSC_TOKENS.USDT, AVALANCHE_TOKENS.nUSDC, FANTOM_TOKENS.USDC, POLYGON_TOKENS.USDC];
if (
quoteTokenAddresses.includes(woofiFillData.takerToken) ||
quoteTokenAddresses.includes(woofiFillData.makerToken)
) {
return 500e3;
} else {
return 100e4;
}
},
// //
// Polygon // Polygon
// //
@@ -2698,10 +2720,7 @@ export const POSITIVE_SLIPPAGE_FEE_TRANSFORMER_GAS = new BigNumber(20000);
export const DEFAULT_FEE_ESTIMATE = { gas: 0, fee: ZERO_AMOUNT }; export const DEFAULT_FEE_ESTIMATE = { gas: 0, fee: ZERO_AMOUNT };
// tslint:enable:custom-no-magic-numbers
export const DEFAULT_GET_MARKET_ORDERS_OPTS: Omit<GetMarketOrdersOpts, 'gasPrice'> = { export const DEFAULT_GET_MARKET_ORDERS_OPTS: Omit<GetMarketOrdersOpts, 'gasPrice'> = {
// tslint:disable-next-line: custom-no-magic-numbers
runLimit: 2 ** 15, runLimit: 2 ** 15,
excludedSources: [], excludedSources: [],
excludedFeeSources: [], excludedFeeSources: [],

View File

@@ -29,7 +29,6 @@ import {
PriceComparisonsReport, PriceComparisonsReport,
QuoteReport, QuoteReport,
} from './../quote_report_generator'; } from './../quote_report_generator';
import { getComparisonPrices } from './comparison_price'; import { getComparisonPrices } from './comparison_price';
import { import {
BUY_SOURCE_FILTER_BY_CHAIN_ID, BUY_SOURCE_FILTER_BY_CHAIN_ID,
@@ -862,14 +861,9 @@ export class MarketOperationUtils {
} }
private async _refreshPoolCacheIfRequiredAsync(takerToken: string, makerToken: string): Promise<void> { private async _refreshPoolCacheIfRequiredAsync(takerToken: string, makerToken: string): Promise<void> {
void Promise.all( _.values(this._sampler.poolsCaches)
Object.values(this._sampler.poolsCaches).map(async cache => { .filter(cache => cache !== undefined && !cache.isFresh(takerToken, makerToken))
if (!cache || cache.isFresh(takerToken, makerToken)) { .forEach(cache => cache?.getFreshPoolsForPairAsync(takerToken, makerToken));
return Promise.resolve([]);
}
return cache.getFreshPoolsForPairAsync(takerToken, makerToken);
}),
);
} }
} }

View File

@@ -43,6 +43,7 @@ import {
UniswapV3FillData, UniswapV3FillData,
UniswapV3PathAmount, UniswapV3PathAmount,
VelodromeFillData, VelodromeFillData,
WOOFiFillData,
} from './types'; } from './types';
// tslint:disable completed-docs // tslint:disable completed-docs
@@ -213,6 +214,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.Velodrome, 'Velodrome'); return encodeBridgeSourceId(BridgeProtocol.Velodrome, 'Velodrome');
case ERC20BridgeSource.Synthetix: case ERC20BridgeSource.Synthetix:
return encodeBridgeSourceId(BridgeProtocol.Synthetix, 'Synthetix'); return encodeBridgeSourceId(BridgeProtocol.Synthetix, 'Synthetix');
case ERC20BridgeSource.WOOFi:
return encodeBridgeSourceId(BridgeProtocol.WOOFi, 'WOOFi');
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);
} }
@@ -402,6 +405,10 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
fillData.makerTokenSymbolBytes32, fillData.makerTokenSymbolBytes32,
]); ]);
break; break;
case ERC20BridgeSource.WOOFi:
const woofiFillData = (order as OptimizedMarketBridgeOrder<WOOFiFillData>).fillData;
bridgeData = encoder.encode([woofiFillData.poolAddress]);
break;
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);
} }
@@ -529,6 +536,7 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.Geist]: AbiEncoder.create('(address,address)'), [ERC20BridgeSource.Geist]: AbiEncoder.create('(address,address)'),
[ERC20BridgeSource.Velodrome]: AbiEncoder.create('(address,bool)'), [ERC20BridgeSource.Velodrome]: AbiEncoder.create('(address,bool)'),
[ERC20BridgeSource.Synthetix]: AbiEncoder.create('(address,bytes32,bytes32)'), [ERC20BridgeSource.Synthetix]: AbiEncoder.create('(address,bytes32,bytes32)'),
[ERC20BridgeSource.WOOFi]: AbiEncoder.create('(address)'),
}; };
function getFillTokenAmounts(fill: Fill, side: MarketOperation): [BigNumber, BigNumber] { function getFillTokenAmounts(fill: Fill, side: MarketOperation): [BigNumber, BigNumber] {

View File

@@ -14,7 +14,7 @@ import { dexSampleToFill, ethToOutputAmount, nativeOrderToFill } from './fills';
import { Path, PathPenaltyOpts } from './path'; import { Path, PathPenaltyOpts } from './path';
import { DexSample, ERC20BridgeSource, FeeSchedule, Fill, FillAdjustor, FillData, SamplerMetrics } from './types'; import { DexSample, ERC20BridgeSource, FeeSchedule, Fill, FillAdjustor, FillData, SamplerMetrics } from './types';
// tslint:disable: prefer-for-of custom-no-magic-numbers completed-docs no-bitwise // tslint:disable: prefer-for-of completed-docs no-bitwise
// NOTE: The Rust router will panic with less than 3 samples // NOTE: The Rust router will panic with less than 3 samples
const MIN_NUM_SAMPLE_INPUTS = 3; const MIN_NUM_SAMPLE_INPUTS = 3;

View File

@@ -1,16 +1,19 @@
import { ChainId } from '@0x/contract-addresses';
import { getPoolsWithTokens, parsePoolData } from 'balancer-labs-sor-v1'; import { getPoolsWithTokens, parsePoolData } from 'balancer-labs-sor-v1';
import { Pool } from 'balancer-labs-sor-v1/dist/types'; import { Pool } from 'balancer-labs-sor-v1/dist/types';
import { gql, request } from 'graphql-request'; import { gql, request } from 'graphql-request';
import { DEFAULT_WARNING_LOGGER } from '../../../constants'; import { DEFAULT_WARNING_LOGGER } from '../../../constants';
import { LogFunction } from '../../../types'; import { LogFunction } from '../../../types';
import { BALANCER_MAX_POOLS_FETCHED, BALANCER_SUBGRAPH_URL, BALANCER_TOP_POOLS_FETCHED } from '../constants'; import { BALANCER_MAX_POOLS_FETCHED, BALANCER_TOP_POOLS_FETCHED } from '../constants';
import { CacheValue, PoolsCache } from './pools_cache'; import { NoOpPoolsCache } from './no_op_pools_cache';
import { AbstractPoolsCache, CacheValue, PoolsCache } from './pools_cache';
// tslint:disable:custom-no-magic-numbers
const ONE_DAY_MS = 24 * 60 * 60 * 1000; const ONE_DAY_MS = 24 * 60 * 60 * 1000;
// tslint:enable:custom-no-magic-numbers // tslint:disable: member-ordering
const BALANCER_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer';
interface BalancerPoolResponse { interface BalancerPoolResponse {
id: string; id: string;
@@ -20,10 +23,18 @@ interface BalancerPoolResponse {
totalWeight: string; totalWeight: string;
} }
export class BalancerPoolsCache extends PoolsCache { export class BalancerPoolsCache extends AbstractPoolsCache {
constructor( public static create(chainId: ChainId): PoolsCache {
if (chainId !== ChainId.Mainnet) {
return new NoOpPoolsCache();
}
return new BalancerPoolsCache();
}
private constructor(
private readonly _subgraphUrl: string = BALANCER_SUBGRAPH_URL, private readonly _subgraphUrl: string = BALANCER_SUBGRAPH_URL,
cache: { [key: string]: CacheValue } = {}, cache: Map<string, CacheValue> = new Map(),
private readonly maxPoolsFetched: number = BALANCER_MAX_POOLS_FETCHED, private readonly maxPoolsFetched: number = BALANCER_MAX_POOLS_FETCHED,
private readonly _topPoolsFetched: number = BALANCER_TOP_POOLS_FETCHED, private readonly _topPoolsFetched: number = BALANCER_TOP_POOLS_FETCHED,
private readonly _warningLogger: LogFunction = DEFAULT_WARNING_LOGGER, private readonly _warningLogger: LogFunction = DEFAULT_WARNING_LOGGER,

View File

@@ -9,13 +9,15 @@ import { LogFunction } from '../../../types';
import { BALANCER_MAX_POOLS_FETCHED, BALANCER_TOP_POOLS_FETCHED } from '../constants'; import { BALANCER_MAX_POOLS_FETCHED, BALANCER_TOP_POOLS_FETCHED } from '../constants';
import { parsePoolData } from './balancer_sor_v2'; import { parsePoolData } from './balancer_sor_v2';
import { CacheValue, PoolsCache } from './pools_cache'; import { NoOpPoolsCache } from './no_op_pools_cache';
import { AbstractPoolsCache, CacheValue, PoolsCache } from './pools_cache';
// tslint:disable: member-ordering
const BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN = new Map<ChainId, string>([ const BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN = new Map<ChainId, string>([
[ChainId.Fantom, 'https://api.thegraph.com/subgraphs/name/beethovenxfi/beethovenx'], [ChainId.Fantom, 'https://api.thegraph.com/subgraphs/name/beethovenxfi/beethovenx'],
]); ]);
// tslint:disable-next-line:custom-no-magic-numbers
const ONE_DAY_MS = 24 * 60 * 60 * 1000; const ONE_DAY_MS = 24 * 60 * 60 * 1000;
interface BalancerPoolResponse { interface BalancerPoolResponse {
@@ -28,11 +30,11 @@ interface BalancerPoolResponse {
amp: string | null; amp: string | null;
} }
export class BalancerV2PoolsCache extends PoolsCache { export class BalancerV2PoolsCache extends AbstractPoolsCache {
public static createBeethovenXPoolCache(chainId: ChainId): BalancerV2PoolsCache | undefined { public static createBeethovenXPoolCache(chainId: ChainId): PoolsCache {
const subgraphUrl = BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN.get(chainId); const subgraphUrl = BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN.get(chainId);
if (subgraphUrl === undefined) { if (subgraphUrl === undefined) {
return undefined; return new NoOpPoolsCache();
} }
return new BalancerV2PoolsCache(subgraphUrl); return new BalancerV2PoolsCache(subgraphUrl);
@@ -58,12 +60,12 @@ export class BalancerV2PoolsCache extends PoolsCache {
}; };
} }
constructor( private constructor(
private readonly subgraphUrl: string, private readonly subgraphUrl: string,
private readonly maxPoolsFetched: number = BALANCER_MAX_POOLS_FETCHED, private readonly maxPoolsFetched: number = BALANCER_MAX_POOLS_FETCHED,
private readonly _topPoolsFetched: number = BALANCER_TOP_POOLS_FETCHED, private readonly _topPoolsFetched: number = BALANCER_TOP_POOLS_FETCHED,
private readonly _warningLogger: LogFunction = DEFAULT_WARNING_LOGGER, private readonly _warningLogger: LogFunction = DEFAULT_WARNING_LOGGER,
cache: { [key: string]: CacheValue } = {}, cache: Map<string, CacheValue> = new Map(),
) { ) {
super(cache); super(cache);
void this._loadTopPoolsAsync(); void this._loadTopPoolsAsync();

View File

@@ -20,7 +20,6 @@ import { BalancerSwapInfo, BalancerSwaps } from '../types';
import { CacheValue, EMPTY_BALANCER_SWAPS, SwapInfoCache } from './pair_swaps_cache'; import { CacheValue, EMPTY_BALANCER_SWAPS, SwapInfoCache } from './pair_swaps_cache';
import { SubgraphPoolDataService } from './sgPoolDataService'; import { SubgraphPoolDataService } from './sgPoolDataService';
// tslint:disable-next-line:custom-no-magic-numbers
const ONE_DAY_MS = 24 * 60 * 60 * ONE_SECOND_MS; const ONE_DAY_MS = 24 * 60 * 60 * ONE_SECOND_MS;
export interface BalancerPoolResponse { export interface BalancerPoolResponse {

View File

@@ -1,18 +1,20 @@
import { ChainId } from '@0x/contract-addresses';
import { Pool } from 'balancer-labs-sor-v1/dist/types'; import { Pool } from 'balancer-labs-sor-v1/dist/types';
import { getPoolsWithTokens, parsePoolData } from 'cream-sor'; import { getPoolsWithTokens, parsePoolData } from 'cream-sor';
import { BALANCER_MAX_POOLS_FETCHED } from '../constants'; import { BALANCER_MAX_POOLS_FETCHED } from '../constants';
import { CacheValue, PoolsCache } from './pools_cache'; import { NoOpPoolsCache } from './no_op_pools_cache';
import { AbstractPoolsCache, CacheValue, PoolsCache } from './pools_cache';
export class CreamPoolsCache extends PoolsCache { export class CreamPoolsCache extends AbstractPoolsCache {
constructor( public static create(chainId: ChainId): PoolsCache {
_cache: { [key: string]: CacheValue } = {}, if (chainId !== ChainId.Mainnet) {
private readonly maxPoolsFetched: number = BALANCER_MAX_POOLS_FETCHED, return new NoOpPoolsCache();
) { }
super(_cache);
return new CreamPoolsCache();
} }
protected async _fetchPoolsForPairAsync(takerToken: string, makerToken: string): Promise<Pool[]> { protected async _fetchPoolsForPairAsync(takerToken: string, makerToken: string): Promise<Pool[]> {
try { try {
const poolData = (await getPoolsWithTokens(takerToken, makerToken)).pools; const poolData = (await getPoolsWithTokens(takerToken, makerToken)).pools;
@@ -25,4 +27,10 @@ export class CreamPoolsCache extends PoolsCache {
return []; return [];
} }
} }
private constructor(
_cache: Map<string, CacheValue> = new Map(),
private readonly maxPoolsFetched: number = BALANCER_MAX_POOLS_FETCHED,
) {
super(_cache);
}
} }

View File

@@ -1,4 +1,4 @@
export { BalancerPoolsCache } from './balancer_utils'; export { BalancerPoolsCache } from './balancer_pools_cache';
export { BalancerV2PoolsCache } from './balancer_v2_utils'; export { BalancerV2PoolsCache } from './balancer_v2_pools_cache';
export { CreamPoolsCache } from './cream_utils'; export { CreamPoolsCache } from './cream_pools_cache';
export { PoolsCache } from './pools_cache'; export { AbstractPoolsCache, PoolsCache } from './pools_cache';

View File

@@ -0,0 +1,21 @@
import { Pool, PoolsCache } from './pools_cache';
// tslint:disable:prefer-function-over-method
export class NoOpPoolsCache implements PoolsCache {
public async getFreshPoolsForPairAsync(
_takerToken: string,
_makerToken: string,
_timeoutMs?: number | undefined,
): Promise<Pool[]> {
return [];
}
public getPoolAddressesForPair(_takerToken: string, _makerToken: string): string[] {
return [];
}
public isFresh(_takerToken: string, _makerToken: string): boolean {
return true;
}
}

View File

@@ -1,18 +1,15 @@
import { BalancerSwaps } from '../types';
import { ONE_HOUR_IN_SECONDS, ONE_SECOND_MS } from '../constants'; import { ONE_HOUR_IN_SECONDS, ONE_SECOND_MS } from '../constants';
import { BalancerSwaps } from '../types';
export interface CacheValue { export interface CacheValue {
expiresAt: number; expiresAt: number;
balancerSwaps: BalancerSwaps; balancerSwaps: BalancerSwaps;
} }
// tslint:disable:custom-no-magic-numbers
// Cache results for 30mins // Cache results for 30mins
const DEFAULT_CACHE_TIME_MS = (ONE_HOUR_IN_SECONDS / 2) * ONE_SECOND_MS; const DEFAULT_CACHE_TIME_MS = (ONE_HOUR_IN_SECONDS / 2) * ONE_SECOND_MS;
const DEFAULT_TIMEOUT_MS = ONE_SECOND_MS; const DEFAULT_TIMEOUT_MS = ONE_SECOND_MS;
export const EMPTY_BALANCER_SWAPS = { swapInfoExactIn: [], swapInfoExactOut: [] }; export const EMPTY_BALANCER_SWAPS = { swapInfoExactIn: [], swapInfoExactOut: [] };
// tslint:enable:custom-no-magic-numbers
/** /**
* Caches SwapInfo for a pair of tokens. * Caches SwapInfo for a pair of tokens.

View File

@@ -7,18 +7,30 @@ export interface CacheValue {
pools: Pool[]; pools: Pool[];
} }
// tslint:disable:custom-no-magic-numbers
// Cache results for 30mins // Cache results for 30mins
const DEFAULT_CACHE_TIME_MS = (ONE_HOUR_IN_SECONDS / 2) * ONE_SECOND_MS; const DEFAULT_CACHE_TIME_MS = (ONE_HOUR_IN_SECONDS / 2) * ONE_SECOND_MS;
const DEFAULT_TIMEOUT_MS = 1000; const DEFAULT_TIMEOUT_MS = 3000;
// tslint:enable:custom-no-magic-numbers
export abstract class PoolsCache { export interface PoolsCache {
protected static _isExpired(value: CacheValue): boolean { getFreshPoolsForPairAsync(takerToken: string, makerToken: string, timeoutMs?: number): Promise<Pool[]>;
getPoolAddressesForPair(takerToken: string, makerToken: string): string[];
isFresh(takerToken: string, makerToken: string): boolean;
}
export abstract class AbstractPoolsCache implements PoolsCache {
protected static _getKey(takerToken: string, makerToken: string): string {
return `${takerToken}-${makerToken}`;
}
protected static _isExpired(value: CacheValue | undefined): boolean {
if (value === undefined) {
return true;
}
return Date.now() >= value.expiresAt; return Date.now() >= value.expiresAt;
} }
constructor( constructor(
protected readonly _cache: { [key: string]: CacheValue }, protected readonly _cache: Map<string, CacheValue>,
protected readonly _cacheTimeMs: number = DEFAULT_CACHE_TIME_MS, protected readonly _cacheTimeMs: number = DEFAULT_CACHE_TIME_MS,
) {} ) {}
@@ -31,47 +43,42 @@ export abstract class PoolsCache {
return Promise.race([this._getAndSaveFreshPoolsForPairAsync(takerToken, makerToken), timeout]); return Promise.race([this._getAndSaveFreshPoolsForPairAsync(takerToken, makerToken), timeout]);
} }
public getCachedPoolAddressesForPair( /**
takerToken: string, * Returns pool addresses (can be stale) for a pair.
makerToken: string, *
ignoreExpired: boolean = true, * An empty array will be returned if cache does not exist.
): string[] | undefined { */
const key = JSON.stringify([takerToken, makerToken]); public getPoolAddressesForPair(takerToken: string, makerToken: string): string[] {
const value = this._cache[key]; const value = this._getValue(takerToken, makerToken);
if (ignoreExpired) { return value === undefined ? [] : value.pools.map(pool => pool.id);
return value === undefined ? [] : value.pools.map(pool => pool.id);
}
if (!value) {
return undefined;
}
if (PoolsCache._isExpired(value)) {
return undefined;
}
return (value || []).pools.map(pool => pool.id);
} }
public isFresh(takerToken: string, makerToken: string): boolean { public isFresh(takerToken: string, makerToken: string): boolean {
const cached = this.getCachedPoolAddressesForPair(takerToken, makerToken, false); const value = this._getValue(takerToken, makerToken);
return cached !== undefined; return !AbstractPoolsCache._isExpired(value);
}
protected _getValue(takerToken: string, makerToken: string): CacheValue | undefined {
const key = AbstractPoolsCache._getKey(takerToken, makerToken);
return this._cache.get(key);
} }
protected async _getAndSaveFreshPoolsForPairAsync(takerToken: string, makerToken: string): Promise<Pool[]> { protected async _getAndSaveFreshPoolsForPairAsync(takerToken: string, makerToken: string): Promise<Pool[]> {
const key = JSON.stringify([takerToken, makerToken]); const key = AbstractPoolsCache._getKey(takerToken, makerToken);
const value = this._cache[key]; const value = this._cache.get(key);
if (value === undefined || value.expiresAt >= Date.now()) { if (!AbstractPoolsCache._isExpired(value)) {
const pools = await this._fetchPoolsForPairAsync(takerToken, makerToken); return value!.pools;
const expiresAt = Date.now() + this._cacheTimeMs;
this._cachePoolsForPair(takerToken, makerToken, pools, expiresAt);
} }
return this._cache[key].pools;
const pools = await this._fetchPoolsForPairAsync(takerToken, makerToken);
const expiresAt = Date.now() + this._cacheTimeMs;
this._cachePoolsForPair(takerToken, makerToken, pools, expiresAt);
return pools;
} }
protected _cachePoolsForPair(takerToken: string, makerToken: string, pools: Pool[], expiresAt: number): void { protected _cachePoolsForPair(takerToken: string, makerToken: string, pools: Pool[], expiresAt: number): void {
const key = JSON.stringify([takerToken, makerToken]); const key = AbstractPoolsCache._getKey(takerToken, makerToken);
this._cache[key] = { this._cache.set(key, { pools, expiresAt });
pools,
expiresAt,
};
} }
protected abstract _fetchPoolsForPairAsync(takerToken: string, makerToken: string): Promise<Pool[]>; protected abstract _fetchPoolsForPairAsync(takerToken: string, makerToken: string): Promise<Pool[]>;

View File

@@ -26,9 +26,9 @@ import {
AAVE_V2_SUBGRAPH_URL_BY_CHAIN_ID, AAVE_V2_SUBGRAPH_URL_BY_CHAIN_ID,
AVALANCHE_TOKENS, AVALANCHE_TOKENS,
BALANCER_V2_VAULT_ADDRESS_BY_CHAIN, BALANCER_V2_VAULT_ADDRESS_BY_CHAIN,
BANCOR_REGISTRY_BY_CHAIN_ID,
BANCORV3_NETWORK_BY_CHAIN_ID, BANCORV3_NETWORK_BY_CHAIN_ID,
BANCORV3_NETWORK_INFO_BY_CHAIN_ID, BANCORV3_NETWORK_INFO_BY_CHAIN_ID,
BANCOR_REGISTRY_BY_CHAIN_ID,
BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN, BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN,
COMPOUND_API_URL_BY_CHAIN_ID, COMPOUND_API_URL_BY_CHAIN_ID,
DODOV1_CONFIG_BY_CHAIN_ID, DODOV1_CONFIG_BY_CHAIN_ID,
@@ -52,12 +52,14 @@ import {
UNISWAPV1_ROUTER_BY_CHAIN_ID, UNISWAPV1_ROUTER_BY_CHAIN_ID,
UNISWAPV3_CONFIG_BY_CHAIN_ID, UNISWAPV3_CONFIG_BY_CHAIN_ID,
VELODROME_ROUTER_BY_CHAIN_ID, VELODROME_ROUTER_BY_CHAIN_ID,
WOOFI_POOL_BY_CHAIN_ID,
WOOFI_SUPPORTED_TOKENS,
ZERO_AMOUNT, ZERO_AMOUNT,
} from './constants'; } from './constants';
import { getGeistInfoForPair } from './geist_utils'; import { getGeistInfoForPair } from './geist_utils';
import { getLiquidityProvidersForPair } from './liquidity_provider_utils'; import { getLiquidityProvidersForPair } from './liquidity_provider_utils';
import { BalancerPoolsCache, BalancerV2PoolsCache, CreamPoolsCache } from './pools_cache'; import { BalancerPoolsCache, BalancerV2PoolsCache, CreamPoolsCache, PoolsCache } from './pools_cache';
import { BalancerV2SwapInfoCache } from './pools_cache/balancer_v2_utils_new'; import { BalancerV2SwapInfoCache } from './pools_cache/balancer_v2_swap_info_cache';
import { SamplerContractOperation } from './sampler_contract_operation'; import { SamplerContractOperation } from './sampler_contract_operation';
import { SamplerNoOperation } from './sampler_no_operation'; import { SamplerNoOperation } from './sampler_no_operation';
import { SourceFilters } from './source_filters'; import { SourceFilters } from './source_filters';
@@ -99,6 +101,7 @@ import {
UniswapV2FillData, UniswapV2FillData,
UniswapV3FillData, UniswapV3FillData,
VelodromeFillData, VelodromeFillData,
WOOFiFillData,
} from './types'; } from './types';
/** /**
@@ -114,10 +117,10 @@ export const TWO_HOP_SOURCE_FILTERS = SourceFilters.all().exclude([
export const BATCH_SOURCE_FILTERS = SourceFilters.all().exclude([ERC20BridgeSource.MultiHop, ERC20BridgeSource.Native]); export const BATCH_SOURCE_FILTERS = SourceFilters.all().exclude([ERC20BridgeSource.MultiHop, ERC20BridgeSource.Native]);
export interface PoolsCacheMap { export interface PoolsCacheMap {
[ERC20BridgeSource.Balancer]: BalancerPoolsCache; [ERC20BridgeSource.Balancer]: PoolsCache;
[ERC20BridgeSource.BalancerV2]: BalancerV2SwapInfoCache | undefined; [ERC20BridgeSource.BalancerV2]: BalancerV2SwapInfoCache | undefined;
[ERC20BridgeSource.Beethovenx]: BalancerV2PoolsCache | undefined; [ERC20BridgeSource.Beethovenx]: PoolsCache;
[ERC20BridgeSource.Cream]: CreamPoolsCache; [ERC20BridgeSource.Cream]: PoolsCache;
} }
// tslint:disable:no-inferred-empty-object-type no-unbound-method // tslint:disable:no-inferred-empty-object-type no-unbound-method
@@ -156,8 +159,8 @@ export class SamplerOperations {
? poolsCaches ? poolsCaches
: { : {
[ERC20BridgeSource.Beethovenx]: BalancerV2PoolsCache.createBeethovenXPoolCache(chainId), [ERC20BridgeSource.Beethovenx]: BalancerV2PoolsCache.createBeethovenXPoolCache(chainId),
[ERC20BridgeSource.Balancer]: new BalancerPoolsCache(), [ERC20BridgeSource.Balancer]: BalancerPoolsCache.create(chainId),
[ERC20BridgeSource.Cream]: new CreamPoolsCache(), [ERC20BridgeSource.Cream]: CreamPoolsCache.create(chainId),
[ERC20BridgeSource.BalancerV2]: [ERC20BridgeSource.BalancerV2]:
BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[chainId] === NULL_ADDRESS BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[chainId] === NULL_ADDRESS
? undefined ? undefined
@@ -1364,6 +1367,35 @@ export class SamplerOperations {
}, },
}); });
} }
public getWOOFiSellQuotes(
poolAddress: string,
takerToken: string,
makerToken: string,
makerFillAmounts: BigNumber[],
): SourceQuoteOperation<WOOFiFillData> {
return new SamplerContractOperation({
fillData: { poolAddress, takerToken, makerToken },
source: ERC20BridgeSource.WOOFi,
contract: this._samplerContract,
function: this._samplerContract.sampleSellsFromWooPP,
params: [poolAddress, takerToken, makerToken, makerFillAmounts],
});
}
public getWOOFiBuyQuotes(
poolAddress: string,
takerToken: string,
makerToken: string,
makerFillAmounts: BigNumber[],
): SourceQuoteOperation<WOOFiFillData> {
return new SamplerContractOperation({
fillData: { poolAddress, takerToken, makerToken },
source: ERC20BridgeSource.WOOFi,
contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromWooPP,
params: [poolAddress, takerToken, makerToken, makerFillAmounts],
});
}
/** /**
* Returns the best price for the native token * Returns the best price for the native token
@@ -1592,20 +1624,17 @@ export class SamplerOperations {
), ),
]; ];
case ERC20BridgeSource.Balancer: case ERC20BridgeSource.Balancer:
return ( return this.poolsCaches[ERC20BridgeSource.Balancer]
this.poolsCaches[ERC20BridgeSource.Balancer].getCachedPoolAddressesForPair( .getPoolAddressesForPair(takerToken, makerToken)
takerToken, .map(balancerPool =>
makerToken, this.getBalancerSellQuotes(
) || [] balancerPool,
).map(balancerPool => makerToken,
this.getBalancerSellQuotes( takerToken,
balancerPool, takerFillAmounts,
makerToken, ERC20BridgeSource.Balancer,
takerToken, ),
takerFillAmounts, );
ERC20BridgeSource.Balancer,
),
);
case ERC20BridgeSource.BalancerV2: { case ERC20BridgeSource.BalancerV2: {
const cache = this.poolsCaches[source]; const cache = this.poolsCaches[source];
if (!cache) { if (!cache) {
@@ -1624,18 +1653,14 @@ export class SamplerOperations {
} }
case ERC20BridgeSource.Beethovenx: { case ERC20BridgeSource.Beethovenx: {
const cache = this.poolsCaches[source]; const cache = this.poolsCaches[source];
if (cache === undefined) { const poolAddresses = cache.getPoolAddressesForPair(takerToken, makerToken);
return [];
}
const poolIds = cache.getCachedPoolAddressesForPair(takerToken, makerToken) || [];
const vault = BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; const vault = BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId];
if (vault === NULL_ADDRESS) { if (vault === NULL_ADDRESS) {
return []; return [];
} }
return poolIds.map(poolId => return poolAddresses.map(poolAddress =>
this.getBalancerV2SellQuotes( this.getBalancerV2SellQuotes(
{ poolId, vault }, { poolId: poolAddress, vault },
makerToken, makerToken,
takerToken, takerToken,
takerFillAmounts, takerFillAmounts,
@@ -1644,20 +1669,17 @@ export class SamplerOperations {
); );
} }
case ERC20BridgeSource.Cream: case ERC20BridgeSource.Cream:
return ( return this.poolsCaches[ERC20BridgeSource.Cream]
this.poolsCaches[ERC20BridgeSource.Cream].getCachedPoolAddressesForPair( .getPoolAddressesForPair(takerToken, makerToken)
takerToken, .map(creamPool =>
makerToken, this.getBalancerSellQuotes(
) || [] creamPool,
).map(creamPool => makerToken,
this.getBalancerSellQuotes( takerToken,
creamPool, takerFillAmounts,
makerToken, ERC20BridgeSource.Cream,
takerToken, ),
takerFillAmounts, );
ERC20BridgeSource.Cream,
),
);
case ERC20BridgeSource.Dodo: case ERC20BridgeSource.Dodo:
if (!isValidAddress(DODOV1_CONFIG_BY_CHAIN_ID[this.chainId].registry)) { if (!isValidAddress(DODOV1_CONFIG_BY_CHAIN_ID[this.chainId].registry)) {
return []; return [];
@@ -1810,6 +1832,17 @@ export class SamplerOperations {
takerFillAmounts, takerFillAmounts,
); );
} }
case ERC20BridgeSource.WOOFi: {
if (!(WOOFI_SUPPORTED_TOKENS.has(takerToken) && WOOFI_SUPPORTED_TOKENS.has(makerToken))) {
return [];
}
return this.getWOOFiSellQuotes(
WOOFI_POOL_BY_CHAIN_ID[this.chainId],
takerToken,
makerToken,
takerFillAmounts,
);
}
default: default:
throw new Error(`Unsupported sell sample source: ${source}`); throw new Error(`Unsupported sell sample source: ${source}`);
} }
@@ -1948,20 +1981,17 @@ export class SamplerOperations {
), ),
]; ];
case ERC20BridgeSource.Balancer: case ERC20BridgeSource.Balancer:
return ( return this.poolsCaches[ERC20BridgeSource.Balancer]
this.poolsCaches[ERC20BridgeSource.Balancer].getCachedPoolAddressesForPair( .getPoolAddressesForPair(takerToken, makerToken)
takerToken, .map(poolAddress =>
makerToken, this.getBalancerBuyQuotes(
) || [] poolAddress,
).map(poolAddress => makerToken,
this.getBalancerBuyQuotes( takerToken,
poolAddress, makerFillAmounts,
makerToken, ERC20BridgeSource.Balancer,
takerToken, ),
makerFillAmounts, );
ERC20BridgeSource.Balancer,
),
);
case ERC20BridgeSource.BalancerV2: { case ERC20BridgeSource.BalancerV2: {
const cache = this.poolsCaches[source]; const cache = this.poolsCaches[source];
if (!cache) { if (!cache) {
@@ -1986,11 +2016,7 @@ export class SamplerOperations {
} }
case ERC20BridgeSource.Beethovenx: { case ERC20BridgeSource.Beethovenx: {
const cache = this.poolsCaches[source]; const cache = this.poolsCaches[source];
if (cache === undefined) { const poolIds = cache.getPoolAddressesForPair(takerToken, makerToken) || [];
return [];
}
const poolIds = cache.getCachedPoolAddressesForPair(takerToken, makerToken) || [];
const vault = BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; const vault = BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId];
if (vault === NULL_ADDRESS) { if (vault === NULL_ADDRESS) {
return []; return [];
@@ -2006,20 +2032,17 @@ export class SamplerOperations {
); );
} }
case ERC20BridgeSource.Cream: case ERC20BridgeSource.Cream:
return ( return this.poolsCaches[ERC20BridgeSource.Cream]
this.poolsCaches[ERC20BridgeSource.Cream].getCachedPoolAddressesForPair( .getPoolAddressesForPair(takerToken, makerToken)
takerToken, .map(poolAddress =>
makerToken, this.getBalancerBuyQuotes(
) || [] poolAddress,
).map(poolAddress => makerToken,
this.getBalancerBuyQuotes( takerToken,
poolAddress, makerFillAmounts,
makerToken, ERC20BridgeSource.Cream,
takerToken, ),
makerFillAmounts, );
ERC20BridgeSource.Cream,
),
);
case ERC20BridgeSource.Dodo: case ERC20BridgeSource.Dodo:
if (!isValidAddress(DODOV1_CONFIG_BY_CHAIN_ID[this.chainId].registry)) { if (!isValidAddress(DODOV1_CONFIG_BY_CHAIN_ID[this.chainId].registry)) {
return []; return [];
@@ -2160,6 +2183,17 @@ export class SamplerOperations {
makerFillAmounts, makerFillAmounts,
); );
} }
case ERC20BridgeSource.WOOFi: {
if (!(WOOFI_SUPPORTED_TOKENS.has(takerToken) && WOOFI_SUPPORTED_TOKENS.has(makerToken))) {
return [];
}
return this.getWOOFiBuyQuotes(
WOOFI_POOL_BY_CHAIN_ID[this.chainId],
takerToken,
makerToken,
makerFillAmounts,
);
}
default: default:
throw new Error(`Unsupported buy sample source: ${source}`); throw new Error(`Unsupported buy sample source: ${source}`);
} }

View File

@@ -69,6 +69,7 @@ export enum ERC20BridgeSource {
Synapse = 'Synapse', Synapse = 'Synapse',
BancorV3 = 'BancorV3', BancorV3 = 'BancorV3',
Synthetix = 'Synthetix', Synthetix = 'Synthetix',
WOOFi = 'WOOFi',
// BSC only // BSC only
PancakeSwap = 'PancakeSwap', PancakeSwap = 'PancakeSwap',
PancakeSwapV2 = 'PancakeSwap_V2', PancakeSwapV2 = 'PancakeSwap_V2',
@@ -373,6 +374,12 @@ export interface PlatypusFillData extends FillData {
tokenAddressPath: string[]; tokenAddressPath: string[];
} }
export interface WOOFiFillData extends FillData {
poolAddress: string;
takerToken: string;
makerToken: string;
}
export interface VelodromeFillData extends FillData { export interface VelodromeFillData extends FillData {
router: string; router: string;
stable: boolean; stable: boolean;
@@ -617,15 +624,6 @@ export interface OptimizerResultWithReport extends OptimizerResult {
priceComparisonsReport?: PriceComparisonsReport; priceComparisonsReport?: PriceComparisonsReport;
} }
export type MarketDepthSide = Array<Array<DexSample<FillData>>>;
export interface MarketDepth {
bids: MarketDepthSide;
asks: MarketDepthSide;
makerTokenDecimals: number;
takerTokenDecimals: number;
}
export interface MarketSideLiquidity { export interface MarketSideLiquidity {
side: MarketOperation; side: MarketOperation;
inputAmount: BigNumber; inputAmount: BigNumber;

View File

@@ -6,28 +6,36 @@ import { SwapQuoterError } from '../types';
const MAX_ERROR_COUNT = 5; const MAX_ERROR_COUNT = 5;
interface GasOracleResponse {
result: {
// gas price in wei
fast: number;
};
}
export class ProtocolFeeUtils { export class ProtocolFeeUtils {
private static _instance: ProtocolFeeUtils; private static _instance: ProtocolFeeUtils;
private readonly _ethGasStationUrl!: string; private readonly _zeroExGasApiUrl: string;
private readonly _gasPriceHeart: any; private readonly _gasPriceHeart: any;
private _gasPriceEstimation: BigNumber = constants.ZERO_AMOUNT; private _gasPriceEstimation: BigNumber = constants.ZERO_AMOUNT;
private _errorCount: number = 0; private _errorCount: number = 0;
public static getInstance( public static getInstance(
gasPricePollingIntervalInMs: number, gasPricePollingIntervalInMs: number,
ethGasStationUrl: string = constants.ETH_GAS_STATION_API_URL, zeroExGasApiUrl: string = constants.ZERO_EX_GAS_API_URL,
initialGasPrice: BigNumber = constants.ZERO_AMOUNT, initialGasPrice: BigNumber = constants.ZERO_AMOUNT,
): ProtocolFeeUtils { ): ProtocolFeeUtils {
if (!ProtocolFeeUtils._instance) { if (!ProtocolFeeUtils._instance) {
ProtocolFeeUtils._instance = new ProtocolFeeUtils( ProtocolFeeUtils._instance = new ProtocolFeeUtils(
gasPricePollingIntervalInMs, gasPricePollingIntervalInMs,
ethGasStationUrl, zeroExGasApiUrl,
initialGasPrice, initialGasPrice,
); );
} }
return ProtocolFeeUtils._instance; return ProtocolFeeUtils._instance;
} }
/** @returns gas price (in wei) */
public async getGasPriceEstimationOrThrowAsync(shouldHardRefresh?: boolean): Promise<BigNumber> { public async getGasPriceEstimationOrThrowAsync(shouldHardRefresh?: boolean): Promise<BigNumber> {
if (this._gasPriceEstimation.eq(constants.ZERO_AMOUNT)) { if (this._gasPriceEstimation.eq(constants.ZERO_AMOUNT)) {
return this._getGasPriceFromGasStationOrThrowAsync(); return this._getGasPriceFromGasStationOrThrowAsync();
@@ -48,27 +56,21 @@ export class ProtocolFeeUtils {
private constructor( private constructor(
gasPricePollingIntervalInMs: number, gasPricePollingIntervalInMs: number,
ethGasStationUrl: string = constants.ETH_GAS_STATION_API_URL, zeroExGasApiUrl: string = constants.ZERO_EX_GAS_API_URL,
initialGasPrice: BigNumber = constants.ZERO_AMOUNT, initialGasPrice: BigNumber = constants.ZERO_AMOUNT,
) { ) {
this._gasPriceHeart = heartbeats.createHeart(gasPricePollingIntervalInMs); this._gasPriceHeart = heartbeats.createHeart(gasPricePollingIntervalInMs);
this._gasPriceEstimation = initialGasPrice; this._gasPriceEstimation = initialGasPrice;
this._ethGasStationUrl = ethGasStationUrl; this._zeroExGasApiUrl = zeroExGasApiUrl;
this._initializeHeartBeat(); this._initializeHeartBeat();
} }
// tslint:disable-next-line: prefer-function-over-method // tslint:disable-next-line: prefer-function-over-method
private async _getGasPriceFromGasStationOrThrowAsync(): Promise<BigNumber> { private async _getGasPriceFromGasStationOrThrowAsync(): Promise<BigNumber> {
try { try {
const res = await fetch(this._ethGasStationUrl); const res = await fetch(this._zeroExGasApiUrl);
const gasInfo = await res.json(); const gasInfo: GasOracleResponse = await res.json();
// Eth Gas Station result is gwei * 10 const gasPriceWei = new BigNumber(gasInfo.result.fast);
// tslint:disable-next-line:custom-no-magic-numbers
const BASE_TEN = 10;
const gasPriceGwei = new BigNumber(gasInfo.fast / BASE_TEN);
// tslint:disable-next-line:custom-no-magic-numbers
const unit = new BigNumber(BASE_TEN).pow(9);
const gasPriceWei = unit.times(gasPriceGwei);
// Reset the error count to 0 once we have a successful response // Reset the error count to 0 once we have a successful response
this._errorCount = 0; this._errorCount = 0;
return gasPriceWei; return gasPriceWei;

View File

@@ -51,6 +51,7 @@ import * as UniswapV2Sampler from '../test/generated-artifacts/UniswapV2Sampler.
import * as UniswapV3Sampler from '../test/generated-artifacts/UniswapV3Sampler.json'; import * as UniswapV3Sampler from '../test/generated-artifacts/UniswapV3Sampler.json';
import * as UtilitySampler from '../test/generated-artifacts/UtilitySampler.json'; import * as UtilitySampler from '../test/generated-artifacts/UtilitySampler.json';
import * as VelodromeSampler from '../test/generated-artifacts/VelodromeSampler.json'; import * as VelodromeSampler from '../test/generated-artifacts/VelodromeSampler.json';
import * as WooPPSampler from '../test/generated-artifacts/WooPPSampler.json';
export const artifacts = { export const artifacts = {
ApproximateBuys: ApproximateBuys as ContractArtifact, ApproximateBuys: ApproximateBuys as ContractArtifact,
BalanceChecker: BalanceChecker as ContractArtifact, BalanceChecker: BalanceChecker as ContractArtifact,
@@ -84,6 +85,7 @@ export const artifacts = {
UniswapV3Sampler: UniswapV3Sampler as ContractArtifact, UniswapV3Sampler: UniswapV3Sampler as ContractArtifact,
UtilitySampler: UtilitySampler as ContractArtifact, UtilitySampler: UtilitySampler as ContractArtifact,
VelodromeSampler: VelodromeSampler as ContractArtifact, VelodromeSampler: VelodromeSampler as ContractArtifact,
WooPPSampler: WooPPSampler as ContractArtifact,
IBalancer: IBalancer as ContractArtifact, IBalancer: IBalancer as ContractArtifact,
IBalancerV2Vault: IBalancerV2Vault as ContractArtifact, IBalancerV2Vault: IBalancerV2Vault as ContractArtifact,
IBancor: IBancor as ContractArtifact, IBancor: IBancor as ContractArtifact,

View File

@@ -24,7 +24,7 @@ import {
SOURCE_FLAGS, SOURCE_FLAGS,
ZERO_AMOUNT, ZERO_AMOUNT,
} from '../src/utils/market_operation_utils/constants'; } from '../src/utils/market_operation_utils/constants';
import { PoolsCache } from '../src/utils/market_operation_utils/pools_cache'; import { AbstractPoolsCache } from '../src/utils/market_operation_utils/pools_cache';
import { DexOrderSampler } from '../src/utils/market_operation_utils/sampler'; import { DexOrderSampler } from '../src/utils/market_operation_utils/sampler';
import { BATCH_SOURCE_FILTERS } from '../src/utils/market_operation_utils/sampler_operations'; import { BATCH_SOURCE_FILTERS } from '../src/utils/market_operation_utils/sampler_operations';
import { SourceFilters } from '../src/utils/market_operation_utils/source_filters'; import { SourceFilters } from '../src/utils/market_operation_utils/source_filters';
@@ -98,9 +98,9 @@ async function getMarketBuyOrdersAsync(
return utils.getOptimizerResultAsync(nativeOrders, makerAmount, MarketOperation.Buy, opts); return utils.getOptimizerResultAsync(nativeOrders, makerAmount, MarketOperation.Buy, opts);
} }
class MockPoolsCache extends PoolsCache { class MockPoolsCache extends AbstractPoolsCache {
constructor(private readonly _handler: (takerToken: string, makerToken: string) => Pool[]) { constructor(private readonly _handler: (takerToken: string, makerToken: string) => Pool[]) {
super({}); super(new Map());
} }
protected async _fetchPoolsForPairAsync(takerToken: string, makerToken: string): Promise<Pool[]> { protected async _fetchPoolsForPairAsync(takerToken: string, makerToken: string): Promise<Pool[]> {
return this._handler(takerToken, makerToken); return this._handler(takerToken, makerToken);

View File

@@ -28,12 +28,12 @@ describe('Pools Caches for Balancer-based sampling', () => {
expect(pools.length).greaterThan(0, `Failed to find any pools for ${takerToken} and ${makerToken}`); expect(pools.length).greaterThan(0, `Failed to find any pools for ${takerToken} and ${makerToken}`);
expect(pools[0]).not.undefined(); expect(pools[0]).not.undefined();
expect(Object.keys(pools[0])).to.include.members(poolKeys); expect(Object.keys(pools[0])).to.include.members(poolKeys);
const cachedPoolIds = cache.getCachedPoolAddressesForPair(takerToken, makerToken); const cachedPoolIds = cache.getPoolAddressesForPair(takerToken, makerToken);
expect(cachedPoolIds).to.deep.equal(pools.map(p => p.id)); expect(cachedPoolIds).to.deep.equal(pools.map(p => p.id));
} }
describe('BalancerPoolsCache', () => { describe('BalancerPoolsCache', () => {
const cache = new BalancerPoolsCache(); const cache = BalancerPoolsCache.create(ChainId.Mainnet);
it('fetches pools', async () => { it('fetches pools', async () => {
const pairs = [ const pairs = [
[usdcAddress, daiAddress], [usdcAddress, daiAddress],
@@ -58,15 +58,14 @@ describe('Pools Caches for Balancer-based sampling', () => {
[wftmAddress, fantomWethAddress], [wftmAddress, fantomWethAddress],
]; ];
expect(cache).not.null();
await Promise.all( await Promise.all(
pairs.map(async ([takerToken, makerToken]) => fetchAndAssertPoolsAsync(cache!, takerToken, makerToken)), pairs.map(async ([takerToken, makerToken]) => fetchAndAssertPoolsAsync(cache, takerToken, makerToken)),
); );
}); });
}); });
describe('CreamPoolsCache', () => { describe('CreamPoolsCache', () => {
const cache = new CreamPoolsCache(); const cache = CreamPoolsCache.create(ChainId.Mainnet);
it('fetches pools', async () => { it('fetches pools', async () => {
const pairs = [ const pairs = [
[usdcAddress, creamAddress], [usdcAddress, creamAddress],

View File

@@ -0,0 +1,45 @@
import * as chai from 'chai';
import 'mocha';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { ProtocolFeeUtils } from '../src';
import { chaiSetup } from './utils/chai_setup';
chaiSetup.configure();
const expect = chai.expect;
const server = setupServer(
rest.get('https://mock-0x-gas-api.org/median', (_req, res, ctx) => {
return res(
ctx.json({
result: {
source: 'MEDIAN',
timestamp: 1659386474,
instant: 22000000000,
fast: 18848500000,
standard: 14765010000,
low: 13265000000,
},
}),
);
}),
);
describe('ProtocolFeeUtils', () => {
describe('getGasPriceEstimationOrThrowAsync', () => {
beforeEach(() => {
server.listen();
});
afterEach(() => {
server.close();
});
it('parses fast gas price response correctly', async () => {
const utils = ProtocolFeeUtils.getInstance(420000, 'https://mock-0x-gas-api.org/median');
const gasPrice = await utils.getGasPriceEstimationOrThrowAsync();
expect(gasPrice.toNumber()).to.eq(18848500000);
});
});
});

View File

@@ -49,3 +49,4 @@ export * from '../test/generated-wrappers/uniswap_v2_sampler';
export * from '../test/generated-wrappers/uniswap_v3_sampler'; export * from '../test/generated-wrappers/uniswap_v3_sampler';
export * from '../test/generated-wrappers/utility_sampler'; export * from '../test/generated-wrappers/utility_sampler';
export * from '../test/generated-wrappers/velodrome_sampler'; export * from '../test/generated-wrappers/velodrome_sampler';
export * from '../test/generated-wrappers/woo_p_p_sampler';

View File

@@ -51,6 +51,7 @@
"test/generated-artifacts/UniswapV2Sampler.json", "test/generated-artifacts/UniswapV2Sampler.json",
"test/generated-artifacts/UniswapV3Sampler.json", "test/generated-artifacts/UniswapV3Sampler.json",
"test/generated-artifacts/UtilitySampler.json", "test/generated-artifacts/UtilitySampler.json",
"test/generated-artifacts/VelodromeSampler.json" "test/generated-artifacts/VelodromeSampler.json",
"test/generated-artifacts/WooPPSampler.json"
] ]
} }

View File

@@ -1,6 +1,8 @@
{ {
"extends": ["@0x/tslint-config"], "extends": ["@0x/tslint-config"],
"rules": { "rules": {
"array-type": false,
"custom-no-magic-numbers": false,
"max-file-line-count": false, "max-file-line-count": false,
"binary-expression-operand-order": false "binary-expression-operand-order": false
}, },

View File

@@ -1,4 +1,33 @@
[ [
{
"timestamp": 1660093941,
"version": "6.19.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "6.19.1",
"changes": [
{
"note": "Fix lowercase addresses",
"pr": 543
}
],
"timestamp": 1660073235
},
{
"version": "6.19.0",
"changes": [
{
"note": "Goerli and Mumbai updated verified contracts addresses",
"pr": 537
}
],
"timestamp": 1659750766
},
{ {
"version": "6.17.0", "version": "6.17.0",
"changes": [ "changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v6.19.2 - _August 10, 2022_
* Dependencies updated
## v6.19.1 - _August 9, 2022_
* Fix lowercase addresses (#543)
## v6.19.0 - _August 6, 2022_
* Goerli and Mumbai updated verified contracts addresses (#537)
## v6.17.0 - _July 27, 2022_ ## v6.17.0 - _July 27, 2022_
* Goerli and Mumbai * Goerli and Mumbai

View File

@@ -153,18 +153,18 @@
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000", "chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
"maximumGasPrice": "0x0000000000000000000000000000000000000000", "maximumGasPrice": "0x0000000000000000000000000000000000000000",
"dexForwarderBridge": "0x0000000000000000000000000000000000000000", "dexForwarderBridge": "0x0000000000000000000000000000000000000000",
"exchangeProxyGovernor": "0x7cee06249e371a1ecf8107e912294432f7f70832", "exchangeProxyGovernor": "0xf289f8a9d26f9a32ecc8602e92e634d71a91d490",
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", "exchangeProxy": "0xf91bb752490473b8342a3e964e855b9f9a2a668e",
"exchangeProxyTransformerDeployer": "0x2bef57ffde3098eeed9fa4f9166a81d7377533dc", "exchangeProxyTransformerDeployer": "0x7b4f0063cc0097c19c6b8cc74ecaf630621e2be6",
"exchangeProxyFlashWallet": "0xdb6f1920a889355780af7570773609bd8cb1f498", "exchangeProxyFlashWallet": "0xf15469c80a1965f5f90be5651fcb6c6f3392b2a1",
"exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000", "exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000",
"zrxTreasury": "0x0000000000000000000000000000000000000000", "zrxTreasury": "0x0000000000000000000000000000000000000000",
"transformers": { "transformers": {
"wethTransformer": "0xad550dbef7b93a42e335062e808d66a70eca5a0a", "wethTransformer": "0x5e485f1ab8aa2a71d533f2bc15af64dd10fa44e9",
"payTakerTransformer": "0xbd3fec19e4d91a79b329b6b4a6f210c66a40a97f", "payTakerTransformer": "0x0c59ced2ffce5fceb40f665def2146f76c576f34",
"affiliateFeeTransformer": "0x59e7371b613a6f3879694bf9db2fe3117c92a927", "affiliateFeeTransformer": "0x6f4d30df1ecaed54239af95efa2964f9252fd0a3",
"fillQuoteTransformer": "0x3edbf102250d59230ff6d3fc648f97c094f3cb27", "fillQuoteTransformer": "0x841b18c263a290c41ac41b6afbf4c1d31b0c6b36",
"positiveSlippageFeeTransformer": "0x48997b11bbc15c2fa2f141c9e93a0a2ab789a761" "positiveSlippageFeeTransformer": "0x5d6ab5729a08775c69035730bcfbad65759c4f4d"
} }
}, },
"42": { "42": {
@@ -247,7 +247,7 @@
"wethTransformer": "0xac3d95668c092e895cd83a9cbafe9c7d9906471f", "wethTransformer": "0xac3d95668c092e895cd83a9cbafe9c7d9906471f",
"payTakerTransformer": "0x4f5e8ca2cadecd4a467ae441e4b03de4278a4574", "payTakerTransformer": "0x4f5e8ca2cadecd4a467ae441e4b03de4278a4574",
"affiliateFeeTransformer": "0x1be34ab9b2acb5c4ddd89454bdce637967e65230", "affiliateFeeTransformer": "0x1be34ab9b2acb5c4ddd89454bdce637967e65230",
"fillQuoteTransformer": "0x0b72d55485e8d877f73cc8b14ea3e010b3e804fd", "fillQuoteTransformer": "0xbd7fd6e116fc8589bb658fba3a2cc6273050bcf2",
"positiveSlippageFeeTransformer": "0x7f5c79ad1788573b1145f4651a248523c54f5d1f" "positiveSlippageFeeTransformer": "0x7f5c79ad1788573b1145f4651a248523c54f5d1f"
} }
}, },
@@ -331,7 +331,7 @@
"wethTransformer": "0xe309d011cc6f189a3e8dcba85922715a019fed38", "wethTransformer": "0xe309d011cc6f189a3e8dcba85922715a019fed38",
"payTakerTransformer": "0x5ba7b9be86cda01cfbf56e0fb97184783be9dda1", "payTakerTransformer": "0x5ba7b9be86cda01cfbf56e0fb97184783be9dda1",
"affiliateFeeTransformer": "0xbed27284b42e5684e987169cf1da09c5d6c49fa8", "affiliateFeeTransformer": "0xbed27284b42e5684e987169cf1da09c5d6c49fa8",
"fillQuoteTransformer": "0xd4a518760030dae1adbde9496f8a3b478e83932a", "fillQuoteTransformer": "0x01c082e47c8dc6dedd01e3fcb07bfd3eb72e044d",
"positiveSlippageFeeTransformer": "0x4cd8f1c0df4d40fcc1e073845d5f6f4ed5cc8dab" "positiveSlippageFeeTransformer": "0x4cd8f1c0df4d40fcc1e073845d5f6f4ed5cc8dab"
} }
}, },
@@ -363,18 +363,18 @@
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000", "chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
"maximumGasPrice": "0x0000000000000000000000000000000000000000", "maximumGasPrice": "0x0000000000000000000000000000000000000000",
"dexForwarderBridge": "0x0000000000000000000000000000000000000000", "dexForwarderBridge": "0x0000000000000000000000000000000000000000",
"exchangeProxyGovernor": "0x4cf19577bcb5e784f315e952f97a6dc247f03140", "exchangeProxyGovernor": "0x30186b2e187aeddabf019089f9375a8dc53138e4",
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff", "exchangeProxy": "0xf471d32cb40837bf24529fcf17418fc1a4807626",
"exchangeProxyTransformerDeployer": "0xa8220408bcb5b327875fd82145d379a83dfd7d61", "exchangeProxyTransformerDeployer": "0x05481589f447a0767def2b0ed98a04ea5f5eba50",
"exchangeProxyFlashWallet": "0xdb6f1920a889355780af7570773609bd8cb1f498", "exchangeProxyFlashWallet": "0x64254cf2f3abd765bee46f8445b76e2bb0af5a2c",
"exchangeProxyLiquidityProviderSandbox": "0xe6f76f5090f8d64015113841a0c9bc5d14755d6f", "exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000",
"zrxTreasury": "0x0000000000000000000000000000000000000000", "zrxTreasury": "0x0000000000000000000000000000000000000000",
"transformers": { "transformers": {
"wethTransformer": "0x44a65ee6b33f70eda7b854abe8d81e925984c932", "wethTransformer": "0x445af2e5791cc9a72f81c49a3dc90cf3b03d2a62",
"payTakerTransformer": "0x2f4868ed9cae9a4cdba063818dce19f411be4e75", "payTakerTransformer": "0xe3e8652fb306873f9dc87222423ffd51b967f014",
"affiliateFeeTransformer": "0x843c0ac5b1b373be51800c8f1caffe54cc29dd22", "affiliateFeeTransformer": "0xbd901aff2ce18355537594a17ebb0a38ca44d8b6",
"fillQuoteTransformer": "0x750cb81ee6d64e29e1e358ba155925000bf044d4", "fillQuoteTransformer": "0xbfac39aea3c0a6222266cef674ec39c3b5387852",
"positiveSlippageFeeTransformer": "0x30aebc4c68effa70e21612b39b94299a8778d0cb" "positiveSlippageFeeTransformer": "0x33ab86b46d84d30538a9b35c7ece4d5673caa778"
} }
}, },
"43114": { "43114": {
@@ -415,7 +415,7 @@
"wethTransformer": "0x9b8b52391071d71cd4ad1e61d7f273268fa34c6c", "wethTransformer": "0x9b8b52391071d71cd4ad1e61d7f273268fa34c6c",
"payTakerTransformer": "0x898c6fde239d646c73f0a57e3570b6f86a3d62a3", "payTakerTransformer": "0x898c6fde239d646c73f0a57e3570b6f86a3d62a3",
"affiliateFeeTransformer": "0x34617b855411e52fbc05899435f44cbd0503022c", "affiliateFeeTransformer": "0x34617b855411e52fbc05899435f44cbd0503022c",
"fillQuoteTransformer": "0xb6c9c52ce7094fc96d8bd5d3ecd0c6feeafe3457", "fillQuoteTransformer": "0xcee9118bc14e1fe740c54c754b901629b322ee4f",
"positiveSlippageFeeTransformer": "0x470ba89da18a6db6e8a0567b3c9214b960861857" "positiveSlippageFeeTransformer": "0x470ba89da18a6db6e8a0567b3c9214b960861857"
} }
}, },
@@ -457,7 +457,7 @@
"wethTransformer": "0x9b6aa8f26a92108e7d1f66373d757bb955112703", "wethTransformer": "0x9b6aa8f26a92108e7d1f66373d757bb955112703",
"payTakerTransformer": "0x32df54951d33d7460e15fa59b1fcc262183ce4c2", "payTakerTransformer": "0x32df54951d33d7460e15fa59b1fcc262183ce4c2",
"affiliateFeeTransformer": "0x67efa679a4b56c38713d478e649c88247f4f8e88", "affiliateFeeTransformer": "0x67efa679a4b56c38713d478e649c88247f4f8e88",
"fillQuoteTransformer": "0x641efe8a57ad39353fe22f77d211ef6b17b0590b", "fillQuoteTransformer": "0xe40f81ef6e9c95ba04c659b8d032eab73152aafd",
"positiveSlippageFeeTransformer": "0xe87d69b285005cc82b53b844322652c49ed64600" "positiveSlippageFeeTransformer": "0xe87d69b285005cc82b53b844322652c49ed64600"
} }
}, },

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contract-addresses", "name": "@0x/contract-addresses",
"version": "6.17.0", "version": "6.19.2",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },

View File

@@ -1,4 +1,31 @@
[ [
{
"timestamp": 1660093941,
"version": "13.20.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1660073235,
"version": "13.20.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1659750766,
"version": "13.20.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1658950329, "timestamp": 1658950329,
"version": "13.20.5", "version": "13.20.5",

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v13.20.8 - _August 10, 2022_
* Dependencies updated
## v13.20.7 - _August 9, 2022_
* Dependencies updated
## v13.20.6 - _August 6, 2022_
* Dependencies updated
## v13.20.5 - _July 27, 2022_ ## v13.20.5 - _July 27, 2022_
* Dependencies updated * Dependencies updated

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contract-wrappers", "name": "@0x/contract-wrappers",
"version": "13.20.5", "version": "13.20.8",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -57,7 +57,7 @@
"dependencies": { "dependencies": {
"@0x/assert": "^3.0.34", "@0x/assert": "^3.0.34",
"@0x/base-contract": "^6.5.0", "@0x/base-contract": "^6.5.0",
"@0x/contract-addresses": "^6.17.0", "@0x/contract-addresses": "^6.19.2",
"@0x/json-schemas": "^6.4.4", "@0x/json-schemas": "^6.4.4",
"@0x/types": "^3.3.6", "@0x/types": "^3.3.6",
"@0x/utils": "^6.5.3", "@0x/utils": "^6.5.3",

View File

@@ -1,4 +1,31 @@
[ [
{
"timestamp": 1660093941,
"version": "11.16.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1660073235,
"version": "11.16.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1659750766,
"version": "11.16.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"version": "11.16.0", "version": "11.16.0",
"changes": [ "changes": [

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v11.16.3 - _August 10, 2022_
* Dependencies updated
## v11.16.2 - _August 9, 2022_
* Dependencies updated
## v11.16.1 - _August 6, 2022_
* Dependencies updated
## v11.16.0 - _July 27, 2022_ ## v11.16.0 - _July 27, 2022_
* Add Synthetix support` (#518) * Add Synthetix support` (#518)

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/protocol-utils", "name": "@0x/protocol-utils",
"version": "11.16.0", "version": "11.16.3",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -63,8 +63,8 @@
}, },
"dependencies": { "dependencies": {
"@0x/assert": "^3.0.34", "@0x/assert": "^3.0.34",
"@0x/contract-addresses": "^6.17.0", "@0x/contract-addresses": "^6.19.2",
"@0x/contract-wrappers": "^13.20.5", "@0x/contract-wrappers": "^13.20.8",
"@0x/json-schemas": "^6.4.4", "@0x/json-schemas": "^6.4.4",
"@0x/subproviders": "^6.6.5", "@0x/subproviders": "^6.6.5",
"@0x/utils": "^6.5.3", "@0x/utils": "^6.5.3",

View File

@@ -141,6 +141,7 @@ export enum BridgeProtocol {
BancorV3, BancorV3,
Velodrome, Velodrome,
Synthetix, Synthetix,
WOOFi,
} }
// tslint:enable: enum-naming // tslint:enable: enum-naming

1072
yarn.lock

File diff suppressed because it is too large Load Diff