Compare commits

...

108 Commits

Author SHA1 Message Date
Github Actions
40b6d9a56a Publish
- @0x/asset-swapper@16.62.1
2022-06-15 11:19:29 -04:00
Github Actions
faac36d8d8 Updated CHANGELOGS & MD docs 2022-06-15 11:19:29 -04:00
Kyu
291ba8f28e Empty commit to trigger CI 2022-06-15 11:19:29 -04:00
Ido Kleinman
79565bd2f4 Remove nUSD from intermediate liquidity to save on sampler gas (#505)
* remote nUSD from intermediate liquidity

* changelog
2022-06-15 11:19:29 -04:00
Github Actions
4d55bc11c9 Publish
- @0x/contracts-erc20@3.3.32
 - @0x/contracts-test-utils@5.4.23
 - @0x/contracts-treasury@1.4.15
 - @0x/contracts-utils@4.8.13
 - @0x/contracts-zero-ex@0.35.0
 - @0x/asset-swapper@16.62.0
 - @0x/contract-addresses@6.16.0
 - @0x/contract-wrappers@13.20.4
 - @0x/protocol-utils@11.15.0
2022-06-15 11:19:29 -04:00
Github Actions
81bd825369 Updated CHANGELOGS & MD docs 2022-06-15 11:19:29 -04:00
Kyu
adf35091c0 Update Ethereum and Optimism FQT addresses (#504) 2022-06-15 11:19:29 -04:00
eobbad
d8311b1de1 Offboard Jetswap, CafeSwap, JulSwap, and PolyDex (#503)
* Offboard Jetswap

* Offboarded CafeSwap

* Offboarded JulSwap

* Offboarded PolyDex

* Changelog

* Update changelog

* Changelog update
2022-06-15 11:19:29 -04:00
eobbad
c874beab91 KnightSwap and Mdex cosmetic changes (#502)
* Lowercased KnightSwap and MDEX router address

* Changelog.JSON
2022-06-15 11:19:29 -04:00
Jorge Pérez
7b8c1a7e1d Chore: Do not send empty entries on Quote Report (#501)
* Chore: Do not send empty entries on Quote Report

* Changelog
2022-06-15 11:19:29 -04:00
Kyu
1b6b238d79 feat: Add Velodrome support [TKR-432] (#494)
* Implement MixinVelodrome

* Add preliminary implementation of VelodromeSampler

* Add Velodrome in BridgeProtocol of transformer_utils.ts

* Fix MixinVelodrome

* Wire Velodrome sampler in market_operation_utils

* Fix lint error

* Remove gas schedule TODO

* Format VelodromeSampler.sol

* Fix MixinVelodrome

* Update CHANGELOG.json
2022-06-15 11:19:27 -04:00
Kyu
a8264822d2 Fix a lint error in CHANGELOG.json 2022-06-15 11:18:23 -04:00
Kyu
7e0ed41759 Fix a lint error introduced in earlier PRs 2022-06-15 11:18:23 -04:00
eobbad
19e7dd6af1 Add KnightSwap on BSC (#498)
* Curve pool script to generate pools and their info. Still need to integrate into API

* Added MDEX to BSC

* Removed curve automation scripts from this PR

* Fixed typo

* Changelog

* fix formatting

* Fixed yarn lint

* Add KnightSwap

* Changelog

* update changelog

* changelog again...
2022-06-15 11:18:23 -04:00
eobbad
43aeec4711 Add MDEX support (BSC) [TKR-426] (#496)
* Curve pool script to generate pools and their info. Still need to integrate into API

* Added MDEX to BSC

* Removed curve automation scripts from this PR

* Fixed typo

* Changelog

* fix formatting

* Fixed yarn lint
2022-06-15 11:18:23 -04:00
Github Actions
06763ac275 Publish
- @0x/contracts-erc20@3.3.31
 - @0x/contracts-test-utils@5.4.22
 - @0x/contracts-treasury@1.4.14
 - @0x/contracts-utils@4.8.12
 - @0x/contracts-zero-ex@0.34.0
 - @0x/asset-swapper@16.61.0
 - @0x/contract-addresses@6.15.0
 - @0x/contract-wrappers@13.20.3
 - @0x/protocol-utils@11.14.0
2022-06-15 11:18:23 -04:00
Github Actions
359b36a6c7 Updated CHANGELOGS & MD docs 2022-06-15 11:18:23 -04:00
Noah Khamliche
7503ef37ba address comments 2022-06-15 11:18:23 -04:00
Noah Khamliche
a5bee1f363 fix linting 2022-06-15 11:18:23 -04:00
Noah Khamliche
54da1e733c fix linting 2022-06-15 11:18:23 -04:00
Noah Khamliche
ce82d3529c rebase development 2022-06-15 11:18:23 -04:00
Megan
32b0743517 feat/add MeshSwap on Polygon [TKR-374] (#491)
* Added MeshSwap on Polygon

* Updated changelog
2022-06-15 11:18:23 -04:00
Noah Khamliche
9d51c0f7ce Added BancorV3 to fqt, and added support in asset-swapper 2022-06-15 11:18:23 -04:00
Noah Khamliche
830a6474c1 updated contract-addresses with new ethereum fqt 2022-06-15 11:18:23 -04:00
Noah Khamliche
5d8e1da37c add weth/eth wrap/unwrap support for bancorv3 2022-06-15 11:18:23 -04:00
Megan
34acdd64fc feat/add MeshSwap on Polygon [TKR-374] (#491)
* Added MeshSwap on Polygon

* Updated changelog
2022-06-15 11:18:23 -04:00
Noah Khamliche
e90ffcf1d7 fix versioning issue on protocol-utils 2022-06-15 11:18:23 -04:00
Noah Khamliche
6f7ef9c54f final changes 2022-06-15 11:18:23 -04:00
Noah Khamliche
1c51f5962b nitpicks 2022-06-15 11:18:23 -04:00
Noah Khamliche
a942e03e94 added changelog entries 2022-06-15 11:18:23 -04:00
Noah Khamliche
cc387ae176 fixed bancor sell quotes 2022-06-15 11:18:21 -04:00
Noah Khamliche
8bfb58eba9 added weth/eth support to sampler 2022-06-15 11:17:25 -04:00
Noah Khamliche
1f76e3c949 add weth/eth wrap/unwrap support for bancorv3 2022-06-15 11:17:23 -04:00
Noah Khamliche
7af372f56b added bancor mixin/sampler and started linking up with asset-swapper 2022-06-15 11:17:07 -04:00
Megan
2a2bb53d9c feat/add MeshSwap on Polygon [TKR-374] (#491)
* Added MeshSwap on Polygon

* Updated changelog
2022-06-15 11:16:41 -04:00
Kyu
0f2078e70f Delete packages/migrations (#488)
* Delete packages/migrations

* Remove 0x/migrations from asset-swapper dev dependency

* Remove 0x/migrations references
2022-06-15 11:16:41 -04:00
Kyu
d3396fff3c Add stETH wrap/unwrap support [TKR-377] (#476)
* Update MixinLido to support stETH wrapping/unwrapping

* Update LidoSampler and asset-swapper

* Re-use token address constants in LIDO_INFO_BY_CHAIN

* Update CHANGELOG.json

* Add stETH <-> wstETH to TokenAdjacencyGraph

* Change lido gas schedule code style

* Move allowance approval inside the wrap branch

* Refactor LidoSampler to reduce its bytecode size
2022-06-15 11:16:39 -04:00
mzhu25
68bc3979dd Split up BridgeAdapter by chain [TKR-402] (#487)
* Split up BridgeAdapter by chain

* Fix BridgeProtocols enum

* Add isSupportedSource to bridge adapter contracts

* Add bridge adapter tests

* Fix FQT test
2022-06-15 11:16:21 -04:00
Kyu
7b98c436a5 Offboard/clean up Oasis, CoFix, and legacy Kyber [TKR-405] (#482)
* Remove Oasis

* Remove CoFix code

* Remove MixinKyber

* Remove Kyber from asset-swapper

* Delete unused imports, interface, and etc.

* Fix the test failure issue when it's run with neon-router

* Update CHANGELOG.json
2022-06-15 11:16:19 -04:00
Github Actions
9bda78c57b Publish
- @0x/asset-swapper@16.60.1
2022-06-15 11:15:20 -04:00
Github Actions
6c0d1d8a37 Updated CHANGELOGS & MD docs 2022-06-15 11:12:35 -04:00
Jacob Evans
777f83c702 fix: BalancerV2 sor alias (#481)
* Install both Balancer sor and rename early version to v1

* yarn.lock

* CHANGELOG
2022-06-15 11:12:30 -04:00
Github Actions
01f4e0eb48 Publish
- @0x/contracts-erc20@3.3.30
 - @0x/contracts-test-utils@5.4.21
 - @0x/contracts-treasury@1.4.13
 - @0x/contracts-utils@4.8.11
 - @0x/contracts-zero-ex@0.33.0
 - @0x/asset-swapper@16.60.0
 - @0x/contract-addresses@6.14.0
 - @0x/contract-wrappers@13.20.2
 - @0x/migrations@8.1.19
 - @0x/protocol-utils@11.13.0
2022-06-15 11:10:48 -04:00
Github Actions
95454fdaff Updated CHANGELOGS & MD docs 2022-06-15 11:10:48 -04:00
Kyu
a47e7ee105 Increase KyberDMM base gas [TKR-317] (#479)
* Increase KyberDMM base gas

* Update CHANGELOG.json
2022-06-15 11:10:48 -04:00
Kyu
330b8e96e5 Add Yoshi Exchange support (Fantom) [TKR-270] (#473)
* Resolve conflicts

* Update CHANGELOG.json
2022-06-15 11:10:48 -04:00
Noah Khamliche
0a529e7f96 prettier and lint everything 2022-06-15 11:10:48 -04:00
Noah Khamliche
294a4d2d71 removed extraneous comments in sampler 2022-06-15 11:10:48 -04:00
Noah Khamliche
160d6a0ff2 comments and nits 2022-06-15 11:10:48 -04:00
Noah Khamliche
3a005254dd added address ref from AVALANCHE_TOKENS for mim instead of raw address 2022-06-15 11:10:48 -04:00
Noah Khamliche
014acef6f6 final deployments and updates for bridge adapter and fqt on avax/bsc 2022-06-15 11:10:48 -04:00
Noah Khamliche
52ca453a63 added changelog entries 2022-06-15 11:10:48 -04:00
Noah Khamliche
e3d90fb7f1 rebased dev and merged 2022-06-15 11:10:47 -04:00
Ido Kleinman
c04a326c30 Add BiSwap (as UniV2 clone) on BSC (#471)
* Add BiSwap (as UniV2 clone) on BSC

* changelog PR number

* add BSW

* remove BiSwap from transformer_utils

* Do not initialize BalancerV2SwapInfoCache on unsupported chains [TKR-365] (#472)

* Do not initialize BalancerV2SwapInfoCache on unsupported chains
* Update CHANGELOG.json

* Updated CHANGELOGS & MD docs

* Publish

 - @0x/asset-swapper@16.57.3

* chore: Decomission SnowSwap [TKR-356] (#468)

* Decomission SnowSwap

* SnowSwap doesn't have much liquidity anymore (the largest pool has ~$50k)

* Update CHANGELOG.json

* Update CHANGELOG.json

* chore: Offboard Swerve Finance and LinkSwap [TKR-356] (#469)

* Offboard swerve

* Update CHANGELOG.json

* Offboard LinkSwap

* Remove unused import

* Fix CHANGELOG.json

* chore: Offboard Eth2Dai [TKR-356] (#470)

* Offboard Eth2Dai

* Update CHANGELOG.json

* feat: add IRfqClient (#467)

* add message to changelog for #467 (#474)

* Update saddle mainnet pools (#450)

* Add saddle v2 pools

* remove outdated pools

* add two saddle meta pools

* forgot changelog

* remove saddle metapools

* changelog update

* Fix a lint issue (#475)

* Updated CHANGELOGS & MD docs

* Publish

 - @0x/asset-swapper@16.59.0

* Add BiSwap (as UniV2 clone) on BSC

* rebase new changes for balv2, up changelog, quotes working

* remove Biswap from transformer_utils once again

Co-authored-by: Kyu <kyuhyun217@gmail.com>
Co-authored-by: Github Actions <github-actions@github.com>
Co-authored-by: phil-ociraptor <phil@0x.org>
Co-authored-by: Cece Z <me@cecez.xyz>
Co-authored-by: Noah Khamliche <noah@0xproject.com>
2022-06-15 11:09:01 -04:00
Github Actions
19aebbdf02 Publish
- @0x/asset-swapper@16.59.0
2022-06-15 11:08:08 -04:00
Github Actions
679f1fd625 Updated CHANGELOGS & MD docs 2022-06-15 11:08:08 -04:00
Kyu
cb81fa322e Fix a lint issue (#475) 2022-06-15 11:08:08 -04:00
Cece Z
85daeaca54 Update saddle mainnet pools (#450)
* Add saddle v2 pools

* remove outdated pools

* add two saddle meta pools

* forgot changelog

* remove saddle metapools

* changelog update
2022-06-15 11:08:06 -04:00
phil-ociraptor
a7c0c761ce add message to changelog for #467 (#474) 2022-06-15 11:06:35 -04:00
phil-ociraptor
300a64947c feat: add IRfqClient (#467) 2022-06-15 11:06:32 -04:00
Kyu
f395be9269 chore: Offboard Eth2Dai [TKR-356] (#470)
* Offboard Eth2Dai

* Update CHANGELOG.json
2022-06-15 11:05:08 -04:00
Kyu
0558203407 chore: Offboard Swerve Finance and LinkSwap [TKR-356] (#469)
* Offboard swerve

* Update CHANGELOG.json

* Offboard LinkSwap

* Remove unused import

* Fix CHANGELOG.json
2022-06-15 11:04:55 -04:00
Kyu
895754750f chore: Decomission SnowSwap [TKR-356] (#468)
* Decomission SnowSwap

* SnowSwap doesn't have much liquidity anymore (the largest pool has ~$50k)

* Update CHANGELOG.json

* Update CHANGELOG.json
2022-06-15 11:04:23 -04:00
Github Actions
f856f449ad Publish
- @0x/asset-swapper@16.57.3
2022-06-15 11:01:18 -04:00
Github Actions
aac291ddcf Updated CHANGELOGS & MD docs 2022-06-15 11:01:18 -04:00
Kyu
87b97ff4b5 Do not initialize BalancerV2SwapInfoCache on unsupported chains [TKR-365] (#472)
* Do not initialize BalancerV2SwapInfoCache on unsupported chains
* Update CHANGELOG.json
2022-06-15 11:01:16 -04:00
Github Actions
a933ea502f Publish
- @0x/asset-swapper@16.57.2
2022-06-15 11:00:42 -04:00
Github Actions
91238d7bfa Updated CHANGELOGS & MD docs 2022-06-15 11:00:42 -04:00
Jorge Pérez
bc6253059e Fix the filter for considered sources on indicative sells for Quote Report (#466) 2022-06-15 11:00:41 -04:00
Kyu
3ef9d50742 Add cvxfxs-fxs curve pool on Ethereum mainnet (#465)
* Add cvxfxs-fxs curve pool on Ethereum mainnet

* Update CHANGELOG.json

* Fix an existing formatting issue

* Adjust gasSchedule and merge the change under 16.57.1
2022-06-15 11:00:21 -04:00
eobbad
498698471f chore/ANY-QUICK on polygon MAG-MIM on avax (#464)
* Added ANY/QUICK pair on Polygon

* Updated changelog.json

* Update CHANGELOG.json
2022-06-15 10:58:29 -04:00
Github Actions
7223ea0c0a Publish
- @0x/contracts-erc20@3.3.29
 - @0x/contracts-test-utils@5.4.20
 - @0x/contracts-treasury@1.4.12
 - @0x/contracts-utils@4.8.10
 - @0x/contracts-zero-ex@0.32.0
 - @0x/asset-swapper@16.57.0
 - @0x/contract-addresses@6.13.0
 - @0x/contract-wrappers@13.20.1
 - @0x/migrations@8.1.18
 - @0x/protocol-utils@11.12.0
2022-06-15 10:57:36 -04:00
Github Actions
d0bc0d7936 Updated CHANGELOGS & MD docs 2022-06-15 10:57:36 -04:00
Lawrence Forman
2bbdf29df8 AS: Balancer V2 batchSwap (#462)
* Draft. PoC pseudo code showing general idea for resuing SOR path creation logic and adding multihop support.

* Add actual Balancer SDK function calls.

* Update to handle buys.

* Correct taker>maker for buy.

* Draft. PoC pseudo code showing general idea for resuing SOR path creation logic and adding multihop support.

* make it build

* rebase

* add BalancerV2Batch protocol

* add BalancerV2Batch protocol

* get balancer v2 multihop working

* fix BalancerV2Batch for sells (buys still iffy)

* fix buys, appease linter and prettier

* remove unused RPC URL from balancer sdk construction

* update changelogs

* clean up comments
add event loop yield in `BalancerV2SwapInfoCache.loadTopPools()`

* add negative result check on balancerv2batch swap output

* compiler hack

* reintroduce CompilerHack

* delete unused multibridge sampler

* remove compilerhack

* reintroduce compilerhack

* try to fix CI compile errors

* plz work

* plz work

* pretty plz work

* yay it works, also address feedback

* appease linter

* deploy new FQTs

Co-authored-by: johngrantuk <johngrantuk@googlemail.com>
Co-authored-by: Lawrence Forman <me@merklejerk.com>
2022-06-15 10:57:33 -04:00
Github Actions
353dffa6c3 Publish
- @0x/asset-swapper@16.56.0
2022-06-15 10:56:16 -04:00
Github Actions
1cdc5e0679 Updated CHANGELOGS & MD docs 2022-06-15 10:56:16 -04:00
mzhu25
26edf14859 Add estimatedGas to ExtendedQuoteReport (#463) 2022-06-15 10:56:16 -04:00
Github Actions
8857ef6b4c Publish
- @0x/asset-swapper@16.55.0
2022-06-15 10:56:16 -04:00
Github Actions
d6fbb43c10 Updated CHANGELOGS & MD docs 2022-06-15 10:56:16 -04:00
Lawrence Forman
4929c60565 fix quote consumer RFQ VIP code path not checking if transfromERC20 is required (#461)
Co-authored-by: Lawrence Forman <me@merklejerk.com>
2022-06-15 10:56:16 -04:00
Github Actions
aca9338acb Publish
- @0x/asset-swapper@16.54.0
2022-06-15 10:56:16 -04:00
Github Actions
d775e780ad Updated CHANGELOGS & MD docs 2022-06-15 10:56:16 -04:00
Lawrence Forman
b197bf734d add real VIP support for eligible RFQT swaps (#458)
Co-authored-by: Lawrence Forman <me@merklejerk.com>
2022-06-15 10:56:13 -04:00
Github Actions
95aa9d0150 Publish
- @0x/contracts-erc20@3.3.28
 - @0x/contracts-test-utils@5.4.19
 - @0x/contracts-treasury@1.4.11
 - @0x/contracts-utils@4.8.9
 - @0x/contracts-zero-ex@0.31.2
 - @0x/asset-swapper@16.53.0
 - @0x/contract-addresses@6.12.1
 - @0x/contract-artifacts@3.18.0
 - @0x/contract-wrappers@13.20.0
 - @0x/migrations@8.1.17
 - @0x/protocol-utils@1.11.2
2022-06-15 10:55:42 -04:00
Github Actions
edb3d11e59 Updated CHANGELOGS & MD docs 2022-06-15 10:55:42 -04:00
Kim Persson
9f047f9fd5 fix: use Node 16 for publish GH action (#457) 2022-06-15 10:55:42 -04:00
Kim Persson
dea5cb8ac9 feat: add block number to quote report data [TKR-314] (#448)
* feat: add blockNumber to MarketSideLiquidity response

* fix: return block number back in swap quote response

* chore: add asset-swapper changelog entry
2022-06-15 10:55:40 -04:00
Kim Persson
300ff1d7e8 feat: use neon-router in CI tests (#453)
* fix: initially skip all tests that don't work with the Rust router

* fix: enable rust router for CircleCI tests

* fix: handle invalid output sampels & enable numSamples tests

* chore: add comments about disabled tests

* chore: add asset-swapper changelog entry
2022-06-15 10:55:17 -04:00
Kim Persson
ccd7aa0c5e chore: bump ts version to solve type issue with ethereumjs (#455) 2022-06-15 10:55:17 -04:00
Noah Khamliche
f2140a153e fixed gas estimation and removed hint from intermediate tokens 2022-06-15 10:55:17 -04:00
Noah Khamliche
dd02415f8e updated routing 2022-06-15 10:55:15 -04:00
Noah Khamliche
692eee0cf2 updating changelog 2022-06-15 10:55:04 -04:00
Noah Khamliche
1d96d7fd8e fixing routing 2022-06-15 10:55:04 -04:00
Noah Khamliche
706ef6d2ec Added Stargate curve pool 2022-06-15 10:55:01 -04:00
Lawrence Forman
504924a685 remove debug logs 2022-04-23 03:15:30 -04:00
Lawrence Forman
a7801c7e77 remove debug output 2022-04-22 17:21:15 -04:00
Lawrence Forman
8389ef31d8 use compatible quotes across different hop legs 2022-03-29 11:36:32 -04:00
Lawrence Forman
7967ccfb9d rebase 2022-03-16 15:54:48 -04:00
Lawrence Forman
da279052b1 remove debug log 2022-03-16 12:16:07 -04:00
Lawrence Forman
35c0cafd6b fix gas/overhead evaluation 2022-03-16 12:16:07 -04:00
Lawrence Forman
bd0d672012 properly handle multihop overhead (I hope) 2022-03-16 12:16:07 -04:00
Lawrence Forman
27ae6aabd1 do not demand multihop prices from non-fee soures 2022-03-16 12:16:07 -04:00
Lawrence Forman
f46b878637 rebase 2022-03-16 12:16:07 -04:00
Lawrence Forman
6334f5bd84 fixed multihop buy through multiplex 2022-03-16 12:16:07 -04:00
Lawrence Forman
d1a93737ce it builds 2022-03-16 12:16:07 -04:00
Lawrence Forman
29c77059a0 continue rebase 2022-03-16 12:16:07 -04:00
Lawrence Forman
7d5e4ed685 rebasing against development... 2022-03-16 12:16:07 -04:00
Lawrence Forman
6ac7dd006c @0x/asset-swapper: hack together basic sampler service integration
`@0x/asset-swapper`: use gasCost from sampler service

cleanup

`@0x/asset-swapper`: Handle per-fill gas cost correctly in more places

getting multihop back up + refactors for treating all quotes as n-hop

multihop with nice breakdowns

get vips working

get multiplex working

get rfq working

remove unused functions

fix multihop buys

plz work multihop buys

multihop buys seem ok now.
fetch less samples for multihop legs

get quote report and price comparisons working

clean up
2022-03-16 12:16:07 -04:00
206 changed files with 8473 additions and 14324 deletions

View File

@@ -19,7 +19,6 @@ jobs:
command: yarn --frozen-lockfile --ignore-engines install || yarn --frozen-lockfile --ignore-engines install
- setup_remote_docker
- run: yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci
- run: yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts
- save_cache:
key: repo-{{ .Environment.CIRCLE_SHA1 }}
paths:
@@ -110,6 +109,8 @@ jobs:
docker:
- image: node:16
working_directory: ~/repo
environment:
RUST_ROUTER: 'true'
steps:
- restore_cache:
keys:
@@ -117,7 +118,6 @@ jobs:
- run: yarn wsrun -p @0x/contracts-test-utils -m --serial -c test:circleci
- run: yarn wsrun -p @0x/contract-artifacts -m --serial -c test:circleci
- run: yarn wsrun -p @0x/contract-wrappers-test -m --serial -c test:circleci
- run: yarn wsrun -p @0x/migrations -m --serial -c test:circleci
- run: yarn wsrun -p @0x/order-utils -m --serial -c test:circleci
- run: yarn wsrun -p @0x/asset-swapper -m --serial -c test:circleci
- save_cache:

View File

@@ -1,7 +1,6 @@
python: ['python-packages']
contracts: ['contracts']
@0x/contract-addresses: ['packages/contract-addresses']
@0x/migrations: ['packages/migrations']
@0x/order-utils: ['packages/order-utils']
@0x/contract-artifacts: ['packages/contract-artifacts']
@0x/contract-wrappers: ['packages/contract-wrappers']

View File

@@ -28,7 +28,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-node@v1
with:
node-version: 10
node-version: 16
- uses: actions/setup-python@v2
- name: 'configure git'
run: |

View File

@@ -38,7 +38,6 @@ These packages are all under development. See [/contracts/README.md](/contracts/
| [`@0x/protocol-utils`](/packages/protocol-utils) | [![npm](https://img.shields.io/npm/v/@0x/protocol-utils.svg)](https://www.npmjs.com/package/@0x/protocol-utils) | A set of utilities for generating, parsing, signing and validating 0x orders |
| [`@0x/contract-addresses`](/packages/contract-addresses) | [![npm](https://img.shields.io/npm/v/@0x/contract-addresses.svg)](https://www.npmjs.com/package/@0x/contract-addresses) | A tiny utility library for getting known deployed contract addresses for a particular network. |
| [`@0x/contract-wrappers`](/packages/contract-wrappers) | [![npm](https://img.shields.io/npm/v/@0x/contract-wrappers.svg)](https://www.npmjs.com/package/@0x/contract-wrappers) | JS/TS wrappers for interacting with the 0x smart contracts |
| [`@0x/migrations`](/packages/migrations) | [![npm](https://img.shields.io/npm/v/@0x/migrations.svg)](https://www.npmjs.com/package/@0x/migrations) | Migration tool for deploying 0x smart contracts on private testnets |
| [`@0x/contract-artifacts`](/packages/contract-artifacts) | [![npm](https://img.shields.io/npm/v/@0x/contract-artifacts.svg)](https://www.npmjs.com/package/@0x/contract-artifacts) | 0x smart contract compilation artifacts | |
## Usage

View File

@@ -1,4 +1,49 @@
[
{
"timestamp": 1655244958,
"version": "3.3.32",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1654284040,
"version": "3.3.31",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1652919697,
"version": "3.3.30",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1650611093,
"version": "3.3.29",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1648739346,
"version": "3.3.28",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1646225739,
"version": "3.3.27",

View File

@@ -5,6 +5,26 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.3.32 - _June 14, 2022_
* Dependencies updated
## v3.3.31 - _June 3, 2022_
* Dependencies updated
## v3.3.30 - _May 19, 2022_
* Dependencies updated
## v3.3.29 - _April 22, 2022_
* Dependencies updated
## v3.3.28 - _March 31, 2022_
* Dependencies updated
## v3.3.27 - _March 2, 2022_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc20",
"version": "3.3.27",
"version": "3.3.32",
"engines": {
"node": ">=6.12"
},
@@ -53,8 +53,8 @@
"devDependencies": {
"@0x/abi-gen": "^5.8.0",
"@0x/contracts-gen": "^2.0.46",
"@0x/contracts-test-utils": "^5.4.18",
"@0x/contracts-utils": "^4.8.8",
"@0x/contracts-test-utils": "^5.4.23",
"@0x/contracts-utils": "^4.8.13",
"@0x/dev-utils": "^4.2.14",
"@0x/sol-compiler": "^4.8.1",
"@0x/ts-doc-gen": "^0.0.28",
@@ -79,7 +79,7 @@
"solhint": "^1.4.1",
"tslint": "5.11.0",
"typedoc": "~0.16.11",
"typescript": "4.2.2"
"typescript": "4.6.3"
},
"dependencies": {
"@0x/base-contract": "^6.5.0",

View File

@@ -1,4 +1,49 @@
[
{
"timestamp": 1655244958,
"version": "5.4.23",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1654284040,
"version": "5.4.22",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1652919697,
"version": "5.4.21",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1650611093,
"version": "5.4.20",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1648739346,
"version": "5.4.19",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1646225739,
"version": "5.4.18",

View File

@@ -5,6 +5,26 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v5.4.23 - _June 14, 2022_
* Dependencies updated
## v5.4.22 - _June 3, 2022_
* Dependencies updated
## v5.4.21 - _May 19, 2022_
* Dependencies updated
## v5.4.20 - _April 22, 2022_
* Dependencies updated
## v5.4.19 - _March 31, 2022_
* Dependencies updated
## v5.4.18 - _March 2, 2022_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-test-utils",
"version": "5.4.18",
"version": "5.4.23",
"engines": {
"node": ">=6.12"
},
@@ -39,12 +39,12 @@
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.11.0",
"typescript": "4.2.2"
"typescript": "4.6.3"
},
"dependencies": {
"@0x/assert": "^3.0.34",
"@0x/base-contract": "^6.5.0",
"@0x/contract-addresses": "^6.12.0",
"@0x/contract-addresses": "^6.16.0",
"@0x/dev-utils": "^4.2.14",
"@0x/json-schemas": "^6.4.4",
"@0x/order-utils": "^10.4.28",

View File

@@ -1,4 +1,49 @@
[
{
"timestamp": 1655244958,
"version": "1.4.15",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1654284040,
"version": "1.4.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1652919697,
"version": "1.4.13",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1650611093,
"version": "1.4.12",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1648739346,
"version": "1.4.11",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1646225739,
"version": "1.4.10",

View File

@@ -5,6 +5,26 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.4.15 - _June 14, 2022_
* Dependencies updated
## v1.4.14 - _June 3, 2022_
* Dependencies updated
## v1.4.13 - _May 19, 2022_
* Dependencies updated
## v1.4.12 - _April 22, 2022_
* Dependencies updated
## v1.4.11 - _March 31, 2022_
* Dependencies updated
## v1.4.10 - _March 2, 2022_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-treasury",
"version": "1.4.10",
"version": "1.4.15",
"engines": {
"node": ">=6.12"
},
@@ -47,12 +47,12 @@
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury",
"devDependencies": {
"@0x/abi-gen": "^5.8.0",
"@0x/contract-addresses": "^6.12.0",
"@0x/contract-addresses": "^6.16.0",
"@0x/contracts-asset-proxy": "^3.7.19",
"@0x/contracts-erc20": "^3.3.27",
"@0x/contracts-erc20": "^3.3.32",
"@0x/contracts-gen": "^2.0.46",
"@0x/contracts-staking": "^2.0.45",
"@0x/contracts-test-utils": "^5.4.18",
"@0x/contracts-test-utils": "^5.4.23",
"@0x/sol-compiler": "^4.8.1",
"@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.4",
@@ -69,11 +69,11 @@
"solhint": "^1.4.1",
"tslint": "5.11.0",
"typedoc": "~0.16.11",
"typescript": "4.2.2"
"typescript": "4.6.3"
},
"dependencies": {
"@0x/base-contract": "^6.5.0",
"@0x/protocol-utils": "^1.11.1",
"@0x/protocol-utils": "^11.15.0",
"@0x/subproviders": "^6.6.5",
"@0x/types": "^3.3.6",
"@0x/typescript-typings": "^5.3.1",

View File

@@ -1,4 +1,49 @@
[
{
"timestamp": 1655244958,
"version": "4.8.13",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1654284040,
"version": "4.8.12",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1652919697,
"version": "4.8.11",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1650611093,
"version": "4.8.10",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1648739346,
"version": "4.8.9",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1646225739,
"version": "4.8.8",

View File

@@ -5,6 +5,26 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.8.13 - _June 14, 2022_
* Dependencies updated
## v4.8.12 - _June 3, 2022_
* Dependencies updated
## v4.8.11 - _May 19, 2022_
* Dependencies updated
## v4.8.10 - _April 22, 2022_
* Dependencies updated
## v4.8.9 - _March 31, 2022_
* Dependencies updated
## v4.8.8 - _March 2, 2022_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-utils",
"version": "4.8.8",
"version": "4.8.13",
"engines": {
"node": ">=6.12"
},
@@ -52,7 +52,7 @@
"devDependencies": {
"@0x/abi-gen": "^5.8.0",
"@0x/contracts-gen": "^2.0.46",
"@0x/contracts-test-utils": "^5.4.18",
"@0x/contracts-test-utils": "^5.4.23",
"@0x/dev-utils": "^4.2.14",
"@0x/order-utils": "^10.4.28",
"@0x/sol-compiler": "^4.8.1",
@@ -76,7 +76,7 @@
"solhint": "^1.4.1",
"truffle": "^5.0.32",
"tslint": "5.11.0",
"typescript": "4.2.2"
"typescript": "4.6.3"
},
"dependencies": {
"@0x/base-contract": "^6.5.0",

View File

@@ -1,4 +1,61 @@
[
{
"version": "0.35.0",
"changes": [
{
"note": "Adds support for Velodrome OptimismBridgeAdapter",
"pr": 494
}
],
"timestamp": 1655244958
},
{
"version": "0.34.0",
"changes": [
{
"note": "Splits BridgeAdapter up by chain",
"pr": 487
},
{
"note": "Add stETH wrap/unwrap support",
"pr": 476
},
{
"note": "Adds support for BancorV3 to EthereumBridgeAdapter",
"pr": 492
}
],
"timestamp": 1654284040
},
{
"version": "0.33.0",
"changes": [
{
"note": "Add support for GMX and Platypus to bridge adapter",
"pr": 478
}
],
"timestamp": 1652919697
},
{
"version": "0.32.0",
"changes": [
{
"note": "Add support for `BalancerV2Batch` fills in FQT",
"pr": 462
}
],
"timestamp": 1650611093
},
{
"timestamp": 1648739346,
"version": "0.31.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1646225739,
"version": "0.31.1",

View File

@@ -5,6 +5,28 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.35.0 - _June 14, 2022_
* Adds support for Velodrome OptimismBridgeAdapter (#494)
## v0.34.0 - _June 3, 2022_
* Splits BridgeAdapter up by chain (#487)
* Add stETH wrap/unwrap support (#476)
* Adds support for BancorV3 to EthereumBridgeAdapter (#492)
## v0.33.0 - _May 19, 2022_
* Add support for GMX and Platypus to bridge adapter (#478)
## v0.32.0 - _April 22, 2022_
* Add support for `BalancerV2Batch` fills in FQT (#462)
## v0.31.2 - _March 31, 2022_
* Dependencies updated
## v0.31.1 - _March 2, 2022_
* Dependencies updated

View File

@@ -0,0 +1,88 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./IBridgeAdapter.sol";
abstract contract AbstractBridgeAdapter is IBridgeAdapter {
constructor(
uint256 expectedChainId,
string memory expectedChainName
)
public
{
uint256 chainId;
assembly { chainId := chainid() }
// Allow testing on Ganache
if (chainId != expectedChainId && chainId != 1337) {
revert(string(abi.encodePacked(expectedChainName, "BridgeAdapter.constructor: wrong chain ID")));
}
}
function isSupportedSource(bytes32 source)
external
override
returns (bool isSupported)
{
BridgeOrder memory placeholderOrder;
placeholderOrder.source = source;
IERC20TokenV06 placeholderToken = IERC20TokenV06(address(0));
(, isSupported) = _trade(
placeholderOrder,
placeholderToken,
placeholderToken,
0,
true
);
}
function trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount
)
public
override
returns (uint256 boughtAmount)
{
(boughtAmount, ) = _trade(
order,
sellToken,
buyToken,
sellAmount,
false
);
}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bool dryRun
)
internal
virtual
returns (uint256 boughtAmount, bool supportedSource);
}

View File

@@ -0,0 +1,141 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinCurve.sol";
import "./mixins/MixinCurveV2.sol";
import "./mixins/MixinGMX.sol";
import "./mixins/MixinKyberDmm.sol";
import "./mixins/MixinAaveV2.sol";
import "./mixins/MixinNerve.sol";
import "./mixins/MixinPlatypus.sol";
import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinZeroExBridge.sol";
contract AvalancheBridgeAdapter is
AbstractBridgeAdapter(43114, "Avalanche"),
MixinCurve,
MixinCurveV2,
MixinGMX,
MixinKyberDmm,
MixinAaveV2,
MixinNerve,
MixinPlatypus,
MixinUniswapV2,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth)
public
MixinCurve(weth)
{}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bool dryRun
)
internal
override
returns (uint256 boughtAmount, bool supportedSource)
{
uint128 protocolId = uint128(uint256(order.source) >> 128);
if (protocolId == BridgeProtocols.CURVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurve(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.CURVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurveV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV2(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.NERVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeNerve(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.KYBERDMM) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeKyberDmm(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.AAVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeAaveV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.GMX) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeGMX(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.PLATYPUS) {
if (dryRun) { return (0, true); }
boughtAmount = _tradePlatypus(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
}
emit BridgeFill(
order.source,
sellToken,
buyToken,
sellAmount,
boughtAmount
);
}
}

View File

@@ -0,0 +1,132 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinCurve.sol";
import "./mixins/MixinDodo.sol";
import "./mixins/MixinDodoV2.sol";
import "./mixins/MixinKyberDmm.sol";
import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinZeroExBridge.sol";
contract BSCBridgeAdapter is
AbstractBridgeAdapter(56, "BSC"),
MixinCurve,
MixinDodo,
MixinDodoV2,
MixinKyberDmm,
MixinMooniswap,
MixinNerve,
MixinUniswapV2,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth)
public
MixinCurve(weth)
MixinMooniswap(weth)
{}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bool dryRun
)
internal
override
returns (uint256 boughtAmount, bool supportedSource)
{
uint128 protocolId = uint128(uint256(order.source) >> 128);
if (protocolId == BridgeProtocols.CURVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurve(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV2(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.MOONISWAP) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeMooniswap(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.DODO) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeDodo(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.DODOV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeDodoV2(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.NERVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeNerve(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.KYBERDMM) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeKyberDmm(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
}
emit BridgeFill(
order.source,
sellToken,
buyToken,
sellAmount,
boughtAmount
);
}
}

View File

@@ -27,29 +27,34 @@ library BridgeProtocols {
// A incrementally increasing, append-only list of protocol IDs.
// We don't use an enum so solidity doesn't throw when we pass in a
// new protocol ID that hasn't been rolled up yet.
uint128 internal constant UNKNOWN = 0;
uint128 internal constant CURVE = 1;
uint128 internal constant UNISWAPV2 = 2;
uint128 internal constant UNISWAP = 3;
uint128 internal constant BALANCER = 4;
uint128 internal constant KYBER = 5;
uint128 internal constant MOONISWAP = 6;
uint128 internal constant MSTABLE = 7;
uint128 internal constant OASIS = 8;
uint128 internal constant SHELL = 9;
uint128 internal constant DODO = 10;
uint128 internal constant DODOV2 = 11;
uint128 internal constant CRYPTOCOM = 12;
uint128 internal constant BANCOR = 13;
uint128 internal constant COFIX = 14;
uint128 internal constant NERVE = 15;
uint128 internal constant MAKERPSM = 16;
uint128 internal constant BALANCERV2 = 17;
uint128 internal constant UNISWAPV3 = 18;
uint128 internal constant KYBERDMM = 19;
uint128 internal constant CURVEV2 = 20;
uint128 internal constant LIDO = 21;
uint128 internal constant CLIPPER = 22; // Not used: Clipper is now using PLP interface
uint128 internal constant AAVEV2 = 23;
uint128 internal constant COMPOUND = 24;
uint128 internal constant UNKNOWN = 0;
uint128 internal constant CURVE = 1;
uint128 internal constant UNISWAPV2 = 2;
uint128 internal constant UNISWAP = 3;
uint128 internal constant BALANCER = 4;
uint128 internal constant KYBER = 5; // Not used: deprecated.
uint128 internal constant MOONISWAP = 6;
uint128 internal constant MSTABLE = 7;
uint128 internal constant OASIS = 8; // Not used: deprecated.
uint128 internal constant SHELL = 9;
uint128 internal constant DODO = 10;
uint128 internal constant DODOV2 = 11;
uint128 internal constant CRYPTOCOM = 12;
uint128 internal constant BANCOR = 13;
uint128 internal constant COFIX = 14; // Not used: deprecated.
uint128 internal constant NERVE = 15;
uint128 internal constant MAKERPSM = 16;
uint128 internal constant BALANCERV2 = 17;
uint128 internal constant UNISWAPV3 = 18;
uint128 internal constant KYBERDMM = 19;
uint128 internal constant CURVEV2 = 20;
uint128 internal constant LIDO = 21;
uint128 internal constant CLIPPER = 22; // Not used: Clipper is now using PLP interface
uint128 internal constant AAVEV2 = 23;
uint128 internal constant COMPOUND = 24;
uint128 internal constant BALANCERV2BATCH = 25;
uint128 internal constant GMX = 26;
uint128 internal constant PLATYPUS = 27;
uint128 internal constant BANCORV3 = 28;
uint128 internal constant VELODROME = 29;
}

View File

@@ -0,0 +1,84 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinZeroExBridge.sol";
contract CeloBridgeAdapter is
AbstractBridgeAdapter(42220, "Celo"),
MixinNerve,
MixinUniswapV2,
MixinZeroExBridge
{
constructor(address _weth)
public
{}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bool dryRun
)
internal
override
returns (uint256 boughtAmount, bool supportedSource)
{
uint128 protocolId = uint128(uint256(order.source) >> 128);
if (protocolId == BridgeProtocols.UNISWAPV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV2(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.NERVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeNerve(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
}
emit BridgeFill(
order.source,
sellToken,
buyToken,
sellAmount,
boughtAmount
);
}
}

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
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.
@@ -20,54 +20,52 @@
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./IBridgeAdapter.sol";
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinAaveV2.sol";
import "./mixins/MixinBalancer.sol";
import "./mixins/MixinBalancerV2.sol";
import "./mixins/MixinBalancerV2Batch.sol";
import "./mixins/MixinBancor.sol";
import "./mixins/MixinCoFiX.sol";
import "./mixins/MixinBancorV3.sol";
import "./mixins/MixinCompound.sol";
import "./mixins/MixinCurve.sol";
import "./mixins/MixinCurveV2.sol";
import "./mixins/MixinCryptoCom.sol";
import "./mixins/MixinDodo.sol";
import "./mixins/MixinDodoV2.sol";
import "./mixins/MixinKyber.sol";
import "./mixins/MixinKyberDmm.sol";
import "./mixins/MixinLido.sol";
import "./mixins/MixinMakerPSM.sol";
import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinMStable.sol";
import "./mixins/MixinNerve.sol";
import "./mixins/MixinOasis.sol";
import "./mixins/MixinShell.sol";
import "./mixins/MixinUniswap.sol";
import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinUniswapV3.sol";
import "./mixins/MixinZeroExBridge.sol";
contract BridgeAdapter is
IBridgeAdapter,
contract EthereumBridgeAdapter is
AbstractBridgeAdapter(1, "Ethereum"),
MixinAaveV2,
MixinBalancer,
MixinBalancerV2,
MixinBalancerV2Batch,
MixinBancor,
MixinCoFiX,
MixinBancorV3,
MixinCompound,
MixinCurve,
MixinCurveV2,
MixinCryptoCom,
MixinDodo,
MixinDodoV2,
MixinKyber,
MixinKyberDmm,
MixinLido,
MixinMakerPSM,
MixinMooniswap,
MixinMStable,
MixinNerve,
MixinOasis,
MixinShell,
MixinUniswap,
MixinUniswapV2,
@@ -76,43 +74,29 @@ contract BridgeAdapter is
{
constructor(IEtherTokenV06 weth)
public
MixinAaveV2()
MixinBalancer()
MixinBalancerV2()
MixinBancor(weth)
MixinCoFiX()
MixinBancorV3(weth)
MixinCompound(weth)
MixinCurve(weth)
MixinCurveV2()
MixinCryptoCom()
MixinDodo()
MixinDodoV2()
MixinKyber(weth)
MixinLido(weth)
MixinMakerPSM()
MixinMooniswap(weth)
MixinMStable()
MixinNerve()
MixinOasis()
MixinShell()
MixinUniswap(weth)
MixinUniswapV2()
MixinUniswapV3()
MixinZeroExBridge()
{}
function trade(
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount
uint256 sellAmount,
bool dryRun
)
public
internal
override
returns (uint256 boughtAmount)
returns (uint256 boughtAmount, bool supportedSource)
{
uint128 protocolId = uint128(uint256(order.source) >> 128);
if (protocolId == BridgeProtocols.CURVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurve(
sellToken,
buyToken,
@@ -120,6 +104,7 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.CURVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurveV2(
sellToken,
buyToken,
@@ -127,18 +112,21 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAPV3) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV3(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV2(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAP) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswap(
sellToken,
buyToken,
@@ -146,6 +134,7 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.BALANCER) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeBalancer(
sellToken,
buyToken,
@@ -153,20 +142,21 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.BALANCERV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeBalancerV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.KYBER) {
boughtAmount = _tradeKyber(
sellToken,
buyToken,
} else if (protocolId == BridgeProtocols.BALANCERV2BATCH) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeBalancerV2Batch(
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.MAKERPSM) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeMakerPsm(
sellToken,
buyToken,
@@ -174,6 +164,7 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.MOONISWAP) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeMooniswap(
sellToken,
buyToken,
@@ -181,20 +172,15 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.MSTABLE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeMStable(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.OASIS) {
boughtAmount = _tradeOasis(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.SHELL) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeShell(
sellToken,
buyToken,
@@ -202,49 +188,49 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.DODO) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeDodo(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.DODOV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeDodoV2(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.CRYPTOCOM) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCryptoCom(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.BANCOR) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeBancor(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.COFIX) {
boughtAmount = _tradeCoFiX(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.NERVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeNerve(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.KYBERDMM) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeKyberDmm(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.LIDO) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeLido(
sellToken,
buyToken,
@@ -252,6 +238,7 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.AAVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeAaveV2(
sellToken,
buyToken,
@@ -259,13 +246,22 @@ contract BridgeAdapter is
order.bridgeData
);
} else if (protocolId == BridgeProtocols.COMPOUND) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCompound(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else {
} else if (protocolId == BridgeProtocols.BANCORV3) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeBancorV3(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge(
sellToken,
buyToken,

View File

@@ -0,0 +1,124 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinAaveV2.sol";
import "./mixins/MixinBalancerV2.sol";
import "./mixins/MixinCurve.sol";
import "./mixins/MixinCurveV2.sol";
import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinZeroExBridge.sol";
contract FantomBridgeAdapter is
AbstractBridgeAdapter(250, "Fantom"),
MixinAaveV2,
MixinBalancerV2,
MixinCurve,
MixinCurveV2,
MixinNerve,
MixinUniswapV2,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth)
public
MixinCurve(weth)
{}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bool dryRun
)
internal
override
returns (uint256 boughtAmount, bool supportedSource)
{
uint128 protocolId = uint128(uint256(order.source) >> 128);
if (protocolId == BridgeProtocols.CURVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurve(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.CURVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurveV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV2(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.BALANCERV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeBalancerV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.NERVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeNerve(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.AAVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeAaveV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
}
emit BridgeFill(
order.source,
sellToken,
buyToken,
sellAmount,
boughtAmount
);
}
}

View File

@@ -50,6 +50,10 @@ interface IBridgeAdapter {
uint256 outputTokenAmount
);
function isSupportedSource(bytes32 source)
external
returns (bool isSupported);
function trade(
BridgeOrder calldata order,
IERC20TokenV06 sellToken,

View File

@@ -0,0 +1,114 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinCurve.sol";
import "./mixins/MixinCurveV2.sol";
import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV3.sol";
import "./mixins/MixinVelodrome.sol";
import "./mixins/MixinZeroExBridge.sol";
contract OptimismBridgeAdapter is
AbstractBridgeAdapter(10, "Optimism"),
MixinCurve,
MixinCurveV2,
MixinNerve,
MixinUniswapV3,
MixinVelodrome,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth)
public
MixinCurve(weth)
{}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bool dryRun
)
internal
override
returns (uint256 boughtAmount, bool supportedSource)
{
uint128 protocolId = uint128(uint256(order.source) >> 128);
if (protocolId == BridgeProtocols.CURVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurve(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.CURVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurveV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAPV3) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV3(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.NERVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeNerve(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.VELODROME) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeVelodrome(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
}
emit BridgeFill(
order.source,
sellToken,
buyToken,
sellAmount,
boughtAmount
);
}
}

View File

@@ -0,0 +1,178 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinAaveV2.sol";
import "./mixins/MixinBalancerV2.sol";
import "./mixins/MixinBalancerV2Batch.sol";
import "./mixins/MixinCurve.sol";
import "./mixins/MixinCurveV2.sol";
import "./mixins/MixinDodo.sol";
import "./mixins/MixinDodoV2.sol";
import "./mixins/MixinKyberDmm.sol";
import "./mixins/MixinMStable.sol";
import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinUniswapV3.sol";
import "./mixins/MixinZeroExBridge.sol";
contract PolygonBridgeAdapter is
AbstractBridgeAdapter(137, "Polygon"),
MixinAaveV2,
MixinBalancerV2,
MixinBalancerV2Batch,
MixinCurve,
MixinCurveV2,
MixinDodo,
MixinDodoV2,
MixinKyberDmm,
MixinMStable,
MixinNerve,
MixinUniswapV2,
MixinUniswapV3,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth)
public
MixinCurve(weth)
{}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bool dryRun
)
internal
override
returns (uint256 boughtAmount, bool supportedSource)
{
uint128 protocolId = uint128(uint256(order.source) >> 128);
if (protocolId == BridgeProtocols.CURVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurve(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.CURVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeCurveV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAPV3) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV3(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeUniswapV2(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.BALANCERV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeBalancerV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.BALANCERV2BATCH) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeBalancerV2Batch(
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.MSTABLE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeMStable(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.DODO) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeDodo(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.DODOV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeDodoV2(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.NERVE) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeNerve(
sellToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.KYBERDMM) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeKyberDmm(
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.AAVEV2) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeAaveV2(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
}
emit BridgeFill(
order.source,
sellToken,
buyToken,
sellAmount,
boughtAmount
);
}
}

View File

@@ -0,0 +1,107 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
interface IBalancerV2BatchSwapVault {
enum SwapKind { GIVEN_IN, GIVEN_OUT }
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
function batchSwap(
SwapKind kind,
BatchSwapStep[] calldata swaps,
IERC20TokenV06[] calldata assets,
FundManagement calldata funds,
int256[] calldata limits,
uint256 deadline
) external returns (int256[] memory amounts);
}
contract MixinBalancerV2Batch {
using LibERC20TokenV06 for IERC20TokenV06;
struct BalancerV2BatchBridgeData {
IBalancerV2BatchSwapVault vault;
IBalancerV2BatchSwapVault.BatchSwapStep[] swapSteps;
IERC20TokenV06[] assets;
}
function _tradeBalancerV2Batch(
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
// Decode the bridge data.
(
IBalancerV2BatchSwapVault vault,
IBalancerV2BatchSwapVault.BatchSwapStep[] memory swapSteps,
address[] memory assets_
) = abi.decode(bridgeData, (IBalancerV2BatchSwapVault, IBalancerV2BatchSwapVault.BatchSwapStep[], address[]));
IERC20TokenV06[] memory assets;
assembly { assets := assets_ }
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
assets[0].approveIfBelow(address(vault), sellAmount);
swapSteps[0].amount = sellAmount;
int256[] memory limits = new int256[](assets.length);
for (uint256 i = 0; i < limits.length; ++i) {
limits[i] = type(int256).max;
}
int256[] memory amounts = vault.batchSwap(
IBalancerV2BatchSwapVault.SwapKind.GIVEN_IN,
swapSteps,
assets,
IBalancerV2BatchSwapVault.FundManagement({
sender: address(this),
fromInternalBalance: false,
recipient: payable(address(this)),
toInternalBalance: false
}),
limits,
block.timestamp + 1
);
require(amounts[amounts.length - 1] <= 0, 'Unexpected BalancerV2Batch output');
return uint256(amounts[amounts.length - 1] * -1);
}
}

View File

@@ -0,0 +1,128 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
/*
BancorV3
*/
interface IBancorV3 {
/**
* @dev performs a trade by providing the source amount and returns the target amount and the associated fee
*
* requirements:
*
* - the caller must be the network contract
*/
function tradeBySourceAmount(
address sourceToken,
address targetToken,
uint256 sourceAmount,
uint256 minReturnAmount,
uint256 deadline,
address beneficiary
) external payable returns (uint256 amount);
}
contract MixinBancorV3 {
using LibERC20TokenV06 for IERC20TokenV06;
IERC20TokenV06 constant public BANCORV3_ETH_ADDRESS =
IERC20TokenV06(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
IEtherTokenV06 private immutable WETH;
constructor(IEtherTokenV06 weth)
public
{
WETH = weth;
}
function _tradeBancorV3(
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 amountOut)
{
IBancorV3 router;
IERC20TokenV06[] memory path;
address[] memory _path;
uint256 payableAmount = 0;
{
(router, _path) = abi.decode(bridgeData, (IBancorV3, address[]));
// To get around `abi.decode()` not supporting interface array types.
assembly { path := _path }
}
require(path.length >= 2, "MixinBancorV3/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
require(
path[path.length - 1] == buyToken,
"MixinBancorV3/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
);
//swap WETH->ETH as Bancor only deals in ETH
if(_path[0] == address(WETH)) {
//withdraw the sell amount of WETH for ETH
WETH.withdraw(sellAmount);
payableAmount = sellAmount;
// set _path[0] to the ETH address if WETH is our buy token
_path[0] = address(BANCORV3_ETH_ADDRESS);
} else {
// Grant the BancorV3 router an allowance to sell the first token.
path[0].approveIfBelow(address(router), sellAmount);
}
// if we are buying WETH we need to swap to ETH and deposit into WETH after the swap
if(_path[1] == address(WETH)){
_path[1] = address(BANCORV3_ETH_ADDRESS);
}
uint256 amountOut = router.tradeBySourceAmount{value: payableAmount}(
_path[0],
_path[1],
// Sell all tokens we hold.
sellAmount,
// Minimum buy amount.
1,
//deadline
block.timestamp + 1,
// address of the mixin
address(this)
);
// if we want to return WETH deposit the ETH amount we sold
if(buyToken == WETH){
WETH.deposit{value: amountOut}();
}
return amountOut;
}
}

View File

@@ -1,92 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
interface ICoFiXRouter {
// msg.value = fee
function swapExactTokensForETH(
address token,
uint amountIn,
uint amountOutMin,
address to,
address rewardTo,
uint deadline
) external payable returns (uint _amountIn, uint _amountOut);
// msg.value = amountIn + fee
function swapExactETHForTokens(
address token,
uint amountIn,
uint amountOutMin,
address to,
address rewardTo,
uint deadline
) external payable returns (uint _amountIn, uint _amountOut);
}
interface ICoFiXPair {
function swapWithExact(address outToken, address to)
external
payable
returns (
uint amountIn,
uint amountOut,
uint oracleFeeChange,
uint256[4] memory tradeInfo
);
}
contract MixinCoFiX {
using LibERC20TokenV06 for IERC20TokenV06;
function _tradeCoFiX(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
(uint256 fee, ICoFiXPair pool) = abi.decode(bridgeData, (uint256, ICoFiXPair));
// Transfer tokens into the pool
LibERC20TokenV06.compatTransfer(
sellToken,
address(pool),
sellAmount
);
// Call the swap exact with the tokens now in the pool
// pay the NEST Oracle fee with ETH
(/* In */, boughtAmount, , ) = pool.swapWithExact{value: fee}(
address(buyToken),
address(this)
);
return boughtAmount;
}
}

View File

@@ -0,0 +1,98 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../IBridgeAdapter.sol";
/*
UniswapV2
*/
interface IGmxRouter {
// /// @dev Swaps an exact amount of input tokens for as many output tokens as possible, along the route determined by the path.
// /// The first element of path is the input token, the last is the output token, and any intermediate elements represent
// /// intermediate pairs to trade through (if, for example, a direct pair does not exist).
// /// @param _path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
// /// @param _amountIn The amount of input tokens to send.
// /// @param _minOut The minimum amount of output tokens that must be received for the transaction not to revert.
// /// @param _reciever Recipient of the output tokens.
function swap(
address[] calldata _path, uint256 _amountIn, uint256 _minOut, address _receiver
) external;
}
contract MixinGMX {
using LibERC20TokenV06 for IERC20TokenV06;
using LibSafeMathV06 for uint256;
function _tradeGMX(
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
public
returns (uint256 boughtAmount)
{
address _router;
address reader;
address vault;
address[] memory _path;
IGmxRouter router;
IERC20TokenV06[] memory path;
{
//decode the bridge data
(_router, reader, vault, _path) = abi.decode(bridgeData, (address, address, address, address[]));
// To get around `abi.decode()` not supporting interface array types.
assembly { path := _path }
}
require(path.length >= 2, "MixinGMX/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
require(
path[path.length - 1] == buyToken,
"MixinGMX/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
);
//connect to the GMX router
router = IGmxRouter(_router);
// Grant the GMX router an allowance to sell the first token.
path[0].approveIfBelow(address(router), sellAmount);
//track the balance to know how much we bought
uint256 beforeBalance = buyToken.balanceOf(address(this));
router.swap(
// Convert to `buyToken` along this path.
_path,
// Sell all tokens we hold.
sellAmount,
// Minimum buy amount.
0,
// Recipient is `this`.
address(this)
);
//calculate the difference in balance from preswap->postswap to find how many tokens out
boughtAmount = buyToken.balanceOf(address(this)).safeSub(beforeBalance);
return boughtAmount;
}
}

View File

@@ -1,124 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
import "../IBridgeAdapter.sol";
interface IKyberNetworkProxy {
/// @dev Sells `sellTokenAddress` tokens for `buyTokenAddress` tokens
/// using a hint for the reserve.
/// @param sellToken Token to sell.
/// @param sellAmount Amount of tokens to sell.
/// @param buyToken Token to buy.
/// @param recipientAddress Address to send bought tokens to.
/// @param maxBuyTokenAmount A limit on the amount of tokens to buy.
/// @param minConversionRate The minimal conversion rate. If actual rate
/// is lower, trade is canceled.
/// @param walletId The wallet ID to send part of the fees
/// @param hint The hint for the selective inclusion (or exclusion) of reserves
/// @return boughtAmount Amount of tokens bought.
function tradeWithHint(
IERC20TokenV06 sellToken,
uint256 sellAmount,
IERC20TokenV06 buyToken,
address payable recipientAddress,
uint256 maxBuyTokenAmount,
uint256 minConversionRate,
address payable walletId,
bytes calldata hint
)
external
payable
returns (uint256 boughtAmount);
}
contract MixinKyber {
using LibERC20TokenV06 for IERC20TokenV06;
/// @dev Address indicating the trade is using ETH
IERC20TokenV06 private immutable KYBER_ETH_ADDRESS =
IERC20TokenV06(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
/// @dev Mainnet address of the WETH contract.
IEtherTokenV06 private immutable WETH;
constructor(IEtherTokenV06 weth)
public
{
WETH = weth;
}
function _tradeKyber(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
(IKyberNetworkProxy kyber, bytes memory hint) =
abi.decode(bridgeData, (IKyberNetworkProxy, bytes));
uint256 payableAmount = 0;
if (sellToken != WETH) {
// If the input token is not WETH, grant an allowance to the exchange
// to spend them.
sellToken.approveIfBelow(
address(kyber),
sellAmount
);
} else {
// If the input token is WETH, unwrap it and attach it to the call.
payableAmount = sellAmount;
WETH.withdraw(payableAmount);
}
// Try to sell all of this contract's input token balance through
// `KyberNetworkProxy.trade()`.
boughtAmount = kyber.tradeWithHint{ value: payableAmount }(
// Input token.
sellToken == WETH ? KYBER_ETH_ADDRESS : sellToken,
// Sell amount.
sellAmount,
// Output token.
buyToken == WETH ? KYBER_ETH_ADDRESS : buyToken,
// Transfer to this contract
address(uint160(address(this))),
// Buy as much as possible.
uint256(-1),
// Lowest minimum conversion rate
1,
// No affiliate address.
address(0),
hint
);
// If receving ETH, wrap it to WETH.
if (buyToken == WETH) {
WETH.deposit{ value: boughtAmount }();
}
return boughtAmount;
}
}

View File

@@ -26,7 +26,7 @@ import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
/// @dev Minimal interface for minting StETH
interface ILido {
interface IStETH {
/// @dev Adds eth to the pool
/// @param _referral optional address for referrals
/// @return StETH Amount of shares generated
@@ -37,6 +37,33 @@ interface ILido {
function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256);
}
/// @dev Minimal interface for wrapping/unwrapping stETH.
interface IWstETH {
/**
* @notice Exchanges stETH to wstETH
* @param _stETHAmount amount of stETH to wrap in exchange for wstETH
* @dev Requirements:
* - `_stETHAmount` must be non-zero
* - msg.sender must approve at least `_stETHAmount` stETH to this
* contract.
* - msg.sender must have at least `_stETHAmount` of stETH.
* User should first approve _stETHAmount to the WstETH contract
* @return Amount of wstETH user receives after wrap
*/
function wrap(uint256 _stETHAmount) external returns (uint256);
/**
* @notice Exchanges wstETH to stETH
* @param _wstETHAmount amount of wstETH to uwrap in exchange for stETH
* @dev Requirements:
* - `_wstETHAmount` must be non-zero
* - msg.sender must have at least `_wstETHAmount` wstETH.
* @return Amount of stETH user receives after unwrap
*/
function unwrap(uint256 _wstETHAmount) external returns (uint256);
}
contract MixinLido {
using LibERC20TokenV06 for IERC20TokenV06;
@@ -59,12 +86,43 @@ contract MixinLido {
internal
returns (uint256 boughtAmount)
{
(ILido lido) = abi.decode(bridgeData, (ILido));
if (address(sellToken) == address(WETH) && address(buyToken) == address(lido)) {
if (address(sellToken) == address(WETH)) {
return _tradeStETH(buyToken, sellAmount, bridgeData);
}
return _tradeWstETH(sellToken, buyToken, sellAmount, bridgeData);
}
function _tradeStETH(
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
) private returns (uint256 boughtAmount) {
(IStETH stETH) = abi.decode(bridgeData, (IStETH));
if (address(buyToken) == address(stETH)) {
WETH.withdraw(sellAmount);
boughtAmount = lido.getPooledEthByShares(lido.submit{ value: sellAmount}(address(0)));
} else {
revert("MixinLido/UNSUPPORTED_TOKEN_PAIR");
return stETH.getPooledEthByShares(stETH.submit{ value: sellAmount}(address(0)));
}
revert("MixinLido/UNSUPPORTED_TOKEN_PAIR");
}
function _tradeWstETH(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
) private returns(uint256 boughtAmount){
(IEtherTokenV06 stETH, IWstETH wstETH) = abi.decode(bridgeData, (IEtherTokenV06, IWstETH));
if (address(sellToken) == address(stETH) && address(buyToken) == address(wstETH) ) {
sellToken.approveIfBelow(address(wstETH), sellAmount);
return wstETH.wrap(sellAmount);
}
if (address(sellToken) == address(wstETH) && address(buyToken) == address(stETH) ) {
return wstETH.unwrap(sellAmount);
}
revert("MixinLido/UNSUPPORTED_TOKEN_PAIR");
}
}

View File

@@ -1,76 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "../IBridgeAdapter.sol";
interface IOasis {
/// @dev Sell `sellAmount` of `sellToken` token and receive `buyToken` token.
/// @param sellToken The token being sold.
/// @param sellAmount The amount of `sellToken` token being sold.
/// @param buyToken The token being bought.
/// @param minBoughtAmount Minimum amount of `buyToken` token to buy.
/// @return boughtAmount Amount of `buyToken` bought.
function sellAllAmount(
IERC20TokenV06 sellToken,
uint256 sellAmount,
IERC20TokenV06 buyToken,
uint256 minBoughtAmount
)
external
returns (uint256 boughtAmount);
}
contract MixinOasis {
using LibERC20TokenV06 for IERC20TokenV06;
function _tradeOasis(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
(IOasis oasis) = abi.decode(bridgeData, (IOasis));
// Grant an allowance to the exchange to spend `sellToken` token.
sellToken.approveIfBelow(
address(oasis),
sellAmount
);
// Try to sell all of this contract's `sellToken` token balance.
boughtAmount = oasis.sellAllAmount(
sellToken,
sellAmount,
buyToken,
// min fill amount
1
);
return boughtAmount;
}
}

View File

@@ -0,0 +1,98 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
interface IPlatypusRouter {
function swapTokensForTokens(
address[] calldata tokenPath,
address[] calldata poolPath,
uint256 fromAmount,
uint256 minimumToAmount,
address to,
uint256 deadline
) external returns (uint256 amountOut, uint256 haircut);
}
contract MixinPlatypus {
using LibERC20TokenV06 for IERC20TokenV06;
using LibSafeMathV06 for uint256;
function _tradePlatypus(
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
public
returns (uint256 boughtAmount)
{
IPlatypusRouter router;
address _router;
address[] memory _pool;
IERC20TokenV06[] memory path;
address[] memory _path;
{
(_router, _pool, _path) = abi.decode(bridgeData, (address, address[], address[]));
// To get around `abi.decode()` not supporting interface array types.
assembly { path := _path }
}
//connect to the ptp router
router = IPlatypusRouter(_router);
require(path.length >= 2, "MixinPlatypus/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
require(
path[path.length - 1] == buyToken,
"MixinPlatypus/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
);
// Grant the Platypus router an allowance to sell the first token.
path[0].approveIfBelow(address(router), sellAmount);
//keep track of the previous balance to confirm amount out
uint256 beforeBalance = buyToken.balanceOf(address(this));
router.swapTokensForTokens(
// Convert to `buyToken` along this path.
_path,
// pool to swap on
_pool,
// Sell all tokens we hold.
sellAmount,
// Minimum buy amount.
0,
// Recipient is `this`.
address(this),
block.timestamp + 1
);
//calculate the buy amount from the tokens we recieved
boughtAmount = buyToken.balanceOf(address(this)).safeSub(beforeBalance);
return boughtAmount;
}
}

View File

@@ -0,0 +1,64 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
interface IVelodromeRouter {
function swapExactTokensForTokensSimple(
uint256 amountIn,
uint256 amountOutMin,
address tokenFrom,
address tokenTo,
bool stable,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
}
contract MixinVelodrome {
using LibERC20TokenV06 for IERC20TokenV06;
function _tradeVelodrome(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
(IVelodromeRouter router, bool stable) = abi.decode(bridgeData, (IVelodromeRouter, bool));
sellToken.approveIfBelow(address(router), sellAmount);
boughtAmount = router.swapExactTokensForTokensSimple(
sellAmount,
0,
address(sellToken),
address(buyToken),
stable,
address(this),
block.timestamp + 1
)[1];
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-zero-ex",
"version": "0.31.1",
"version": "0.35.0",
"engines": {
"node": ">=6.12"
},
@@ -41,9 +41,9 @@
"rollback": "node ./lib/scripts/rollback.js"
},
"config": {
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature",
"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",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2|MixinBancor|MixinCoFiX|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
"abis": "./test/generated-artifacts/@(AbstractBridgeAdapter|AffiliateFeeTransformer|AvalancheBridgeAdapter|BSCBridgeAdapter|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeProtocols|CeloBridgeAdapter|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|EthereumBridgeAdapter|FantomBridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2|MixinBalancerV2Batch|MixinBancor|MixinBancorV3|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinGMX|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinPlatypus|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinVelodrome|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OptimismBridgeAdapter|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PolygonBridgeAdapter|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
},
"repository": {
"type": "git",
@@ -56,10 +56,10 @@
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex",
"devDependencies": {
"@0x/abi-gen": "^5.8.0",
"@0x/contract-addresses": "^6.12.0",
"@0x/contracts-erc20": "^3.3.27",
"@0x/contract-addresses": "^6.16.0",
"@0x/contracts-erc20": "^3.3.32",
"@0x/contracts-gen": "^2.0.46",
"@0x/contracts-test-utils": "^5.4.18",
"@0x/contracts-test-utils": "^5.4.23",
"@0x/dev-utils": "^4.2.14",
"@0x/order-utils": "^10.4.28",
"@0x/sol-compiler": "^4.8.1",
@@ -79,11 +79,11 @@
"truffle": "^5.0.32",
"tslint": "5.11.0",
"typedoc": "~0.16.11",
"typescript": "4.2.2"
"typescript": "4.6.3"
},
"dependencies": {
"@0x/base-contract": "^6.5.0",
"@0x/protocol-utils": "^1.11.1",
"@0x/protocol-utils": "^11.15.0",
"@0x/subproviders": "^6.6.5",
"@0x/types": "^3.3.6",
"@0x/typescript-typings": "^5.3.1",

View File

@@ -6,9 +6,13 @@
import { ContractArtifact } from 'ethereum-types';
import * as AffiliateFeeTransformer from '../generated-artifacts/AffiliateFeeTransformer.json';
import * as AvalancheBridgeAdapter from '../generated-artifacts/AvalancheBridgeAdapter.json';
import * as BatchFillNativeOrdersFeature from '../generated-artifacts/BatchFillNativeOrdersFeature.json';
import * as BridgeAdapter from '../generated-artifacts/BridgeAdapter.json';
import * as BSCBridgeAdapter from '../generated-artifacts/BSCBridgeAdapter.json';
import * as CeloBridgeAdapter from '../generated-artifacts/CeloBridgeAdapter.json';
import * as CurveLiquidityProvider from '../generated-artifacts/CurveLiquidityProvider.json';
import * as EthereumBridgeAdapter from '../generated-artifacts/EthereumBridgeAdapter.json';
import * as FantomBridgeAdapter from '../generated-artifacts/FantomBridgeAdapter.json';
import * as FeeCollector from '../generated-artifacts/FeeCollector.json';
import * as FeeCollectorController from '../generated-artifacts/FeeCollectorController.json';
import * as FillQuoteTransformer from '../generated-artifacts/FillQuoteTransformer.json';
@@ -30,9 +34,11 @@ import * as LogMetadataTransformer from '../generated-artifacts/LogMetadataTrans
import * as MetaTransactionsFeature from '../generated-artifacts/MetaTransactionsFeature.json';
import * as MultiplexFeature from '../generated-artifacts/MultiplexFeature.json';
import * as NativeOrdersFeature from '../generated-artifacts/NativeOrdersFeature.json';
import * as OptimismBridgeAdapter from '../generated-artifacts/OptimismBridgeAdapter.json';
import * as OtcOrdersFeature from '../generated-artifacts/OtcOrdersFeature.json';
import * as OwnableFeature from '../generated-artifacts/OwnableFeature.json';
import * as PayTakerTransformer from '../generated-artifacts/PayTakerTransformer.json';
import * as PolygonBridgeAdapter from '../generated-artifacts/PolygonBridgeAdapter.json';
import * as PositiveSlippageFeeTransformer from '../generated-artifacts/PositiveSlippageFeeTransformer.json';
import * as SimpleFunctionRegistryFeature from '../generated-artifacts/SimpleFunctionRegistryFeature.json';
import * as TransformERC20Feature from '../generated-artifacts/TransformERC20Feature.json';
@@ -58,7 +64,6 @@ export const artifacts = {
AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact,
MetaTransactionsFeature: MetaTransactionsFeature as ContractArtifact,
LogMetadataTransformer: LogMetadataTransformer as ContractArtifact,
BridgeAdapter: BridgeAdapter as ContractArtifact,
LiquidityProviderFeature: LiquidityProviderFeature as ContractArtifact,
ILiquidityProviderFeature: ILiquidityProviderFeature as ContractArtifact,
NativeOrdersFeature: NativeOrdersFeature as ContractArtifact,
@@ -72,4 +77,11 @@ export const artifacts = {
IMultiplexFeature: IMultiplexFeature as ContractArtifact,
OtcOrdersFeature: OtcOrdersFeature as ContractArtifact,
IOtcOrdersFeature: IOtcOrdersFeature as ContractArtifact,
AvalancheBridgeAdapter: AvalancheBridgeAdapter as ContractArtifact,
BSCBridgeAdapter: BSCBridgeAdapter as ContractArtifact,
CeloBridgeAdapter: CeloBridgeAdapter as ContractArtifact,
EthereumBridgeAdapter: EthereumBridgeAdapter as ContractArtifact,
FantomBridgeAdapter: FantomBridgeAdapter as ContractArtifact,
OptimismBridgeAdapter: OptimismBridgeAdapter as ContractArtifact,
PolygonBridgeAdapter: PolygonBridgeAdapter as ContractArtifact,
};

View File

@@ -35,7 +35,11 @@ export * from './bloom_filter_utils';
export { GREEDY_TOKENS } from './constants';
export {
AffiliateFeeTransformerContract,
BridgeAdapterContract,
AvalancheBridgeAdapterContract,
BSCBridgeAdapterContract,
CeloBridgeAdapterContract,
EthereumBridgeAdapterContract,
FantomBridgeAdapterContract,
FillQuoteTransformerContract,
IOwnableFeatureContract,
IOwnableFeatureEvents,
@@ -45,7 +49,9 @@ export {
IZeroExContract,
LogMetadataTransformerContract,
MultiplexFeatureContract,
OptimismBridgeAdapterContract,
PayTakerTransformerContract,
PolygonBridgeAdapterContract,
PositiveSlippageFeeTransformerContract,
TransformERC20FeatureContract,
WethTransformerContract,

View File

@@ -4,9 +4,13 @@
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/affiliate_fee_transformer';
export * from '../generated-wrappers/avalanche_bridge_adapter';
export * from '../generated-wrappers/b_s_c_bridge_adapter';
export * from '../generated-wrappers/batch_fill_native_orders_feature';
export * from '../generated-wrappers/bridge_adapter';
export * from '../generated-wrappers/celo_bridge_adapter';
export * from '../generated-wrappers/curve_liquidity_provider';
export * from '../generated-wrappers/ethereum_bridge_adapter';
export * from '../generated-wrappers/fantom_bridge_adapter';
export * from '../generated-wrappers/fee_collector';
export * from '../generated-wrappers/fee_collector_controller';
export * from '../generated-wrappers/fill_quote_transformer';
@@ -28,9 +32,11 @@ export * from '../generated-wrappers/log_metadata_transformer';
export * from '../generated-wrappers/meta_transactions_feature';
export * from '../generated-wrappers/multiplex_feature';
export * from '../generated-wrappers/native_orders_feature';
export * from '../generated-wrappers/optimism_bridge_adapter';
export * from '../generated-wrappers/otc_orders_feature';
export * from '../generated-wrappers/ownable_feature';
export * from '../generated-wrappers/pay_taker_transformer';
export * from '../generated-wrappers/polygon_bridge_adapter';
export * from '../generated-wrappers/positive_slippage_fee_transformer';
export * from '../generated-wrappers/simple_function_registry_feature';
export * from '../generated-wrappers/transform_erc20_feature';

View File

@@ -5,15 +5,20 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as AbstractBridgeAdapter from '../test/generated-artifacts/AbstractBridgeAdapter.json';
import * as AffiliateFeeTransformer from '../test/generated-artifacts/AffiliateFeeTransformer.json';
import * as AvalancheBridgeAdapter from '../test/generated-artifacts/AvalancheBridgeAdapter.json';
import * as BatchFillNativeOrdersFeature from '../test/generated-artifacts/BatchFillNativeOrdersFeature.json';
import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json';
import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.json';
import * as BridgeProtocols from '../test/generated-artifacts/BridgeProtocols.json';
import * as BSCBridgeAdapter from '../test/generated-artifacts/BSCBridgeAdapter.json';
import * as CeloBridgeAdapter from '../test/generated-artifacts/CeloBridgeAdapter.json';
import * as CurveLiquidityProvider from '../test/generated-artifacts/CurveLiquidityProvider.json';
import * as ERC1155OrdersFeature from '../test/generated-artifacts/ERC1155OrdersFeature.json';
import * as ERC165Feature from '../test/generated-artifacts/ERC165Feature.json';
import * as ERC721OrdersFeature from '../test/generated-artifacts/ERC721OrdersFeature.json';
import * as EthereumBridgeAdapter from '../test/generated-artifacts/EthereumBridgeAdapter.json';
import * as FantomBridgeAdapter from '../test/generated-artifacts/FantomBridgeAdapter.json';
import * as FeeCollector from '../test/generated-artifacts/FeeCollector.json';
import * as FeeCollectorController from '../test/generated-artifacts/FeeCollectorController.json';
import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json';
@@ -101,26 +106,28 @@ import * as MetaTransactionsFeature from '../test/generated-artifacts/MetaTransa
import * as MixinAaveV2 from '../test/generated-artifacts/MixinAaveV2.json';
import * as MixinBalancer from '../test/generated-artifacts/MixinBalancer.json';
import * as MixinBalancerV2 from '../test/generated-artifacts/MixinBalancerV2.json';
import * as MixinBalancerV2Batch from '../test/generated-artifacts/MixinBalancerV2Batch.json';
import * as MixinBancor from '../test/generated-artifacts/MixinBancor.json';
import * as MixinCoFiX from '../test/generated-artifacts/MixinCoFiX.json';
import * as MixinBancorV3 from '../test/generated-artifacts/MixinBancorV3.json';
import * as MixinCompound from '../test/generated-artifacts/MixinCompound.json';
import * as MixinCryptoCom from '../test/generated-artifacts/MixinCryptoCom.json';
import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json';
import * as MixinCurveV2 from '../test/generated-artifacts/MixinCurveV2.json';
import * as MixinDodo from '../test/generated-artifacts/MixinDodo.json';
import * as MixinDodoV2 from '../test/generated-artifacts/MixinDodoV2.json';
import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json';
import * as MixinGMX from '../test/generated-artifacts/MixinGMX.json';
import * as MixinKyberDmm from '../test/generated-artifacts/MixinKyberDmm.json';
import * as MixinLido from '../test/generated-artifacts/MixinLido.json';
import * as MixinMakerPSM from '../test/generated-artifacts/MixinMakerPSM.json';
import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json';
import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json';
import * as MixinNerve from '../test/generated-artifacts/MixinNerve.json';
import * as MixinOasis from '../test/generated-artifacts/MixinOasis.json';
import * as MixinPlatypus from '../test/generated-artifacts/MixinPlatypus.json';
import * as MixinShell from '../test/generated-artifacts/MixinShell.json';
import * as MixinUniswap from '../test/generated-artifacts/MixinUniswap.json';
import * as MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json';
import * as MixinUniswapV3 from '../test/generated-artifacts/MixinUniswapV3.json';
import * as MixinVelodrome from '../test/generated-artifacts/MixinVelodrome.json';
import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json';
import * as MooniswapLiquidityProvider from '../test/generated-artifacts/MooniswapLiquidityProvider.json';
import * as MultiplexFeature from '../test/generated-artifacts/MultiplexFeature.json';
@@ -136,11 +143,13 @@ import * as NativeOrdersInfo from '../test/generated-artifacts/NativeOrdersInfo.
import * as NativeOrdersProtocolFees from '../test/generated-artifacts/NativeOrdersProtocolFees.json';
import * as NativeOrdersSettlement from '../test/generated-artifacts/NativeOrdersSettlement.json';
import * as NFTOrders from '../test/generated-artifacts/NFTOrders.json';
import * as OptimismBridgeAdapter from '../test/generated-artifacts/OptimismBridgeAdapter.json';
import * as OtcOrdersFeature from '../test/generated-artifacts/OtcOrdersFeature.json';
import * as OwnableFeature from '../test/generated-artifacts/OwnableFeature.json';
import * as PancakeSwapFeature from '../test/generated-artifacts/PancakeSwapFeature.json';
import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json';
import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/PermissionlessTransformerDeployer.json';
import * as PolygonBridgeAdapter from '../test/generated-artifacts/PolygonBridgeAdapter.json';
import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.json';
import * as SimpleFunctionRegistryFeature from '../test/generated-artifacts/SimpleFunctionRegistryFeature.json';
import * as TestBridge from '../test/generated-artifacts/TestBridge.json';
@@ -307,32 +316,41 @@ export const artifacts = {
PositiveSlippageFeeTransformer: PositiveSlippageFeeTransformer as ContractArtifact,
Transformer: Transformer as ContractArtifact,
WethTransformer: WethTransformer as ContractArtifact,
BridgeAdapter: BridgeAdapter as ContractArtifact,
AbstractBridgeAdapter: AbstractBridgeAdapter as ContractArtifact,
AvalancheBridgeAdapter: AvalancheBridgeAdapter as ContractArtifact,
BSCBridgeAdapter: BSCBridgeAdapter as ContractArtifact,
BridgeProtocols: BridgeProtocols as ContractArtifact,
CeloBridgeAdapter: CeloBridgeAdapter as ContractArtifact,
EthereumBridgeAdapter: EthereumBridgeAdapter as ContractArtifact,
FantomBridgeAdapter: FantomBridgeAdapter as ContractArtifact,
IBridgeAdapter: IBridgeAdapter as ContractArtifact,
OptimismBridgeAdapter: OptimismBridgeAdapter as ContractArtifact,
PolygonBridgeAdapter: PolygonBridgeAdapter as ContractArtifact,
MixinAaveV2: MixinAaveV2 as ContractArtifact,
MixinBalancer: MixinBalancer as ContractArtifact,
MixinBalancerV2: MixinBalancerV2 as ContractArtifact,
MixinBalancerV2Batch: MixinBalancerV2Batch as ContractArtifact,
MixinBancor: MixinBancor as ContractArtifact,
MixinCoFiX: MixinCoFiX as ContractArtifact,
MixinBancorV3: MixinBancorV3 as ContractArtifact,
MixinCompound: MixinCompound as ContractArtifact,
MixinCryptoCom: MixinCryptoCom as ContractArtifact,
MixinCurve: MixinCurve as ContractArtifact,
MixinCurveV2: MixinCurveV2 as ContractArtifact,
MixinDodo: MixinDodo as ContractArtifact,
MixinDodoV2: MixinDodoV2 as ContractArtifact,
MixinKyber: MixinKyber as ContractArtifact,
MixinGMX: MixinGMX as ContractArtifact,
MixinKyberDmm: MixinKyberDmm as ContractArtifact,
MixinLido: MixinLido as ContractArtifact,
MixinMStable: MixinMStable as ContractArtifact,
MixinMakerPSM: MixinMakerPSM as ContractArtifact,
MixinMooniswap: MixinMooniswap as ContractArtifact,
MixinNerve: MixinNerve as ContractArtifact,
MixinOasis: MixinOasis as ContractArtifact,
MixinPlatypus: MixinPlatypus as ContractArtifact,
MixinShell: MixinShell as ContractArtifact,
MixinUniswap: MixinUniswap as ContractArtifact,
MixinUniswapV2: MixinUniswapV2 as ContractArtifact,
MixinUniswapV3: MixinUniswapV3 as ContractArtifact,
MixinVelodrome: MixinVelodrome as ContractArtifact,
MixinZeroExBridge: MixinZeroExBridge as ContractArtifact,
IERC1155Token: IERC1155Token as ContractArtifact,
IERC721Token: IERC721Token as ContractArtifact,

View File

@@ -28,7 +28,7 @@ import { artifacts } from '../artifacts';
import { TestFillQuoteTransformerBridgeContract } from '../generated-wrappers/test_fill_quote_transformer_bridge';
import { getRandomLimitOrder, getRandomRfqOrder } from '../utils/orders';
import {
BridgeAdapterContract,
EthereumBridgeAdapterContract,
FillQuoteTransformerContract,
TestFillQuoteTransformerExchangeContract,
TestFillQuoteTransformerHostContract,
@@ -52,7 +52,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
let singleProtocolFee: BigNumber;
const GAS_PRICE = 1337;
const TEST_BRIDGE_SOURCE = hexUtils.random(32);
// Left half is 0, corresponding to BridgeProtocol.Unknown
const TEST_BRIDGE_SOURCE = hexUtils.leftPad(hexUtils.random(16), 32);
const HIGH_BIT = new BigNumber(2).pow(255);
const REVERT_AMOUNT = new BigNumber('0xdeadbeef');
@@ -64,8 +65,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
env.txDefaults,
artifacts,
);
const bridgeAdapter = await BridgeAdapterContract.deployFrom0xArtifactAsync(
artifacts.BridgeAdapter,
const bridgeAdapter = await EthereumBridgeAdapterContract.deployFrom0xArtifactAsync(
artifacts.EthereumBridgeAdapter,
env.provider,
env.txDefaults,
artifacts,

View File

@@ -3,15 +3,20 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/abstract_bridge_adapter';
export * from '../test/generated-wrappers/affiliate_fee_transformer';
export * from '../test/generated-wrappers/avalanche_bridge_adapter';
export * from '../test/generated-wrappers/b_s_c_bridge_adapter';
export * from '../test/generated-wrappers/batch_fill_native_orders_feature';
export * from '../test/generated-wrappers/bootstrap_feature';
export * from '../test/generated-wrappers/bridge_adapter';
export * from '../test/generated-wrappers/bridge_protocols';
export * from '../test/generated-wrappers/celo_bridge_adapter';
export * from '../test/generated-wrappers/curve_liquidity_provider';
export * from '../test/generated-wrappers/erc1155_orders_feature';
export * from '../test/generated-wrappers/erc165_feature';
export * from '../test/generated-wrappers/erc721_orders_feature';
export * from '../test/generated-wrappers/ethereum_bridge_adapter';
export * from '../test/generated-wrappers/fantom_bridge_adapter';
export * from '../test/generated-wrappers/fee_collector';
export * from '../test/generated-wrappers/fee_collector_controller';
export * from '../test/generated-wrappers/fill_quote_transformer';
@@ -99,26 +104,28 @@ export * from '../test/generated-wrappers/meta_transactions_feature';
export * from '../test/generated-wrappers/mixin_aave_v2';
export * from '../test/generated-wrappers/mixin_balancer';
export * from '../test/generated-wrappers/mixin_balancer_v2';
export * from '../test/generated-wrappers/mixin_balancer_v2_batch';
export * from '../test/generated-wrappers/mixin_bancor';
export * from '../test/generated-wrappers/mixin_co_fi_x';
export * from '../test/generated-wrappers/mixin_bancor_v3';
export * from '../test/generated-wrappers/mixin_compound';
export * from '../test/generated-wrappers/mixin_crypto_com';
export * from '../test/generated-wrappers/mixin_curve';
export * from '../test/generated-wrappers/mixin_curve_v2';
export * from '../test/generated-wrappers/mixin_dodo';
export * from '../test/generated-wrappers/mixin_dodo_v2';
export * from '../test/generated-wrappers/mixin_kyber';
export * from '../test/generated-wrappers/mixin_g_m_x';
export * from '../test/generated-wrappers/mixin_kyber_dmm';
export * from '../test/generated-wrappers/mixin_lido';
export * from '../test/generated-wrappers/mixin_m_stable';
export * from '../test/generated-wrappers/mixin_maker_p_s_m';
export * from '../test/generated-wrappers/mixin_mooniswap';
export * from '../test/generated-wrappers/mixin_nerve';
export * from '../test/generated-wrappers/mixin_oasis';
export * from '../test/generated-wrappers/mixin_platypus';
export * from '../test/generated-wrappers/mixin_shell';
export * from '../test/generated-wrappers/mixin_uniswap';
export * from '../test/generated-wrappers/mixin_uniswap_v2';
export * from '../test/generated-wrappers/mixin_uniswap_v3';
export * from '../test/generated-wrappers/mixin_velodrome';
export * from '../test/generated-wrappers/mixin_zero_ex_bridge';
export * from '../test/generated-wrappers/mooniswap_liquidity_provider';
export * from '../test/generated-wrappers/multiplex_feature';
@@ -134,11 +141,13 @@ export * from '../test/generated-wrappers/native_orders_feature';
export * from '../test/generated-wrappers/native_orders_info';
export * from '../test/generated-wrappers/native_orders_protocol_fees';
export * from '../test/generated-wrappers/native_orders_settlement';
export * from '../test/generated-wrappers/optimism_bridge_adapter';
export * from '../test/generated-wrappers/otc_orders_feature';
export * from '../test/generated-wrappers/ownable_feature';
export * from '../test/generated-wrappers/pancake_swap_feature';
export * from '../test/generated-wrappers/pay_taker_transformer';
export * from '../test/generated-wrappers/permissionless_transformer_deployer';
export * from '../test/generated-wrappers/polygon_bridge_adapter';
export * from '../test/generated-wrappers/positive_slippage_fee_transformer';
export * from '../test/generated-wrappers/simple_function_registry_feature';
export * from '../test/generated-wrappers/test_bridge';

View File

@@ -4,9 +4,13 @@
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*", "./scripts/**/*"],
"files": [
"generated-artifacts/AffiliateFeeTransformer.json",
"generated-artifacts/AvalancheBridgeAdapter.json",
"generated-artifacts/BSCBridgeAdapter.json",
"generated-artifacts/BatchFillNativeOrdersFeature.json",
"generated-artifacts/BridgeAdapter.json",
"generated-artifacts/CeloBridgeAdapter.json",
"generated-artifacts/CurveLiquidityProvider.json",
"generated-artifacts/EthereumBridgeAdapter.json",
"generated-artifacts/FantomBridgeAdapter.json",
"generated-artifacts/FeeCollector.json",
"generated-artifacts/FeeCollectorController.json",
"generated-artifacts/FillQuoteTransformer.json",
@@ -28,23 +32,30 @@
"generated-artifacts/MetaTransactionsFeature.json",
"generated-artifacts/MultiplexFeature.json",
"generated-artifacts/NativeOrdersFeature.json",
"generated-artifacts/OptimismBridgeAdapter.json",
"generated-artifacts/OtcOrdersFeature.json",
"generated-artifacts/OwnableFeature.json",
"generated-artifacts/PayTakerTransformer.json",
"generated-artifacts/PolygonBridgeAdapter.json",
"generated-artifacts/PositiveSlippageFeeTransformer.json",
"generated-artifacts/SimpleFunctionRegistryFeature.json",
"generated-artifacts/TransformERC20Feature.json",
"generated-artifacts/WethTransformer.json",
"generated-artifacts/ZeroEx.json",
"test/generated-artifacts/AbstractBridgeAdapter.json",
"test/generated-artifacts/AffiliateFeeTransformer.json",
"test/generated-artifacts/AvalancheBridgeAdapter.json",
"test/generated-artifacts/BSCBridgeAdapter.json",
"test/generated-artifacts/BatchFillNativeOrdersFeature.json",
"test/generated-artifacts/BootstrapFeature.json",
"test/generated-artifacts/BridgeAdapter.json",
"test/generated-artifacts/BridgeProtocols.json",
"test/generated-artifacts/CeloBridgeAdapter.json",
"test/generated-artifacts/CurveLiquidityProvider.json",
"test/generated-artifacts/ERC1155OrdersFeature.json",
"test/generated-artifacts/ERC165Feature.json",
"test/generated-artifacts/ERC721OrdersFeature.json",
"test/generated-artifacts/EthereumBridgeAdapter.json",
"test/generated-artifacts/FantomBridgeAdapter.json",
"test/generated-artifacts/FeeCollector.json",
"test/generated-artifacts/FeeCollectorController.json",
"test/generated-artifacts/FillQuoteTransformer.json",
@@ -132,26 +143,28 @@
"test/generated-artifacts/MixinAaveV2.json",
"test/generated-artifacts/MixinBalancer.json",
"test/generated-artifacts/MixinBalancerV2.json",
"test/generated-artifacts/MixinBalancerV2Batch.json",
"test/generated-artifacts/MixinBancor.json",
"test/generated-artifacts/MixinCoFiX.json",
"test/generated-artifacts/MixinBancorV3.json",
"test/generated-artifacts/MixinCompound.json",
"test/generated-artifacts/MixinCryptoCom.json",
"test/generated-artifacts/MixinCurve.json",
"test/generated-artifacts/MixinCurveV2.json",
"test/generated-artifacts/MixinDodo.json",
"test/generated-artifacts/MixinDodoV2.json",
"test/generated-artifacts/MixinKyber.json",
"test/generated-artifacts/MixinGMX.json",
"test/generated-artifacts/MixinKyberDmm.json",
"test/generated-artifacts/MixinLido.json",
"test/generated-artifacts/MixinMStable.json",
"test/generated-artifacts/MixinMakerPSM.json",
"test/generated-artifacts/MixinMooniswap.json",
"test/generated-artifacts/MixinNerve.json",
"test/generated-artifacts/MixinOasis.json",
"test/generated-artifacts/MixinPlatypus.json",
"test/generated-artifacts/MixinShell.json",
"test/generated-artifacts/MixinUniswap.json",
"test/generated-artifacts/MixinUniswapV2.json",
"test/generated-artifacts/MixinUniswapV3.json",
"test/generated-artifacts/MixinVelodrome.json",
"test/generated-artifacts/MixinZeroExBridge.json",
"test/generated-artifacts/MooniswapLiquidityProvider.json",
"test/generated-artifacts/MultiplexFeature.json",
@@ -167,11 +180,13 @@
"test/generated-artifacts/NativeOrdersInfo.json",
"test/generated-artifacts/NativeOrdersProtocolFees.json",
"test/generated-artifacts/NativeOrdersSettlement.json",
"test/generated-artifacts/OptimismBridgeAdapter.json",
"test/generated-artifacts/OtcOrdersFeature.json",
"test/generated-artifacts/OwnableFeature.json",
"test/generated-artifacts/PancakeSwapFeature.json",
"test/generated-artifacts/PayTakerTransformer.json",
"test/generated-artifacts/PermissionlessTransformerDeployer.json",
"test/generated-artifacts/PolygonBridgeAdapter.json",
"test/generated-artifacts/PositiveSlippageFeeTransformer.json",
"test/generated-artifacts/SimpleFunctionRegistryFeature.json",
"test/generated-artifacts/TestBridge.json",

View File

@@ -52,10 +52,10 @@
},
"config": {
"contractsPackages": "@0x/contracts-erc20 @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-zero-ex @0x/contracts-treasury",
"nonContractPackages": "@0x/migrations @0x/contract-wrappers @0x/contract-addresses @0x/contract-artifacts @0x/contract-wrappers-test @0x/asset-swapper",
"nonContractPackages": "@0x/contract-wrappers @0x/contract-addresses @0x/contract-artifacts @0x/contract-wrappers-test @0x/asset-swapper",
"ignoreTestsForPackages": "",
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic",
"packagesWithDocPages": "@0x/contract-wrappers @0x/migrations",
"packagesWithDocPages": "@0x/contract-wrappers",
"ignoreDependencyVersions": "@types/styled-components @types/node",
"ignoreDependencyVersionsForPackage": "contract-wrappers"
},
@@ -71,7 +71,7 @@
"npm-run-all": "^4.1.2",
"prettier": "1.19.1",
"source-map-support": "^0.5.6",
"typescript": "4.2.2",
"typescript": "4.6.3",
"wsrun": "^5.2.4"
},
"resolutions": {

View File

@@ -1,4 +1,216 @@
[
{
"version": "16.62.1",
"changes": [
{
"note": "Remove nUSD from intermediate liquidity to save on sampler gas",
"pr": 505
}
],
"timestamp": 1655253622
},
{
"version": "16.62.0",
"changes": [
{
"note": "Add MDEX on BSC",
"pr": 496
},
{
"note": "Add KnightSwap on BSC",
"pr": 498
},
{
"note": "Add Velodrome support on Optimism",
"pr": 494
},
{
"note": "Do not send empty entries on Quote Report",
"pr": 501
},
{
"note": "KnightSwap/Mdex cosmetic change",
"pr": 502
},
{
"note": "Offboard JetSwap, CafeSwap, JulSwap, and PolyDex",
"pr": 503
}
],
"timestamp": 1655244958
},
{
"version": "16.61.0",
"changes": [
{
"note": "Add stETH wrap/unwrap support",
"pr": 476
},
{
"note": "Offboard/clean up Oasis, CoFix, and legacy Kyber",
"pr": 482
},
{
"note": "Add MeshSwap on Polygon",
"pr": 491
}
],
"timestamp": 1654284040
},
{
"version": "16.60.1",
"changes": [
{
"note": "Alias Balancer sor to the old version",
"pr": 481
}
],
"timestamp": 1652931596
},
{
"version": "16.60.0",
"changes": [
{
"note": "Add BiSwap on BSC",
"pr": 467
},
{
"note": "Add GMX and Platypus on Avalanche and Enable KyberDMM on bsc",
"pr": 478
},
{
"note": "Add Yoshi Exchange support in Fantom",
"pr": 473
},
{
"note": "Fix KyberDMM gas underestimation",
"pr": 479
}
],
"timestamp": 1652919697
},
{
"version": "16.59.0",
"changes": [
{
"note": "Remove SnowSwap on mainnet",
"pr": 468
},
{
"note": "Offboard Swerve Finance and LinkSwap",
"pr": 469
},
{
"note": "Offboard Eth2Dai",
"pr": 470
},
{
"note": "Add an optional IRfqClient for SwapQuoter#getSwapQuoteAsync",
"pr": 467
}
],
"timestamp": 1652400434
},
{
"version": "16.58.0",
"changes": [
{
"note": "Update Saddle pools on Mainnet",
"pr": 450
}
]
},
{
"version": "16.57.3",
"changes": [
{
"note": "Fix a runtime error related to BalancerV2SwapInfoCache",
"pr": 472
}
],
"timestamp": 1652146864
},
{
"version": "16.57.2",
"changes": [
{
"note": "Fix missing AMM quotes on indicative Quote Reports",
"pr": 466
}
],
"timestamp": 1651526551
},
{
"version": "16.57.1",
"changes": [
{
"note": "Added QUICK/ANY pair on Polygon",
"pr": 464
},
{
"note": "Added cvxFXS/FXS curve pool on mainnet",
"pr": 465
}
]
},
{
"version": "16.57.0",
"changes": [
{
"note": "Add BalancerV2 batch swap support",
"pr": 462
}
],
"timestamp": 1650611093
},
{
"version": "16.56.0",
"changes": [
{
"note": "Add estimatedGas to ExtendedQuoteReport",
"pr": 463
}
],
"timestamp": 1650575781
},
{
"version": "16.55.0",
"changes": [
{
"note": "Fix fillRfqOrder VIP being used for swaps that need transformERC20",
"pr": 461
}
],
"timestamp": 1649347667
},
{
"version": "16.54.0",
"changes": [
{
"note": "Add true VIP support for eligible RFQt swaps",
"pr": 458
}
],
"timestamp": 1649215576
},
{
"version": "16.53.0",
"changes": [
{
"note": "Adds support for STG/USDC pool on Curve Mainnet",
"pr": 451
},
{
"note": "Use neon-router in asset-swapper tests",
"pr": 453
},
{
"note": "Add sampler blocknumber to quote report data",
"pr": 448
}
],
"timestamp": 1648739346
},
{
"version": "16.52.0",
"changes": [

View File

@@ -5,6 +5,86 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v16.62.1 - _June 15, 2022_
* Remove nUSD from intermediate liquidity to save on sampler gas (#505)
## v16.62.0 - _June 14, 2022_
* Add MDEX on BSC (#496)
* Add KnightSwap on BSC (#498)
* Add Velodrome support on Optimism (#494)
* Do not send empty entries on Quote Report (#501)
* KnightSwap/Mdex cosmetic change (#502)
* Offboard JetSwap, CafeSwap, JulSwap, and PolyDex (#503)
## v16.61.0 - _June 3, 2022_
* Add stETH wrap/unwrap support (#476)
* Offboard/clean up Oasis, CoFix, and legacy Kyber (#482)
* Add MeshSwap on Polygon (#491)
## v16.60.1 - _May 19, 2022_
* Alias Balancer sor to the old version (#481)
## v16.60.0 - _May 19, 2022_
* Add BiSwap on BSC (#467)
* Add GMX and Platypus on Avalanche and Enable KyberDMM on bsc (#478)
* Add Yoshi Exchange support in Fantom (#473)
* Fix KyberDMM gas underestimation (#479)
## v16.59.0 - _May 13, 2022_
* Remove SnowSwap on mainnet (#468)
* Offboard Swerve Finance and LinkSwap (#469)
* Offboard Eth2Dai (#470)
* Add an optional IRfqClient for SwapQuoter#getSwapQuoteAsync (#467)
## v16.58.0 - _Invalid date_
* Update Saddle pools on Mainnet (#450)
## v16.57.3 - _May 10, 2022_
* Fix a runtime error related to BalancerV2SwapInfoCache (#472)
## v16.57.2 - _May 2, 2022_
* Fix missing AMM quotes on indicative Quote Reports (#466)
## v16.57.1 - _Invalid date_
* Added QUICK/ANY pair on Polygon (#464)
* Added cvxFXS/FXS curve pool on mainnet (#465)
## v16.57.0 - _April 22, 2022_
* Add BalancerV2 batch swap support (#462)
## v16.56.0 - _April 21, 2022_
* Add estimatedGas to ExtendedQuoteReport (#463)
## v16.55.0 - _April 7, 2022_
* Fix fillRfqOrder VIP being used for swaps that need transformERC20 (#461)
## v16.54.0 - _April 6, 2022_
* Add true VIP support for eligible RFQt swaps (#458)
## v16.53.0 - _March 31, 2022_
* Adds support for STG/USDC pool on Curve Mainnet (#451)
* Use neon-router in asset-swapper tests (#453)
* Add sampler blocknumber to quote report data (#448)
## v16.52.0 - _Invalid date_
* Adds support for mobius money on celo (#423)
## v16.51.0 - _March 10, 2022_
* Added `Curve` `YFI-ETH` pool (#444)

View File

@@ -6,7 +6,7 @@
"shouldSaveStandardInput": true,
"compilerSettings": {
"evmVersion": "istanbul",
"optimizer": { "enabled": true, "runs": 200, "details": { "yul": true, "deduplicate": true } },
"optimizer": { "enabled": true, "runs": 200, "details": { "yul": false, "deduplicate": true } },
"outputSelection": {
"*": {
"*": [

View File

@@ -1,148 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
contract ApproximateBuys {
/// @dev Information computing buy quotes for sources that do not have native
/// buy quote support.
struct ApproximateBuyQuoteOpts {
// Arbitrary maker token data to pass to `getSellQuoteCallback`.
bytes makerTokenData;
// Arbitrary taker token data to pass to `getSellQuoteCallback`.
bytes takerTokenData;
// Callback to retrieve a sell quote.
function (bytes memory, bytes memory, uint256)
internal
view
returns (uint256) getSellQuoteCallback;
}
uint256 private constant ONE_HUNDED_PERCENT_BPS = 1e4;
/// @dev Maximum approximate (positive) error rate when approximating a buy quote.
uint256 private constant APPROXIMATE_BUY_TARGET_EPSILON_BPS = 0.0005e4;
/// @dev Maximum iterations to perform when approximating a buy quote.
uint256 private constant APPROXIMATE_BUY_MAX_ITERATIONS = 5;
function _sampleApproximateBuys(
ApproximateBuyQuoteOpts memory opts,
uint256[] memory makerTokenAmounts
)
internal
view
returns (uint256[] memory takerTokenAmounts)
{
takerTokenAmounts = new uint256[](makerTokenAmounts.length);
if (makerTokenAmounts.length == 0) {
return takerTokenAmounts;
}
uint256 sellAmount = opts.getSellQuoteCallback(
opts.makerTokenData,
opts.takerTokenData,
makerTokenAmounts[0]
);
if (sellAmount == 0) {
return takerTokenAmounts;
}
uint256 buyAmount = opts.getSellQuoteCallback(
opts.takerTokenData,
opts.makerTokenData,
sellAmount
);
if (buyAmount == 0) {
return takerTokenAmounts;
}
for (uint256 i = 0; i < makerTokenAmounts.length; i++) {
uint256 eps = 0;
for (uint256 iter = 0; iter < APPROXIMATE_BUY_MAX_ITERATIONS; iter++) {
// adjustedSellAmount = previousSellAmount * (target/actual) * JUMP_MULTIPLIER
sellAmount = _safeGetPartialAmountCeil(
makerTokenAmounts[i],
buyAmount,
sellAmount
);
if (sellAmount == 0) {
break;
}
sellAmount = _safeGetPartialAmountCeil(
(ONE_HUNDED_PERCENT_BPS + APPROXIMATE_BUY_TARGET_EPSILON_BPS),
ONE_HUNDED_PERCENT_BPS,
sellAmount
);
if (sellAmount == 0) {
break;
}
uint256 _buyAmount = opts.getSellQuoteCallback(
opts.takerTokenData,
opts.makerTokenData,
sellAmount
);
if (_buyAmount == 0) {
break;
}
// We re-use buyAmount next iteration, only assign if it is
// non zero
buyAmount = _buyAmount;
// If we've reached our goal, exit early
if (buyAmount >= makerTokenAmounts[i]) {
eps =
(buyAmount - makerTokenAmounts[i]) * ONE_HUNDED_PERCENT_BPS /
makerTokenAmounts[i];
if (eps <= APPROXIMATE_BUY_TARGET_EPSILON_BPS) {
break;
}
}
}
if (eps == 0 || eps > APPROXIMATE_BUY_TARGET_EPSILON_BPS) {
break;
}
// We do our best to close in on the requested amount, but we can either over buy or under buy and exit
// if we hit a max iteration limit
// We scale the sell amount to get the approximate target
takerTokenAmounts[i] = _safeGetPartialAmountCeil(
makerTokenAmounts[i],
buyAmount,
sellAmount
);
}
}
function _safeGetPartialAmountCeil(
uint256 numerator,
uint256 denominator,
uint256 target
)
internal
view
returns (uint256 partialAmount)
{
if (numerator == 0 || target == 0 || denominator == 0) return 0;
uint256 c = numerator * target;
if (c / numerator != target) return 0;
return (c + (denominator - 1)) / denominator;
}
}

View File

@@ -1,197 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IBalancer.sol";
contract BalancerSampler {
/// @dev Base gas limit for Balancer calls.
uint256 constant private BALANCER_CALL_GAS = 300e3; // 300k
// Balancer math constants
// https://github.com/balancer-labs/balancer-core/blob/master/contracts/BConst.sol
uint256 constant private BONE = 10 ** 18;
uint256 constant private MAX_IN_RATIO = BONE / 2;
uint256 constant private MAX_OUT_RATIO = (BONE / 3) + 1 wei;
struct BalancerState {
uint256 takerTokenBalance;
uint256 makerTokenBalance;
uint256 takerTokenWeight;
uint256 makerTokenWeight;
uint256 swapFee;
}
/// @dev Sample sell quotes from Balancer.
/// @param poolAddress Address of the Balancer pool to query.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromBalancer(
address poolAddress,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
IBalancer pool = IBalancer(poolAddress);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
if (!pool.isBound(takerToken) || !pool.isBound(makerToken)) {
return makerTokenAmounts;
}
BalancerState memory poolState;
poolState.takerTokenBalance = pool.getBalance(takerToken);
poolState.makerTokenBalance = pool.getBalance(makerToken);
poolState.takerTokenWeight = pool.getDenormalizedWeight(takerToken);
poolState.makerTokenWeight = pool.getDenormalizedWeight(makerToken);
poolState.swapFee = pool.getSwapFee();
for (uint256 i = 0; i < numSamples; i++) {
// Handles this revert scenario:
// https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol#L443
if (takerTokenAmounts[i] > _bmul(poolState.takerTokenBalance, MAX_IN_RATIO)) {
break;
}
try
pool.calcOutGivenIn
{gas: BALANCER_CALL_GAS}
(
poolState.takerTokenBalance,
poolState.takerTokenWeight,
poolState.makerTokenBalance,
poolState.makerTokenWeight,
takerTokenAmounts[i],
poolState.swapFee
)
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
/// @dev Sample buy quotes from Balancer.
/// @param poolAddress Address of the Balancer pool to query.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromBalancer(
address poolAddress,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
IBalancer pool = IBalancer(poolAddress);
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
if (!pool.isBound(takerToken) || !pool.isBound(makerToken)) {
return takerTokenAmounts;
}
BalancerState memory poolState;
poolState.takerTokenBalance = pool.getBalance(takerToken);
poolState.makerTokenBalance = pool.getBalance(makerToken);
poolState.takerTokenWeight = pool.getDenormalizedWeight(takerToken);
poolState.makerTokenWeight = pool.getDenormalizedWeight(makerToken);
poolState.swapFee = pool.getSwapFee();
for (uint256 i = 0; i < numSamples; i++) {
// Handles this revert scenario:
// https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol#L505
if (makerTokenAmounts[i] > _bmul(poolState.makerTokenBalance, MAX_OUT_RATIO)) {
break;
}
try
pool.calcInGivenOut
{gas: BALANCER_CALL_GAS}
(
poolState.takerTokenBalance,
poolState.takerTokenWeight,
poolState.makerTokenBalance,
poolState.makerTokenWeight,
makerTokenAmounts[i],
poolState.swapFee
)
returns (uint256 amount)
{
// Handles this revert scenario:
// https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol#L443
if (amount > _bmul(poolState.takerTokenBalance, MAX_IN_RATIO)) {
break;
}
takerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (takerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
/// @dev Hacked version of Balancer's `bmul` function, returning 0 instead
/// of reverting.
/// https://github.com/balancer-labs/balancer-core/blob/master/contracts/BNum.sol#L63-L73
/// @param a The first operand.
/// @param b The second operand.
/// @param c The result of the multiplication, or 0 if `bmul` would've reverted.
function _bmul(uint256 a, uint256 b)
private
pure
returns (uint256 c)
{
uint c0 = a * b;
if (a != 0 && c0 / a != b) {
return 0;
}
uint c1 = c0 + (BONE / 2);
if (c1 < c0) {
return 0;
}
uint c2 = c1 / BONE;
return c2;
}
}

View File

@@ -0,0 +1,105 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IBalancerV2Vault.sol";
import "./BalancerV2Common.sol";
contract BalancerV2BatchSampler is BalancerV2Common {
// Replaces amount for first step with each takerTokenAmount and calls queryBatchSwap using supplied steps
/// @dev Sample sell quotes from Balancer V2 supporting multihops.
/// @param swapSteps Array of swap steps (can be >= 1).
/// @param swapAssets Array of token address for swaps.
/// @param takerTokenAmounts Taker token sell amount for each sample.
function sampleMultihopSellsFromBalancerV2(
IBalancerV2Vault vault,
IBalancerV2Vault.BatchSwapStep[] memory swapSteps,
address[] memory swapAssets,
uint256[] memory takerTokenAmounts
)
public
returns (uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
IBalancerV2Vault.FundManagement memory swapFunds =
_createSwapFunds();
for (uint256 i = 0; i < numSamples; i++) {
swapSteps[0].amount = takerTokenAmounts[i];
try
// For sells we specify the takerToken which is what the vault will receive from the trade
vault.queryBatchSwap(IBalancerV2Vault.SwapKind.GIVEN_IN, swapSteps, swapAssets, swapFunds)
// amounts represent pool balance deltas from the swap (incoming balance, outgoing balance)
returns (int256[] memory amounts) {
// Outgoing balance is negative so we need to flip the sign
// Note - queryBatchSwap will return a delta for each token in the assets array and last asset should be tokenOut
int256 amountOutFromPool = amounts[amounts.length - 1] * -1;
if (amountOutFromPool <= 0) {
break;
}
makerTokenAmounts[i] = uint256(amountOutFromPool);
} catch {
// Swallow failures, leaving all results as zero.
break;
}
}
}
// Replaces amount for first step with each makerTokenAmount and calls queryBatchSwap using supplied steps
/// @dev Sample buy quotes from Balancer V2 supporting multihops.
/// @param swapSteps Array of swap steps (can be >= 1).
/// @param swapAssets Array of token address for swaps.
/// @param makerTokenAmounts Maker token buy amount for each sample.
function sampleMultihopBuysFromBalancerV2(
IBalancerV2Vault vault,
IBalancerV2Vault.BatchSwapStep[] memory swapSteps,
address[] memory swapAssets,
uint256[] memory makerTokenAmounts
)
public
returns (uint256[] memory takerTokenAmounts)
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
IBalancerV2Vault.FundManagement memory swapFunds =
_createSwapFunds();
for (uint256 i = 0; i < numSamples; i++) {
swapSteps[0].amount = makerTokenAmounts[i];
try
// Uses GIVEN_OUT type for Buy
vault.queryBatchSwap(IBalancerV2Vault.SwapKind.GIVEN_OUT, swapSteps, swapAssets, swapFunds)
// amounts represent pool balance deltas from the swap (incoming balance, outgoing balance)
returns (int256[] memory amounts) {
int256 amountIntoPool = amounts[0];
if (amountIntoPool <= 0) {
break;
}
takerTokenAmounts[i] = uint256(amountIntoPool);
} catch {
// Swallow failures, leaving all results as zero.
break;
}
}
}
}

View File

@@ -18,28 +18,24 @@
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IBalancerV2Vault.sol";
interface ISmoothy {
contract BalancerV2Common {
function getBalance (
uint256 tid
)
external
function _createSwapFunds()
internal
view
returns (uint256 balance);
function _yBalances (
uint256 tid
)
external
view
returns (uint256 balance);
function getTokenStats (
uint256 tid
)
external
view
returns (uint256 softWeight, uint256 hardWeight, uint256 balance, uint256 decimals);
returns (IBalancerV2Vault.FundManagement memory)
{
return
IBalancerV2Vault.FundManagement({
sender: address(this),
fromInternalBalance: false,
recipient: payable(address(this)),
toInternalBalance: false
});
}
}

View File

@@ -1,189 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./SamplerUtils.sol";
/// @dev Minimal Balancer V2 Vault interface
/// for documentation refer to https://github.com/balancer-labs/balancer-core-v2/blob/master/contracts/vault/interfaces/IVault.sol
interface IBalancerV2Vault {
enum SwapKind { GIVEN_IN, GIVEN_OUT }
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
function queryBatchSwap(
SwapKind kind,
BatchSwapStep[] calldata swaps,
IAsset[] calldata assets,
FundManagement calldata funds
) external returns (int256[] memory assetDeltas);
}
interface IAsset {
// solhint-disable-previous-line no-empty-blocks
}
contract BalancerV2Sampler is SamplerUtils {
struct BalancerV2PoolInfo {
bytes32 poolId;
address vault;
}
/// @dev Sample sell quotes from Balancer V2.
/// @param poolInfo Struct with pool related data
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromBalancerV2(
BalancerV2PoolInfo memory poolInfo,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
returns (uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
IBalancerV2Vault vault = IBalancerV2Vault(poolInfo.vault);
IAsset[] memory swapAssets = new IAsset[](2);
swapAssets[0] = IAsset(takerToken);
swapAssets[1] = IAsset(makerToken);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
IBalancerV2Vault.FundManagement memory swapFunds =
_createSwapFunds();
for (uint256 i = 0; i < numSamples; i++) {
IBalancerV2Vault.BatchSwapStep[] memory swapSteps =
_createSwapSteps(poolInfo, takerTokenAmounts[i]);
try
// For sells we specify the takerToken which is what the vault will receive from the trade
vault.queryBatchSwap(IBalancerV2Vault.SwapKind.GIVEN_IN, swapSteps, swapAssets, swapFunds)
// amounts represent pool balance deltas from the swap (incoming balance, outgoing balance)
returns (int256[] memory amounts) {
// Outgoing balance is negative so we need to flip the sign
int256 amountOutFromPool = amounts[1] * -1;
if (amountOutFromPool <= 0) {
break;
}
makerTokenAmounts[i] = uint256(amountOutFromPool);
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
/// @dev Sample buy quotes from Balancer V2.
/// @param poolInfo Struct with pool related data
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromBalancerV2(
BalancerV2PoolInfo memory poolInfo,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
returns (uint256[] memory takerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
IBalancerV2Vault vault = IBalancerV2Vault(poolInfo.vault);
IAsset[] memory swapAssets = new IAsset[](2);
swapAssets[0] = IAsset(takerToken);
swapAssets[1] = IAsset(makerToken);
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
IBalancerV2Vault.FundManagement memory swapFunds =
_createSwapFunds();
for (uint256 i = 0; i < numSamples; i++) {
IBalancerV2Vault.BatchSwapStep[] memory swapSteps =
_createSwapSteps(poolInfo, makerTokenAmounts[i]);
try
// For buys we specify the makerToken which is what taker will receive from the trade
vault.queryBatchSwap(IBalancerV2Vault.SwapKind.GIVEN_OUT, swapSteps, swapAssets, swapFunds)
returns (int256[] memory amounts) {
int256 amountIntoPool = amounts[0];
if (amountIntoPool <= 0) {
break;
}
takerTokenAmounts[i] = uint256(amountIntoPool);
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
function _createSwapSteps(
BalancerV2PoolInfo memory poolInfo,
uint256 amount
) private pure returns (IBalancerV2Vault.BatchSwapStep[] memory) {
IBalancerV2Vault.BatchSwapStep[] memory swapSteps =
new IBalancerV2Vault.BatchSwapStep[](1);
swapSteps[0] = IBalancerV2Vault.BatchSwapStep({
poolId: poolInfo.poolId,
assetInIndex: 0,
assetOutIndex: 1,
amount: amount,
userData: ""
});
return swapSteps;
}
function _createSwapFunds()
private
view
returns (IBalancerV2Vault.FundManagement memory)
{
return
IBalancerV2Vault.FundManagement({
sender: address(this),
fromInternalBalance: false,
recipient: payable(address(this)),
toInternalBalance: false
});
}
}

View File

@@ -1,142 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IBancor.sol";
contract CompilerHack {}
contract BancorSampler is CompilerHack {
/// @dev Base gas limit for Bancor calls.
uint256 constant private BANCOR_CALL_GAS = 300e3; // 300k
struct BancorSamplerOpts {
IBancorRegistry registry;
address[][] paths;
}
/// @dev Sample sell quotes from Bancor.
/// @param opts BancorSamplerOpts The Bancor registry contract address and paths
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return bancorNetwork the Bancor Network address
/// @return path the selected conversion path from bancor
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromBancor(
BancorSamplerOpts memory opts,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (address bancorNetwork, address[] memory path, uint256[] memory makerTokenAmounts)
{
if (opts.paths.length == 0) {
return (bancorNetwork, path, makerTokenAmounts);
}
(bancorNetwork, path) = _findBestPath(opts, takerToken, makerToken, takerTokenAmounts);
makerTokenAmounts = new uint256[](takerTokenAmounts.length);
for (uint256 i = 0; i < makerTokenAmounts.length; i++) {
try
IBancorNetwork(bancorNetwork)
.rateByPath
{gas: BANCOR_CALL_GAS}
(path, takerTokenAmounts[i])
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch {
// Swallow failures, leaving all results as zero.
break;
}
}
return (bancorNetwork, path, makerTokenAmounts);
}
/// @dev Sample buy quotes from Bancor. Unimplemented
/// @param opts BancorSamplerOpts The Bancor registry contract address and paths
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return bancorNetwork the Bancor Network address
/// @return path the selected conversion path from bancor
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromBancor(
BancorSamplerOpts memory opts,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (address bancorNetwork, address[] memory path, uint256[] memory takerTokenAmounts)
{
}
function _findBestPath(
BancorSamplerOpts memory opts,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
internal
view
returns (address bancorNetwork, address[] memory path)
{
bancorNetwork = opts.registry.getAddress(opts.registry.BANCOR_NETWORK());
if (opts.paths.length == 0) {
return (bancorNetwork, path);
}
uint256 maxBoughtAmount = 0;
// Find the best path by selling the largest taker amount
for (uint256 i = 0; i < opts.paths.length; i++) {
if (opts.paths[i].length < 2) {
continue;
}
try
IBancorNetwork(bancorNetwork)
.rateByPath
{gas: BANCOR_CALL_GAS}
(opts.paths[i], takerTokenAmounts[takerTokenAmounts.length-1])
returns (uint256 amount)
{
if (amount > maxBoughtAmount) {
maxBoughtAmount = amount;
path = opts.paths[i];
}
} catch {
// Swallow failures, leaving all results as zero.
continue;
}
}
}
}

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
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.
@@ -20,21 +20,25 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IUniswapV2Router01.sol";
import "./interfaces/IBancorV3.sol";
contract UniswapV2Sampler
contract BancorV3Sampler
{
/// @dev Gas limit for UniswapV2 calls.
uint256 constant private UNISWAPV2_CALL_GAS = 150e3; // 150k
/// @dev Gas limit for BancorV3 calls.
uint256 constant private BancorV3_CALL_GAS = 150e3; // 150k
/// @dev Sample sell quotes from UniswapV2.
address constant public ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev Sample sell quotes from BancorV3.
/// @param weth The WETH contract address
/// @param router Router to look up tokens and amounts
/// @param path Token route. Should be takerToken -> makerToken
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromUniswapV2(
function sampleSellsFromBancorV3(
address weth,
address router,
address[] memory path,
uint256[] memory takerTokenAmounts
@@ -45,14 +49,20 @@ contract UniswapV2Sampler
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
if(path[0] == weth){
path[0] = ETH;
}
if(path[1] == weth){
path[1] = ETH;
}
for (uint256 i = 0; i < numSamples; i++) {
try
IUniswapV2Router01(router).getAmountsOut
{gas: UNISWAPV2_CALL_GAS}
(takerTokenAmounts[i], path)
returns (uint256[] memory amounts)
IBancorV3(router).tradeOutputBySourceAmount(path[0], path[1], takerTokenAmounts[i])
returns (uint256 amount)
{
makerTokenAmounts[i] = amounts[path.length - 1];
makerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
@@ -64,13 +74,15 @@ contract UniswapV2Sampler
}
}
/// @dev Sample buy quotes from UniswapV2.
/// @dev Sample buy quotes from BancorV3.
/// @param weth The WETH contract address
/// @param router Router to look up tokens and amounts
/// @param path Token route. Should be takerToken -> makerToken.
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromUniswapV2(
function sampleBuysFromBancorV3(
address weth,
address router,
address[] memory path,
uint256[] memory makerTokenAmounts
@@ -81,14 +93,20 @@ contract UniswapV2Sampler
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
if(path[0] == weth){
path[0] = ETH;
}
if(path[1] == weth){
path[1] = ETH;
}
for (uint256 i = 0; i < numSamples; i++) {
try
IUniswapV2Router01(router).getAmountsIn
{gas: UNISWAPV2_CALL_GAS}
(makerTokenAmounts[i], path)
returns (uint256[] memory amounts)
IBancorV3(router).tradeInputByTargetAmount(path[0], path[1], makerTokenAmounts[i])
returns (uint256 amount)
{
takerTokenAmounts[i] = amounts[0];
takerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (takerTokenAmounts[i] == 0) {
break;
@@ -99,4 +117,4 @@ contract UniswapV2Sampler
}
}
}
}
}

View File

@@ -1,96 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./SamplerUtils.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
// Minimal CToken interface
interface ICToken {
function mint(uint mintAmount) external returns (uint);
function redeem(uint redeemTokens) external returns (uint);
function redeemUnderlying(uint redeemAmount) external returns (uint);
function exchangeRateStored() external view returns (uint);
function decimals() external view returns (uint8);
}
contract CompoundSampler is SamplerUtils {
uint256 constant private EXCHANGE_RATE_SCALE = 1e10;
function sampleSellsFromCompound(
ICToken cToken,
IERC20TokenV06 takerToken,
IERC20TokenV06 makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
// Exchange rate is scaled by 1 * 10^(18 - 8 + Underlying Token Decimals
uint256 exchangeRate = cToken.exchangeRateStored();
uint256 cTokenDecimals = uint256(cToken.decimals());
if (address(makerToken) == address(cToken)) {
// mint
for (uint256 i = 0; i < numSamples; i++) {
makerTokenAmounts[i] = (takerTokenAmounts[i] * EXCHANGE_RATE_SCALE * 10 ** cTokenDecimals) / exchangeRate;
}
} else if (address(takerToken) == address(cToken)) {
// redeem
for (uint256 i = 0; i < numSamples; i++) {
makerTokenAmounts[i] = (takerTokenAmounts[i] * exchangeRate) / (EXCHANGE_RATE_SCALE * 10 ** cTokenDecimals);
}
}
}
function sampleBuysFromCompound(
ICToken cToken,
IERC20TokenV06 takerToken,
IERC20TokenV06 makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
// Exchange rate is scaled by 1 * 10^(18 - 8 + Underlying Token Decimals
uint256 exchangeRate = cToken.exchangeRateStored();
uint256 cTokenDecimals = uint256(cToken.decimals());
if (address(makerToken) == address(cToken)) {
// mint
for (uint256 i = 0; i < numSamples; i++) {
takerTokenAmounts[i] = makerTokenAmounts[i] * exchangeRate / (EXCHANGE_RATE_SCALE * 10 ** cTokenDecimals);
}
} else if (address(takerToken) == address(cToken)) {
// redeem
for (uint256 i = 0; i < numSamples; i++) {
takerTokenAmounts[i] = (makerTokenAmounts[i] * EXCHANGE_RATE_SCALE * 10 ** cTokenDecimals)/exchangeRate;
}
}
}
}

View File

@@ -1,161 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/ICurve.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
contract CurveSampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Information for sampling from curve sources.
struct CurveInfo {
address poolAddress;
bytes4 sellQuoteFunctionSelector;
bytes4 buyQuoteFunctionSelector;
}
/// @dev Base gas limit for Curve calls. Some Curves have multiple tokens
/// So a reasonable ceil is 150k per token. Biggest Curve has 4 tokens.
uint256 constant private CURVE_CALL_GAS = 2000e3; // Was 600k for Curve but SnowSwap is using 1500k+
/// @dev Sample sell quotes from Curve.
/// @param curveInfo Curve information specific to this token pair.
/// @param fromTokenIdx Index of the taker token (what to sell).
/// @param toTokenIdx Index of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromCurve(
CurveInfo memory curveInfo,
int128 fromTokenIdx,
int128 toTokenIdx,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
curveInfo.poolAddress.staticcall.gas(CURVE_CALL_GAS)(
abi.encodeWithSelector(
curveInfo.sellQuoteFunctionSelector,
fromTokenIdx,
toTokenIdx,
takerTokenAmounts[i]
));
uint256 buyAmount = 0;
if (didSucceed) {
buyAmount = abi.decode(resultData, (uint256));
}
makerTokenAmounts[i] = buyAmount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from Curve.
/// @param curveInfo Curve information specific to this token pair.
/// @param fromTokenIdx Index of the taker token (what to sell).
/// @param toTokenIdx Index of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromCurve(
CurveInfo memory curveInfo,
int128 fromTokenIdx,
int128 toTokenIdx,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
if (curveInfo.buyQuoteFunctionSelector == bytes4(0)) {
// Buys not supported on this curve, so approximate it.
return _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(toTokenIdx, curveInfo),
takerTokenData: abi.encode(fromTokenIdx, curveInfo),
getSellQuoteCallback: _sampleSellForApproximateBuyFromCurve
}),
makerTokenAmounts
);
}
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
curveInfo.poolAddress.staticcall.gas(CURVE_CALL_GAS)(
abi.encodeWithSelector(
curveInfo.buyQuoteFunctionSelector,
fromTokenIdx,
toTokenIdx,
makerTokenAmounts[i]
));
uint256 sellAmount = 0;
if (didSucceed) {
sellAmount = abi.decode(resultData, (uint256));
}
takerTokenAmounts[i] = sellAmount;
// Break early if there are 0 amounts
if (takerTokenAmounts[i] == 0) {
break;
}
}
}
function _sampleSellForApproximateBuyFromCurve(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(int128 takerTokenIdx, CurveInfo memory curveInfo) =
abi.decode(takerTokenData, (int128, CurveInfo));
(int128 makerTokenIdx) =
abi.decode(makerTokenData, (int128));
(bool success, bytes memory resultData) =
address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromCurve.selector,
curveInfo,
takerTokenIdx,
makerTokenIdx,
_toSingleValueArray(sellAmount)
));
if (!success) {
return 0;
}
// solhint-disable-next-line indent
return abi.decode(resultData, (uint256[]))[0];
}
}

View File

@@ -1,211 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
interface IDODOZoo {
function getDODO(address baseToken, address quoteToken) external view returns (address);
}
interface IDODOHelper {
function querySellQuoteToken(address dodo, uint256 amount) external view returns (uint256);
}
interface IDODO {
function querySellBaseToken(uint256 amount) external view returns (uint256);
function _TRADE_ALLOWED_() external view returns (bool);
}
contract DODOSampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Gas limit for DODO calls.
uint256 constant private DODO_CALL_GAS = 300e3; // 300k
struct DODOSamplerOpts {
address registry;
address helper;
}
/// @dev Sample sell quotes from DODO.
/// @param opts DODOSamplerOpts DODO Registry and helper addresses
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return sellBase whether the bridge needs to sell the base token
/// @return pool the DODO pool address
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromDODO(
DODOSamplerOpts memory opts,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (bool sellBase, address pool, uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
pool = IDODOZoo(opts.registry).getDODO(takerToken, makerToken);
address baseToken;
// If pool exists we have the correct order of Base/Quote
if (pool != address(0)) {
baseToken = takerToken;
sellBase = true;
} else {
pool = IDODOZoo(opts.registry).getDODO(makerToken, takerToken);
// No pool either direction
if (address(pool) == address(0)) {
return (sellBase, pool, makerTokenAmounts);
}
baseToken = makerToken;
sellBase = false;
}
// DODO Pool has been disabled
if (!IDODO(pool)._TRADE_ALLOWED_()) {
return (sellBase, pool, makerTokenAmounts);
}
for (uint256 i = 0; i < numSamples; i++) {
uint256 buyAmount = _sampleSellForApproximateBuyFromDODO(
abi.encode(takerToken, pool, baseToken, opts.helper), // taker token data
abi.encode(makerToken, pool, baseToken, opts.helper), // maker token data
takerTokenAmounts[i]
);
makerTokenAmounts[i] = buyAmount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from DODO.
/// @param opts DODOSamplerOpts DODO Registry and helper addresses
/// @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.
/// @return sellBase whether the bridge needs to sell the base token
/// @return pool the DODO pool address
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromDODO(
DODOSamplerOpts memory opts,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (bool sellBase, address pool, uint256[] memory takerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
// Pool is BASE/QUOTE
// Look up the pool from the taker/maker combination
pool = IDODOZoo(opts.registry).getDODO(takerToken, makerToken);
address baseToken;
// If pool exists we have the correct order of Base/Quote
if (pool != address(0)) {
baseToken = takerToken;
sellBase = true;
} else {
// Look up the pool from the maker/taker combination
pool = IDODOZoo(opts.registry).getDODO(makerToken, takerToken);
// No pool either direction
if (address(pool) == address(0)) {
return (sellBase, pool, takerTokenAmounts);
}
baseToken = makerToken;
sellBase = false;
}
// DODO Pool has been disabled
if (!IDODO(pool)._TRADE_ALLOWED_()) {
return (sellBase, pool, takerTokenAmounts);
}
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(makerToken, pool, baseToken, opts.helper),
takerTokenData: abi.encode(takerToken, pool, baseToken, opts.helper),
getSellQuoteCallback: _sampleSellForApproximateBuyFromDODO
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromDODO(
bytes memory takerTokenData,
bytes memory /* makerTokenData */,
uint256 sellAmount
)
private
view
returns (uint256)
{
(address takerToken, address pool, address baseToken, address helper) = abi.decode(
takerTokenData,
(address, address, address, address)
);
// We will get called to sell both the taker token and also to sell the maker token
if (takerToken == baseToken) {
// If base token then use the original query on the pool
try
IDODO(pool).querySellBaseToken
{gas: DODO_CALL_GAS}
(sellAmount)
returns (uint256 amount)
{
return amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
} else {
// If quote token then use helper, this is less accurate
try
IDODOHelper(helper).querySellQuoteToken
{gas: DODO_CALL_GAS}
(pool, sellAmount)
returns (uint256 amount)
{
return amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
}
}

View File

@@ -1,204 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
interface IDODOV2Registry {
function getDODOPool(address baseToken, address quoteToken)
external
view
returns (address[] memory machines);
}
interface IDODOV2Pool {
function querySellBase(address trader, uint256 payBaseAmount)
external
view
returns (uint256 receiveQuoteAmount, uint256 mtFee);
function querySellQuote(address trader, uint256 payQuoteAmount)
external
view
returns (uint256 receiveBaseAmount, uint256 mtFee);
}
contract DODOV2Sampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Gas limit for DODO V2 calls.
uint256 constant private DODO_V2_CALL_GAS = 300e3; // 300k
/// @dev Sample sell quotes from DODO V2.
/// @param registry Address of the registry to look up.
/// @param offset offset index for the pool in the registry.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return sellBase whether the bridge needs to sell the base token
/// @return pool the DODO pool address
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromDODOV2(
address registry,
uint256 offset,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (bool sellBase, address pool, uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
(pool, sellBase) = _getNextDODOV2Pool(registry, offset, takerToken, makerToken);
if (pool == address(0)) {
return (sellBase, pool, makerTokenAmounts);
}
for (uint256 i = 0; i < numSamples; i++) {
uint256 buyAmount = _sampleSellForApproximateBuyFromDODOV2(
abi.encode(takerToken, pool, sellBase), // taker token data
abi.encode(makerToken, pool, sellBase), // maker token data
takerTokenAmounts[i]
);
makerTokenAmounts[i] = buyAmount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from DODO.
/// @param registry Address of the registry to look up.
/// @param offset offset index for the pool in the registry.
/// @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.
/// @return sellBase whether the bridge needs to sell the base token
/// @return pool the DODO pool address
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromDODOV2(
address registry,
uint256 offset,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (bool sellBase, address pool, uint256[] memory takerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
(pool, sellBase) = _getNextDODOV2Pool(registry, offset, takerToken, makerToken);
if (pool == address(0)) {
return (sellBase, pool, takerTokenAmounts);
}
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(makerToken, pool, !sellBase),
takerTokenData: abi.encode(takerToken, pool, sellBase),
getSellQuoteCallback: _sampleSellForApproximateBuyFromDODOV2
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromDODOV2(
bytes memory takerTokenData,
bytes memory /* makerTokenData */,
uint256 sellAmount
)
private
view
returns (uint256)
{
(address takerToken, address pool, bool sellBase) = abi.decode(
takerTokenData,
(address, address, bool)
);
// We will get called to sell both the taker token and also to sell the maker token
// since we use approximate buy for sell and buy functions
if (sellBase) {
try
IDODOV2Pool(pool).querySellBase
{ gas: DODO_V2_CALL_GAS }
(address(0), sellAmount)
returns (uint256 amount, uint256)
{
return amount;
} catch {
return 0;
}
} else {
try
IDODOV2Pool(pool).querySellQuote
{ gas: DODO_V2_CALL_GAS }
(address(0), sellAmount)
returns (uint256 amount, uint256)
{
return amount;
} catch {
return 0;
}
}
}
function _getNextDODOV2Pool(
address registry,
uint256 offset,
address takerToken,
address makerToken
)
internal
view
returns (address machine, bool sellBase)
{
// Query in base -> quote direction, if a pool is found then we are selling the base
address[] memory machines = IDODOV2Registry(registry).getDODOPool(takerToken, makerToken);
sellBase = true;
if (machines.length == 0) {
// Query in quote -> base direction, if a pool is found then we are selling the quote
machines = IDODOV2Registry(registry).getDODOPool(makerToken, takerToken);
sellBase = false;
}
if (offset >= machines.length) {
return (address(0), false);
}
machine = machines[offset];
}
}

View File

@@ -22,52 +22,58 @@ pragma experimental ABIEncoderV2;
import "./BalancerSampler.sol";
import "./BalancerV2Sampler.sol";
import "./BalancerV2BatchSampler.sol";
import "./BancorSampler.sol";
import "./BancorV3Sampler.sol";
import "./CompoundSampler.sol";
import "./CurveSampler.sol";
import "./DODOSampler.sol";
import "./DODOV2Sampler.sol";
import "./KyberSampler.sol";
import "./GMXSampler.sol";
import "./KyberDmmSampler.sol";
import "./LidoSampler.sol";
import "./LiquidityProviderSampler.sol";
import "./MakerPSMSampler.sol";
import "./MultiBridgeSampler.sol";
import "./MStableSampler.sol";
import "./MooniswapSampler.sol";
import "./NativeOrderSampler.sol";
import "./PlatypusSampler.sol";
import "./ShellSampler.sol";
import "./SmoothySampler.sol";
import "./TwoHopSampler.sol";
import "./UniswapSampler.sol";
import "./UniswapV2Sampler.sol";
import "./UniswapV3Sampler.sol";
import "./VelodromeSampler.sol";
import "./UtilitySampler.sol";
contract ERC20BridgeSampler is
BalancerSampler,
BalancerV2Sampler,
BalancerV2BatchSampler,
BancorSampler,
BancorV3Sampler,
CompoundSampler,
CurveSampler,
DODOSampler,
DODOV2Sampler,
KyberSampler,
GMXSampler,
KyberDmmSampler,
LidoSampler,
LiquidityProviderSampler,
MakerPSMSampler,
MStableSampler,
MooniswapSampler,
MultiBridgeSampler,
NativeOrderSampler,
PlatypusSampler,
ShellSampler,
SmoothySampler,
TwoHopSampler,
UniswapSampler,
UniswapV2Sampler,
UniswapV3Sampler,
VelodromeSampler,
UtilitySampler
{
@@ -92,4 +98,6 @@ contract ERC20BridgeSampler is
(callResults[i].success, callResults[i].data) = address(this).call(callDatas[i]);
}
}
receive() external payable {}
}

View File

@@ -0,0 +1,96 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IGMX.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
contract GMXSampler is
SamplerUtils,
ApproximateBuys
{
struct GMXInfo {
address reader;
address vault;
address[] path;
}
function sampleSellsFromGMX(
address reader,
address vault,
address[] memory path,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
try
IGMX(reader).getAmountOut(IVault(vault), path[0], path[1], takerTokenAmounts[i])
returns (uint256 amountAfterFees, uint256 feeAmount)
{
makerTokenAmounts[i] = amountAfterFees;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
function sampleBuysFromGMX(
address reader,
address vault,
address[] memory path,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
address[] memory invertBuyPath = new address[](2);
invertBuyPath[0] = path[1];
invertBuyPath[1] = path[0];
return _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(reader, vault, invertBuyPath),
takerTokenData: abi.encode(reader, vault, path),
getSellQuoteCallback: _sampleSellForApproximateBuyFromGMX
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromGMX(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(address _reader, address _vault, address[] memory _path ) = abi.decode(takerTokenData, (address, address, address[]));
(bool success, bytes memory resultData) = address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromGMX.selector,
_reader,
_vault,
_path,
_toSingleValueArray(sellAmount)
));
if(!success) {
return 0;
}
// solhint-disable-next-line indent
return abi.decode(resultData, (uint256[]))[0];
}
}

View File

@@ -1,179 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
interface IKyberDmmPool {
function totalSupply()
external
view
returns (uint256);
}
interface IKyberDmmFactory {
function getPools(address token0, address token1)
external
view
returns (address[] memory _tokenPools);
}
interface IKyberDmmRouter {
function factory() external view returns (address);
function getAmountsOut(uint256 amountIn, address[] calldata pools, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata pools, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}
contract KyberDmmSampler
{
/// @dev Gas limit for KyberDmm calls.
uint256 constant private KYBER_DMM_CALL_GAS = 150e3; // 150k
/// @dev Sample sell quotes from KyberDmm.
/// @param router Router to look up tokens and amounts
/// @param path Token route. Should be takerToken -> makerToken
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return pools The pool addresses involved in the multi path trade
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromKyberDmm(
address router,
address[] memory path,
uint256[] memory takerTokenAmounts
)
public
view
returns (address[] memory pools, uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
pools = _getKyberDmmPools(router, path);
if (pools.length == 0) {
return (pools, makerTokenAmounts);
}
for (uint256 i = 0; i < numSamples; i++) {
try
IKyberDmmRouter(router).getAmountsOut
{gas: KYBER_DMM_CALL_GAS}
(takerTokenAmounts[i], pools, path)
returns (uint256[] memory amounts)
{
makerTokenAmounts[i] = amounts[path.length - 1];
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
/// @dev Sample buy quotes from KyberDmm.
/// @param router Router to look up tokens and amounts
/// @param path Token route. Should be takerToken -> makerToken.
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return pools The pool addresses involved in the multi path trade
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromKyberDmm(
address router,
address[] memory path,
uint256[] memory makerTokenAmounts
)
public
view
returns (address[] memory pools, uint256[] memory takerTokenAmounts)
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
pools = _getKyberDmmPools(router, path);
if (pools.length == 0) {
return (pools, takerTokenAmounts);
}
for (uint256 i = 0; i < numSamples; i++) {
try
IKyberDmmRouter(router).getAmountsIn
{gas: KYBER_DMM_CALL_GAS}
(makerTokenAmounts[i], pools, path)
returns (uint256[] memory amounts)
{
takerTokenAmounts[i] = amounts[0];
// Break early if there are 0 amounts
if (takerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
function _getKyberDmmPools(
address router,
address[] memory path
)
private
view
returns (address[] memory pools)
{
IKyberDmmFactory factory = IKyberDmmFactory(IKyberDmmRouter(router).factory());
pools = new address[](path.length - 1);
for (uint256 i = 0; i < pools.length; i++) {
// find the best pool
address[] memory allPools;
try
factory.getPools
{gas: KYBER_DMM_CALL_GAS}
(path[i], path[i + 1])
returns (address[] memory allPools)
{
if (allPools.length == 0) {
return new address[](0);
}
uint256 maxSupply = 0;
for (uint256 j = 0; j < allPools.length; j++) {
uint256 totalSupply = IKyberDmmPool(allPools[j]).totalSupply();
if (totalSupply > maxSupply) {
maxSupply = totalSupply;
pools[i] = allPools[j];
}
}
} catch (bytes memory) {
return new address[](0);
}
}
}
}

View File

@@ -1,301 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IKyberNetwork.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
contract KyberSampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Gas limit for Kyber calls.
uint256 constant private KYBER_CALL_GAS = 500e3; // 500k
/// @dev Kyber ETH pseudo-address.
address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
struct KyberSamplerOpts {
uint256 reserveOffset;
address hintHandler;
address networkProxy;
address weth;
bytes hint;
}
/// @dev Sample sell quotes from Kyber.
/// @param opts KyberSamplerOpts The nth reserve
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return reserveId The id of the reserve found at reserveOffset
/// @return hint The hint for the selected reserve
/// @return makerTokenAmounts Maker amounts bought at each taker token amount.
function sampleSellsFromKyberNetwork(
KyberSamplerOpts memory opts,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (bytes32 reserveId, bytes memory hint, uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
reserveId = _getNextReserveId(opts, takerToken, makerToken);
if (reserveId == 0x0) {
return (reserveId, hint, makerTokenAmounts);
}
opts.hint = this.encodeKyberHint(opts, reserveId, takerToken, makerToken);
hint = opts.hint;
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
uint256 value = this.sampleSellFromKyberNetwork(
opts,
takerToken,
makerToken,
takerTokenAmounts[i]
);
makerTokenAmounts[i] = value;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from Kyber.
/// @param opts KyberSamplerOpts The nth reserve
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return reserveId The id of the reserve found at reserveOffset
/// @return hint The hint for the selected reserve
/// @return takerTokenAmounts Taker amounts sold at each maker token amount.
function sampleBuysFromKyberNetwork(
KyberSamplerOpts memory opts,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (bytes32 reserveId, bytes memory hint, uint256[] memory takerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
reserveId = _getNextReserveId(opts, takerToken, makerToken);
if (reserveId == 0x0) {
return (reserveId, hint, takerTokenAmounts);
}
opts.hint = this.encodeKyberHint(opts, reserveId, takerToken, makerToken);
hint = opts.hint;
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(makerToken, opts),
takerTokenData: abi.encode(takerToken, opts),
getSellQuoteCallback: _sampleSellForApproximateBuyFromKyber
}),
makerTokenAmounts
);
return (reserveId, hint, takerTokenAmounts);
}
function encodeKyberHint(
KyberSamplerOpts memory opts,
bytes32 reserveId,
address takerToken,
address makerToken
)
public
view
returns (bytes memory hint)
{
// Build a hint selecting the single reserve
IKyberHintHandler kyberHint = IKyberHintHandler(opts.hintHandler);
// All other reserves should be ignored with this hint
bytes32[] memory selectedReserves = new bytes32[](1);
selectedReserves[0] = reserveId;
uint256[] memory emptySplits = new uint256[](0);
if (takerToken == opts.weth) {
// ETH to Token
try
kyberHint.buildEthToTokenHint
{gas: KYBER_CALL_GAS}
(
makerToken,
IKyberHintHandler.TradeType.MaskIn,
selectedReserves,
emptySplits
)
returns (bytes memory result)
{
return result;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
}
} else if (makerToken == opts.weth) {
// Token to ETH
try
kyberHint.buildTokenToEthHint
{gas: KYBER_CALL_GAS}
(
takerToken,
IKyberHintHandler.TradeType.MaskIn,
selectedReserves,
emptySplits
)
returns (bytes memory result)
{
return result;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
}
} else {
// Token to Token
// We use the same reserve both ways
try
kyberHint.buildTokenToTokenHint
{gas: KYBER_CALL_GAS}
(
takerToken,
IKyberHintHandler.TradeType.MaskIn,
selectedReserves,
emptySplits,
makerToken,
IKyberHintHandler.TradeType.MaskIn,
selectedReserves,
emptySplits
)
returns (bytes memory result)
{
return result;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
}
}
}
function _sampleSellForApproximateBuyFromKyber(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256)
{
(address makerToken, KyberSamplerOpts memory opts) =
abi.decode(makerTokenData, (address, KyberSamplerOpts));
(address takerToken, ) =
abi.decode(takerTokenData, (address, KyberSamplerOpts));
try
this.sampleSellFromKyberNetwork
(opts, takerToken, makerToken, sellAmount)
returns (uint256 amount)
{
return amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
function sampleSellFromKyberNetwork(
KyberSamplerOpts memory opts,
address takerToken,
address makerToken,
uint256 takerTokenAmount
)
public
view
returns (uint256 makerTokenAmount)
{
// If there is no hint do not continue
if (opts.hint.length == 0) {
return 0;
}
try
IKyberNetworkProxy(opts.networkProxy).getExpectedRateAfterFee
{gas: KYBER_CALL_GAS}
(
takerToken == opts.weth ? KYBER_ETH_ADDRESS : takerToken,
makerToken == opts.weth ? KYBER_ETH_ADDRESS : makerToken,
takerTokenAmount,
0, // fee
opts.hint
)
returns (uint256 rate)
{
uint256 makerTokenDecimals = _getTokenDecimals(makerToken);
uint256 takerTokenDecimals = _getTokenDecimals(takerToken);
makerTokenAmount =
rate *
takerTokenAmount *
10 ** makerTokenDecimals /
10 ** takerTokenDecimals /
10 ** 18;
return makerTokenAmount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
function _getNextReserveId(
KyberSamplerOpts memory opts,
address takerToken,
address makerToken
)
internal
view
returns (bytes32 reserveId)
{
// Fetch the registered reserves for this pair
IKyberHintHandler kyberHint = IKyberHintHandler(opts.hintHandler);
(bytes32[] memory reserveIds, ,) = kyberHint.getTradingReserves(
takerToken == opts.weth ? KYBER_ETH_ADDRESS : takerToken,
makerToken == opts.weth ? KYBER_ETH_ADDRESS : makerToken,
true,
new bytes(0) // empty hint
);
if (opts.reserveOffset >= reserveIds.length) {
return 0x0;
}
reserveId = reserveIds[opts.reserveOffset];
// Ignore Kyber Bridged Reserves (0xbb)
if (uint256(reserveId >> 248) == 0xbb) {
return 0x0;
}
return reserveId;
}
}

View File

@@ -1,91 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./SamplerUtils.sol";
contract LidoSampler is SamplerUtils {
struct LidoInfo {
address stEthToken;
address wethToken;
}
/// @dev Sample sell quotes from Lido
/// @param lidoInfo Info regarding a specific Lido deployment
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromLido(
LidoInfo memory lidoInfo,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
pure
returns (uint256[] memory)
{
_assertValidPair(makerToken, takerToken);
if (takerToken != lidoInfo.wethToken || makerToken != address(lidoInfo.stEthToken)) {
// Return 0 values if not selling WETH for stETH
uint256 numSamples = takerTokenAmounts.length;
uint256[] memory makerTokenAmounts = new uint256[](numSamples);
return makerTokenAmounts;
}
// Minting stETH is always 1:1 therefore we can just return the same amounts back
return takerTokenAmounts;
}
/// @dev Sample buy quotes from Lido.
/// @param lidoInfo Info regarding a specific Lido deployment
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromLido(
LidoInfo memory lidoInfo,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
pure
returns (uint256[] memory)
{
_assertValidPair(makerToken, takerToken);
if (takerToken != lidoInfo.wethToken || makerToken != address(lidoInfo.stEthToken)) {
// Return 0 values if not buying stETH for WETH
uint256 numSamples = makerTokenAmounts.length;
uint256[] memory takerTokenAmounts = new uint256[](numSamples);
return takerTokenAmounts;
}
// Minting stETH is always 1:1 therefore we can just return the same amounts back
return makerTokenAmounts;
}
}

View File

@@ -1,132 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "@0x/contracts-zero-ex/contracts/src/vendor/ILiquidityProvider.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
contract LiquidityProviderSampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Default gas limit for liquidity provider calls.
uint256 constant private DEFAULT_CALL_GAS = 400e3; // 400k
/// @dev Sample sell quotes from an arbitrary on-chain liquidity provider.
/// @param providerAddress Address of the liquidity provider.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromLiquidityProvider(
address providerAddress,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
// Initialize array of maker token amounts.
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
try
ILiquidityProvider(providerAddress).getSellQuote
{gas: DEFAULT_CALL_GAS}
(
IERC20TokenV06(takerToken),
IERC20TokenV06(makerToken),
takerTokenAmounts[i]
)
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
/// @dev Sample buy quotes from an arbitrary on-chain liquidity provider.
/// @param providerAddress Address of the liquidity provider.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromLiquidityProvider(
address providerAddress,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(makerToken, providerAddress),
takerTokenData: abi.encode(takerToken, providerAddress),
getSellQuoteCallback: _sampleSellForApproximateBuyFromLiquidityProvider
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromLiquidityProvider(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(address takerToken, address providerAddress) =
abi.decode(takerTokenData, (address, address));
(address makerToken) =
abi.decode(makerTokenData, (address));
try
this.sampleSellsFromLiquidityProvider
{gas: DEFAULT_CALL_GAS}
(providerAddress, takerToken, makerToken, _toSingleValueArray(sellAmount))
returns (uint256[] memory amounts)
{
return amounts[0];
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
}

View File

@@ -1,127 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IMStable.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
contract MStableSampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Default gas limit for mStable calls.
uint256 constant private DEFAULT_CALL_GAS = 800e3; // 800k
/// @dev Sample sell quotes from the mStable contract
/// @param router Address of the mStable contract
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromMStable(
address router,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
// Initialize array of maker token amounts.
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
try
IMStable(router).getSwapOutput
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, takerTokenAmounts[i])
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
/// @dev Sample buy quotes from MStable contract
/// @param router Address of the mStable contract
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromMStable(
address router,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
return _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(makerToken, router),
takerTokenData: abi.encode(takerToken, router),
getSellQuoteCallback: _sampleSellForApproximateBuyFromMStable
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromMStable(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(address takerToken, address router) =
abi.decode(takerTokenData, (address, address));
(address makerToken) =
abi.decode(makerTokenData, (address));
try
this.sampleSellsFromMStable
(router, takerToken, makerToken, _toSingleValueArray(sellAmount))
returns (uint256[] memory amounts)
{
return amounts[0];
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
}

View File

@@ -1,267 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./SamplerUtils.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
interface IPSM {
// @dev Get the fee for selling USDC to DAI in PSM
// @return tin toll in [wad]
function tin() external view returns (uint256);
// @dev Get the fee for selling DAI to USDC in PSM
// @return tout toll out [wad]
function tout() external view returns (uint256);
// @dev Get the address of the PSM state Vat
// @return address of the Vat
function vat() external view returns (address);
// @dev Get the address of the underlying vault powering PSM
// @return address of gemJoin contract
function gemJoin() external view returns (address);
// @dev Get the address of DAI
// @return address of DAI contract
function dai() external view returns (address);
// @dev Sell USDC for DAI
// @param usr The address of the account trading USDC for DAI.
// @param gemAmt The amount of USDC to sell in USDC base units
function sellGem(
address usr,
uint256 gemAmt
) external;
// @dev Buy USDC for DAI
// @param usr The address of the account trading DAI for USDC
// @param gemAmt The amount of USDC to buy in USDC base units
function buyGem(
address usr,
uint256 gemAmt
) external;
}
interface IVAT {
// @dev Get a collateral type by identifier
// @param ilkIdentifier bytes32 identifier. Example: ethers.utils.formatBytes32String("PSM-USDC-A")
// @return ilk
// @return ilk.Art Total Normalised Debt in wad
// @return ilk.rate Accumulated Rates in ray
// @return ilk.spot Price with Safety Margin in ray
// @return ilk.line Debt Ceiling in rad
// @return ilk.dust Urn Debt Floor in rad
function ilks(
bytes32 ilkIdentifier
) external view returns (
uint256 Art,
uint256 rate,
uint256 spot,
uint256 line,
uint256 dust
);
}
contract MakerPSMSampler is
SamplerUtils
{
using LibSafeMathV06 for uint256;
/// @dev Information about which PSM module to use
struct MakerPsmInfo {
address psmAddress;
bytes32 ilkIdentifier;
address gemTokenAddress;
}
/// @dev Gas limit for MakerPsm calls.
uint256 constant private MAKER_PSM_CALL_GAS = 300e3; // 300k
// Maker units
// wad: fixed point decimal with 18 decimals (for basic quantities, e.g. balances)
uint256 constant private WAD = 10 ** 18;
// ray: fixed point decimal with 27 decimals (for precise quantites, e.g. ratios)
uint256 constant private RAY = 10 ** 27;
// rad: fixed point decimal with 45 decimals (result of integer multiplication with a wad and a ray)
uint256 constant private RAD = 10 ** 45;
// See https://github.com/makerdao/dss/blob/master/DEVELOPING.m
/// @dev Sample sell quotes from Maker PSM
function sampleSellsFromMakerPsm(
MakerPsmInfo memory psmInfo,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
IPSM psm = IPSM(psmInfo.psmAddress);
IVAT vat = IVAT(psm.vat());
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
if (makerToken != psm.dai() && takerToken != psm.dai()) {
return makerTokenAmounts;
}
for (uint256 i = 0; i < numSamples; i++) {
uint256 buyAmount = _samplePSMSell(psmInfo, makerToken, takerToken, takerTokenAmounts[i], psm, vat);
if (buyAmount == 0) {
break;
}
makerTokenAmounts[i] = buyAmount;
}
}
function sampleBuysFromMakerPsm(
MakerPsmInfo memory psmInfo,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
IPSM psm = IPSM(psmInfo.psmAddress);
IVAT vat = IVAT(psm.vat());
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
if (makerToken != psm.dai() && takerToken != psm.dai()) {
return takerTokenAmounts;
}
for (uint256 i = 0; i < numSamples; i++) {
uint256 sellAmount = _samplePSMBuy(psmInfo, makerToken, takerToken, makerTokenAmounts[i], psm, vat);
if (sellAmount == 0) {
break;
}
takerTokenAmounts[i] = sellAmount;
}
}
function _samplePSMSell(MakerPsmInfo memory psmInfo, address makerToken, address takerToken, uint256 takerTokenAmount, IPSM psm, IVAT vat)
private
view
returns (uint256)
{
(uint256 totalDebtInWad,,, uint256 debtCeilingInRad, uint256 debtFloorInRad) = vat.ilks(psmInfo.ilkIdentifier);
uint256 gemTokenBaseUnit = uint256(1e6);
if (takerToken == psmInfo.gemTokenAddress) {
// Simulate sellGem
// Selling USDC to the PSM, increasing the total debt
// Convert USDC 6 decimals to 18 decimals [wad]
uint256 takerTokenAmountInWad = takerTokenAmount.safeMul(1e12);
uint256 newTotalDebtInRad = totalDebtInWad.safeAdd(takerTokenAmountInWad).safeMul(RAY);
// PSM is too full to fit
if (newTotalDebtInRad >= debtCeilingInRad) {
return 0;
}
uint256 feeInWad = takerTokenAmountInWad.safeMul(psm.tin()).safeDiv(WAD);
uint256 makerTokenAmountInWad = takerTokenAmountInWad.safeSub(feeInWad);
return makerTokenAmountInWad;
} else if (makerToken == psmInfo.gemTokenAddress) {
// Simulate buyGem
// Buying USDC from the PSM, decreasing the total debt
// Selling DAI for USDC, already in 18 decimals [wad]
uint256 takerTokenAmountInWad = takerTokenAmount;
if (takerTokenAmountInWad > totalDebtInWad) {
return 0;
}
uint256 newTotalDebtInRad = totalDebtInWad.safeSub(takerTokenAmountInWad).safeMul(RAY);
// PSM is empty, not enough USDC to buy from it
if (newTotalDebtInRad <= debtFloorInRad) {
return 0;
}
uint256 feeDivisorInWad = WAD.safeAdd(psm.tout()); // eg. 1.001 * 10 ** 18 with 0.1% tout;
uint256 makerTokenAmountInGemTokenBaseUnits = takerTokenAmountInWad.safeMul(gemTokenBaseUnit).safeDiv(feeDivisorInWad);
return makerTokenAmountInGemTokenBaseUnits;
}
return 0;
}
function _samplePSMBuy(MakerPsmInfo memory psmInfo, address makerToken, address takerToken, uint256 makerTokenAmount, IPSM psm, IVAT vat)
private
view
returns (uint256)
{
(uint256 totalDebtInWad,,, uint256 debtCeilingInRad, uint256 debtFloorInRad) = vat.ilks(psmInfo.ilkIdentifier);
if (takerToken == psmInfo.gemTokenAddress) {
// Simulate sellGem
// Selling USDC to the PSM, increasing the total debt
uint256 makerTokenAmountInWad = makerTokenAmount;
uint256 feeDivisorInWad = WAD.safeSub(psm.tin()); // eg. 0.999 * 10 ** 18 with 0.1% tin;
uint256 takerTokenAmountInWad = makerTokenAmountInWad.safeMul(WAD).safeDiv(feeDivisorInWad);
uint256 newTotalDebtInRad = totalDebtInWad.safeAdd(takerTokenAmountInWad).safeMul(RAY);
// PSM is too full to fit
if (newTotalDebtInRad >= debtCeilingInRad) {
return 0;
}
uint256 takerTokenAmountInGemInGemBaseUnits = (takerTokenAmountInWad.safeDiv(1e12)).safeAdd(1); // Add 1 to deal with cut off decimals converting to lower decimals
return takerTokenAmountInGemInGemBaseUnits;
} else if (makerToken == psmInfo.gemTokenAddress) {
// Simulate buyGem
// Buying USDC from the PSM, decreasing the total debt
uint256 makerTokenAmountInWad = makerTokenAmount.safeMul(1e12);
uint256 feeMultiplierInWad = WAD.safeAdd(psm.tout()); // eg. 1.001 * 10 ** 18 with 0.1% tout;
uint256 takerTokenAmountInWad = makerTokenAmountInWad.safeMul(feeMultiplierInWad).safeDiv(WAD);
if (takerTokenAmountInWad > totalDebtInWad) {
return 0;
}
uint256 newTotalDebtInRad = totalDebtInWad.safeSub(takerTokenAmountInWad).safeMul(RAY);
// PSM is empty, not enough USDC to buy
if (newTotalDebtInRad <= debtFloorInRad) {
return 0;
}
return takerTokenAmountInWad;
}
return 0;
}
}

View File

@@ -1,169 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IMooniswap.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
contract MooniswapSampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Gas limit for Mooniswap calls.
uint256 constant private MOONISWAP_CALL_GAS = 150e3; // 150k
/// @dev Sample sell quotes from Mooniswap.
/// @param registry Address of the Mooniswap Registry.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return pool The contract address for the pool
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromMooniswap(
address registry,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (IMooniswap pool, uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
uint256 buyAmount = sampleSingleSellFromMooniswapPool(
registry,
takerToken,
makerToken,
takerTokenAmounts[i]
);
makerTokenAmounts[i] = buyAmount;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
}
pool = IMooniswap(
IMooniswapRegistry(registry).pools(takerToken, makerToken)
);
}
function sampleSingleSellFromMooniswapPool(
address registry,
address mooniswapTakerToken,
address mooniswapMakerToken,
uint256 takerTokenAmount
)
public
view
returns (uint256)
{
// Find the pool for the pair.
IMooniswap pool = IMooniswap(
IMooniswapRegistry(registry).pools(mooniswapTakerToken, mooniswapMakerToken)
);
// If there is no pool then return early
if (address(pool) == address(0)) {
return 0;
}
uint256 poolBalance = mooniswapTakerToken == address(0)
? address(pool).balance
: IERC20TokenV06(mooniswapTakerToken).balanceOf(address(pool));
// If the pool balance is smaller than the sell amount
// don't sample to avoid multiplication overflow in buys
if (poolBalance < takerTokenAmount) {
return 0;
}
try
pool.getReturn
{gas: MOONISWAP_CALL_GAS}
(mooniswapTakerToken, mooniswapMakerToken, takerTokenAmount)
returns (uint256 amount)
{
return amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
/// @dev Sample buy quotes from Mooniswap.
/// @param registry Address of the Mooniswap Registry.
/// @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.
/// @return pool The contract address for the pool
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromMooniswap(
address registry,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (IMooniswap pool, uint256[] memory takerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(registry, makerToken),
takerTokenData: abi.encode(registry, takerToken),
getSellQuoteCallback: _sampleSellForApproximateBuyFromMooniswap
}),
makerTokenAmounts
);
pool = IMooniswap(
IMooniswapRegistry(registry).pools(takerToken, makerToken)
);
}
function _sampleSellForApproximateBuyFromMooniswap(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(address registry, address mooniswapTakerToken) = abi.decode(takerTokenData, (address, address));
(address _registry, address mooniswapMakerToken) = abi.decode(makerTokenData, (address, address));
return sampleSingleSellFromMooniswapPool(
registry,
mooniswapTakerToken,
mooniswapMakerToken,
sellAmount
);
}
}

View File

@@ -1,82 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IMultiBridge.sol";
contract MultiBridgeSampler {
/// @dev Default gas limit for multibridge calls.
uint256 constant private DEFAULT_CALL_GAS = 400e3; // 400k
/// @dev Sample sell quotes from MultiBridge.
/// @param multibridge Address of the MultiBridge contract.
/// @param takerToken Address of the taker token (what to sell).
/// @param intermediateToken The address of the intermediate token to
/// use in an indirect route.
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromMultiBridge(
address multibridge,
address takerToken,
address intermediateToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
// Initialize array of maker token amounts.
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
// If no address provided, return all zeros.
if (multibridge == address(0)) {
return makerTokenAmounts;
}
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
multibridge.staticcall.gas(DEFAULT_CALL_GAS)(
abi.encodeWithSelector(
IMultiBridge(0).getSellQuote.selector,
takerToken,
intermediateToken,
makerToken,
takerTokenAmounts[i]
));
uint256 buyAmount = 0;
if (didSucceed) {
buyAmount = abi.decode(resultData, (uint256));
}
// Exit early if the amount is too high for the source to serve
if (buyAmount == 0) {
break;
}
makerTokenAmounts[i] = buyAmount;
}
}
}

View File

@@ -1,239 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
interface IExchange {
enum OrderStatus {
INVALID,
FILLABLE,
FILLED,
CANCELLED,
EXPIRED
}
/// @dev A standard OTC or OO limit order.
struct LimitOrder {
IERC20TokenV06 makerToken;
IERC20TokenV06 takerToken;
uint128 makerAmount;
uint128 takerAmount;
uint128 takerTokenFeeAmount;
address maker;
address taker;
address sender;
address feeRecipient;
bytes32 pool;
uint64 expiry;
uint256 salt;
}
/// @dev An RFQ limit order.
struct RfqOrder {
IERC20TokenV06 makerToken;
IERC20TokenV06 takerToken;
uint128 makerAmount;
uint128 takerAmount;
address maker;
address taker;
address txOrigin;
bytes32 pool;
uint64 expiry;
uint256 salt;
}
/// @dev Info on a limit or RFQ order.
struct OrderInfo {
bytes32 orderHash;
OrderStatus status;
uint128 takerTokenFilledAmount;
}
/// @dev Allowed signature types.
enum SignatureType {
ILLEGAL,
INVALID,
EIP712,
ETHSIGN
}
/// @dev Encoded EC signature.
struct Signature {
// How to validate the signature.
SignatureType signatureType;
// EC Signature data.
uint8 v;
// EC Signature data.
bytes32 r;
// EC Signature data.
bytes32 s;
}
/// @dev Get the order info for a limit order.
/// @param order The limit order.
/// @return orderInfo Info about the order.
function getLimitOrderInfo(LimitOrder memory order)
external
view
returns (OrderInfo memory orderInfo);
/// @dev Get order info, fillable amount, and signature validity for a limit order.
/// Fillable amount is determined using balances and allowances of the maker.
/// @param order The limit order.
/// @param signature The order signature.
/// @return orderInfo Info about the order.
/// @return actualFillableTakerTokenAmount How much of the order is fillable
/// based on maker funds, in taker tokens.
/// @return isSignatureValid Whether the signature is valid.
function getLimitOrderRelevantState(
LimitOrder memory order,
Signature calldata signature
)
external
view
returns (
OrderInfo memory orderInfo,
uint128 actualFillableTakerTokenAmount,
bool isSignatureValid
);
}
contract NativeOrderSampler {
using LibSafeMathV06 for uint256;
using LibBytesV06 for bytes;
/// @dev Gas limit for calls to `getOrderFillableTakerAmount()`.
uint256 constant internal DEFAULT_CALL_GAS = 200e3; // 200k
/// @dev Queries the fillable taker asset amounts of native orders.
/// Effectively ignores orders that have empty signatures or
/// maker/taker asset amounts (returning 0).
/// @param orders Native limit orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`.
/// @param exchange The V4 exchange.
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled
/// by each order in `orders`.
function getLimitOrderFillableTakerAssetAmounts(
IExchange.LimitOrder[] memory orders,
IExchange.Signature[] memory orderSignatures,
IExchange exchange
)
public
view
returns (uint256[] memory orderFillableTakerAssetAmounts)
{
orderFillableTakerAssetAmounts = new uint256[](orders.length);
for (uint256 i = 0; i != orders.length; i++) {
try
this.getLimitOrderFillableTakerAmount
{gas: DEFAULT_CALL_GAS}
(
orders[i],
orderSignatures[i],
exchange
)
returns (uint256 amount)
{
orderFillableTakerAssetAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
orderFillableTakerAssetAmounts[i] = 0;
}
}
}
/// @dev Queries the fillable taker asset amounts of native orders.
/// Effectively ignores orders that have empty signatures or
/// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`.
/// @param exchange The V4 exchange.
/// @return orderFillableMakerAssetAmounts How much maker asset can be filled
/// by each order in `orders`.
function getLimitOrderFillableMakerAssetAmounts(
IExchange.LimitOrder[] memory orders,
IExchange.Signature[] memory orderSignatures,
IExchange exchange
)
public
view
returns (uint256[] memory orderFillableMakerAssetAmounts)
{
orderFillableMakerAssetAmounts = getLimitOrderFillableTakerAssetAmounts(
orders,
orderSignatures,
exchange
);
// `orderFillableMakerAssetAmounts` now holds taker asset amounts, so
// convert them to maker asset amounts.
for (uint256 i = 0; i < orders.length; ++i) {
if (orderFillableMakerAssetAmounts[i] != 0) {
orderFillableMakerAssetAmounts[i] = LibMathV06.getPartialAmountCeil(
orderFillableMakerAssetAmounts[i],
orders[i].takerAmount,
orders[i].makerAmount
);
}
}
}
/// @dev Get the fillable taker amount of an order, taking into account
/// order state, maker fees, and maker balances.
function getLimitOrderFillableTakerAmount(
IExchange.LimitOrder memory order,
IExchange.Signature memory signature,
IExchange exchange
)
virtual
public
view
returns (uint256 fillableTakerAmount)
{
if (signature.signatureType == IExchange.SignatureType.ILLEGAL ||
signature.signatureType == IExchange.SignatureType.INVALID ||
order.makerAmount == 0 ||
order.takerAmount == 0)
{
return 0;
}
(
IExchange.OrderInfo memory orderInfo,
uint128 remainingFillableTakerAmount,
bool isSignatureValid
) = exchange.getLimitOrderRelevantState(order, signature);
if (
orderInfo.status != IExchange.OrderStatus.FILLABLE ||
!isSignatureValid ||
order.makerToken == IERC20TokenV06(0)
) {
return 0;
}
fillableTakerAmount = uint256(remainingFillableTakerAmount);
}
}

View File

@@ -0,0 +1,89 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IPlatypus.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
contract PlatypusSampler is
SamplerUtils,
ApproximateBuys
{
function sampleSellsFromPlatypus(
address pool,
address[] memory path,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
try
IPlatypus(pool).quotePotentialSwap(path[0], path[1], takerTokenAmounts[i])
returns (uint256 amountAfterFees, uint256 feeAmount)
{
makerTokenAmounts[i] = amountAfterFees;
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory result) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
function sampleBuysFromPlatypus(
address pool,
address[] memory path,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
address[] memory invertBuyPath = new address[](2);
invertBuyPath[0] = path[1];
invertBuyPath[1] = path[0];
return _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(pool, invertBuyPath),
takerTokenData: abi.encode(pool, path),
getSellQuoteCallback: _sampleSellForApproximateBuyFromPlatypus
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromPlatypus(
bytes memory makerTokenData,
bytes memory takerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(address _pool, address[] memory _path ) = abi.decode(makerTokenData, (address, address[]));
(bool success, bytes memory resultData) = address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromPlatypus.selector,
_pool,
_path,
_toSingleValueArray(sellAmount)
));
if(!success) {
return 0;
}
// solhint-disable-next-line indent
return abi.decode(resultData, (uint256[]))[0];
}
}

View File

@@ -1,58 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
contract SamplerUtils {
/// @dev Overridable way to get token decimals.
/// @param tokenAddress Address of the token.
/// @return decimals The decimal places for the token.
function _getTokenDecimals(address tokenAddress)
virtual
internal
view
returns (uint8 decimals)
{
return LibERC20TokenV06.compatDecimals(IERC20TokenV06(tokenAddress));
}
function _toSingleValueArray(uint256 v)
internal
pure
returns (uint256[] memory arr)
{
arr = new uint256[](1);
arr[0] = v;
}
/// @dev Assert that the tokens in a trade pair are valid.
/// @param makerToken Address of the maker token.
/// @param takerToken Address of the taker token.
function _assertValidPair(address makerToken, address takerToken)
internal
pure
{
require(makerToken != takerToken, "ERC20BridgeSampler/INVALID_TOKEN_PAIR");
}
}

View File

@@ -1,126 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./ApproximateBuys.sol";
import "./interfaces/IShell.sol";
import "./SamplerUtils.sol";
contract ShellSampler is
SamplerUtils,
ApproximateBuys
{
struct ShellInfo {
address poolAddress;
}
/// @dev Default gas limit for Shell calls.
uint256 constant private DEFAULT_CALL_GAS = 300e3; // 300k
/// @dev Sample sell quotes from the Shell pool contract
/// @param pool Address of the Shell pool contract
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromShell(
address pool,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
// Initialize array of maker token amounts.
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
try
IShell(pool).viewOriginSwap
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, takerTokenAmounts[i])
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
/// @dev Sample buy quotes from Shell pool contract
/// @param pool Address of the Shell pool contract
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromShell(
address pool,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
return _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(makerToken, pool),
takerTokenData: abi.encode(takerToken, pool),
getSellQuoteCallback: _sampleSellForApproximateBuyFromShell
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromShell(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(address takerToken, address pool) = abi.decode(takerTokenData, (address, address));
(address makerToken) = abi.decode(makerTokenData, (address));
try
this.sampleSellsFromShell
(pool, takerToken, makerToken, _toSingleValueArray(sellAmount))
returns (uint256[] memory amounts)
{
return amounts[0];
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
}

View File

@@ -1,156 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
// import "./interfaces/ISmoothy.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
import "./interfaces/ISmoothy.sol";
contract SmoothySampler is
SamplerUtils,
ApproximateBuys
{
/// @dev Information for sampling from smoothy sources.
struct SmoothyInfo {
address poolAddress;
bytes4 sellQuoteFunctionSelector;
bytes4 buyQuoteFunctionSelector;
}
/// @dev Base gas limit for Smoothy calls.
uint256 constant private SMOOTHY_CALL_GAS = 600e3;
/// @dev Sample sell quotes from Smoothy.
/// @param smoothyInfo Smoothy information specific to this token pair.
/// @param fromTokenIdx Index of the taker token (what to sell).
/// @param toTokenIdx Index of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromSmoothy(
SmoothyInfo memory smoothyInfo,
int128 fromTokenIdx,
int128 toTokenIdx,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
// Basically a Curve fork
// Smoothy only keep a percentage of its tokens available in reserve
uint256 poolReserveMakerAmount = ISmoothy(smoothyInfo.poolAddress).getBalance(uint256(toTokenIdx)) -
ISmoothy(smoothyInfo.poolAddress)._yBalances(uint256(toTokenIdx));
(, , , uint256 decimals) = ISmoothy(smoothyInfo.poolAddress).getTokenStats(uint256(toTokenIdx));
poolReserveMakerAmount = poolReserveMakerAmount/(10**(18-decimals));
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
smoothyInfo.poolAddress.staticcall.gas(SMOOTHY_CALL_GAS)(
abi.encodeWithSelector(
smoothyInfo.sellQuoteFunctionSelector,
fromTokenIdx,
toTokenIdx,
takerTokenAmounts[i]
));
uint256 buyAmount = 0;
if (didSucceed) {
buyAmount = abi.decode(resultData, (uint256));
}
// Make sure the quoted buyAmount is available in the pool reserve
if (buyAmount >= poolReserveMakerAmount) {
// Assign pool reserve amount for all higher samples to break early
for (uint256 j = i; j < numSamples; j++) {
makerTokenAmounts[j] = poolReserveMakerAmount;
}
break;
} else {
makerTokenAmounts[i] = buyAmount;
}
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from Smoothy.
/// @param smoothyInfo Smoothy information specific to this token pair.
/// @param fromTokenIdx Index of the taker token (what to sell).
/// @param toTokenIdx Index of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromSmoothy(
SmoothyInfo memory smoothyInfo,
int128 fromTokenIdx,
int128 toTokenIdx,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
// Buys not supported so approximate it.
return _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
makerTokenData: abi.encode(toTokenIdx, smoothyInfo),
takerTokenData: abi.encode(fromTokenIdx, smoothyInfo),
getSellQuoteCallback: _sampleSellForApproximateBuyFromSmoothy
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromSmoothy(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
)
private
view
returns (uint256 buyAmount)
{
(int128 takerTokenIdx, SmoothyInfo memory smoothyInfo) =
abi.decode(takerTokenData, (int128, SmoothyInfo));
(int128 makerTokenIdx) =
abi.decode(makerTokenData, (int128));
(bool success, bytes memory resultData) =
address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromSmoothy.selector,
smoothyInfo,
takerTokenIdx,
makerTokenIdx,
_toSingleValueArray(sellAmount)
));
if (!success) {
return 0;
}
// solhint-disable-next-line indent
return abi.decode(resultData, (uint256[]))[0];
}
}

View File

@@ -1,124 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
contract TwoHopSampler {
using LibBytesV06 for bytes;
struct HopInfo {
uint256 sourceIndex;
bytes returnData;
}
function sampleTwoHopSell(
bytes[] memory firstHopCalls,
bytes[] memory secondHopCalls,
uint256 sellAmount
)
public
returns (
HopInfo memory firstHop,
HopInfo memory secondHop,
uint256 buyAmount
)
{
uint256 intermediateAssetAmount = 0;
for (uint256 i = 0; i != firstHopCalls.length; ++i) {
firstHopCalls[i].writeUint256(firstHopCalls[i].length - 32, sellAmount);
(bool didSucceed, bytes memory returnData) = address(this).call(firstHopCalls[i]);
if (didSucceed) {
uint256 amount = returnData.readUint256(returnData.length - 32);
if (amount > intermediateAssetAmount) {
intermediateAssetAmount = amount;
firstHop.sourceIndex = i;
firstHop.returnData = returnData;
}
}
}
if (intermediateAssetAmount == 0) {
return (firstHop, secondHop, buyAmount);
}
for (uint256 j = 0; j != secondHopCalls.length; ++j) {
secondHopCalls[j].writeUint256(secondHopCalls[j].length - 32, intermediateAssetAmount);
(bool didSucceed, bytes memory returnData) = address(this).call(secondHopCalls[j]);
if (didSucceed) {
uint256 amount = returnData.readUint256(returnData.length - 32);
if (amount > buyAmount) {
buyAmount = amount;
secondHop.sourceIndex = j;
secondHop.returnData = returnData;
}
}
}
}
function sampleTwoHopBuy(
bytes[] memory firstHopCalls,
bytes[] memory secondHopCalls,
uint256 buyAmount
)
public
returns (
HopInfo memory firstHop,
HopInfo memory secondHop,
uint256 sellAmount
)
{
sellAmount = uint256(-1);
uint256 intermediateAssetAmount = uint256(-1);
for (uint256 j = 0; j != secondHopCalls.length; ++j) {
secondHopCalls[j].writeUint256(secondHopCalls[j].length - 32, buyAmount);
(bool didSucceed, bytes memory returnData) = address(this).call(secondHopCalls[j]);
if (didSucceed) {
uint256 amount = returnData.readUint256(returnData.length - 32);
if (
amount > 0 &&
amount < intermediateAssetAmount
) {
intermediateAssetAmount = amount;
secondHop.sourceIndex = j;
secondHop.returnData = returnData;
}
}
}
if (intermediateAssetAmount == uint256(-1)) {
return (firstHop, secondHop, sellAmount);
}
for (uint256 i = 0; i != firstHopCalls.length; ++i) {
firstHopCalls[i].writeUint256(firstHopCalls[i].length - 32, intermediateAssetAmount);
(bool didSucceed, bytes memory returnData) = address(this).call(firstHopCalls[i]);
if (didSucceed) {
uint256 amount = returnData.readUint256(returnData.length - 32);
if (
amount > 0 &&
amount < sellAmount
) {
sellAmount = amount;
firstHop.sourceIndex = i;
firstHop.returnData = returnData;
}
}
}
}
}

View File

@@ -1,214 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IUniswapExchangeQuotes.sol";
import "./SamplerUtils.sol";
interface IUniswapExchangeFactory {
/// @dev Get the exchange for a token.
/// @param tokenAddress The address of the token contract.
function getExchange(address tokenAddress)
external
view
returns (address);
}
contract UniswapSampler is
SamplerUtils
{
/// @dev Gas limit for Uniswap calls.
uint256 constant private UNISWAP_CALL_GAS = 150e3; // 150k
/// @dev Sample sell quotes from Uniswap.
/// @param router Address of the Uniswap Router
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromUniswap(
address router,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
IUniswapExchangeQuotes takerTokenExchange = takerToken == address(0) ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(router, takerToken);
IUniswapExchangeQuotes makerTokenExchange = makerToken == address(0) ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(router, makerToken);
for (uint256 i = 0; i < numSamples; i++) {
bool didSucceed = true;
if (makerToken == address(0)) {
(makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
address(takerTokenExchange),
takerTokenExchange.getTokenToEthInputPrice.selector,
takerTokenAmounts[i]
);
} else if (takerToken == address(0)) {
(makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
address(makerTokenExchange),
makerTokenExchange.getEthToTokenInputPrice.selector,
takerTokenAmounts[i]
);
} else {
uint256 ethBought;
(ethBought, didSucceed) = _callUniswapExchangePriceFunction(
address(takerTokenExchange),
takerTokenExchange.getTokenToEthInputPrice.selector,
takerTokenAmounts[i]
);
if (ethBought != 0) {
(makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
address(makerTokenExchange),
makerTokenExchange.getEthToTokenInputPrice.selector,
ethBought
);
} else {
makerTokenAmounts[i] = 0;
}
}
// Break early if amounts are 0
if (!didSucceed || makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from Uniswap.
/// @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.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromUniswap(
address router,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
IUniswapExchangeQuotes takerTokenExchange = takerToken == address(0) ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(router, takerToken);
IUniswapExchangeQuotes makerTokenExchange = makerToken == address(0) ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(router, makerToken);
for (uint256 i = 0; i < numSamples; i++) {
bool didSucceed = true;
if (makerToken == address(0)) {
(takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
address(takerTokenExchange),
takerTokenExchange.getTokenToEthOutputPrice.selector,
makerTokenAmounts[i]
);
} else if (takerToken == address(0)) {
(takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
address(makerTokenExchange),
makerTokenExchange.getEthToTokenOutputPrice.selector,
makerTokenAmounts[i]
);
} else {
uint256 ethSold;
(ethSold, didSucceed) = _callUniswapExchangePriceFunction(
address(makerTokenExchange),
makerTokenExchange.getEthToTokenOutputPrice.selector,
makerTokenAmounts[i]
);
if (ethSold != 0) {
(takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
address(takerTokenExchange),
takerTokenExchange.getTokenToEthOutputPrice.selector,
ethSold
);
} else {
takerTokenAmounts[i] = 0;
}
}
// Break early if amounts are 0
if (!didSucceed || takerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Gracefully calls a Uniswap pricing function.
/// @param uniswapExchangeAddress Address of an `IUniswapExchangeQuotes` exchange.
/// @param functionSelector Selector of the target function.
/// @param inputAmount Quantity parameter particular to the pricing function.
/// @return outputAmount The returned amount from the function call. Will be
/// zero if the call fails or if `uniswapExchangeAddress` is zero.
function _callUniswapExchangePriceFunction(
address uniswapExchangeAddress,
bytes4 functionSelector,
uint256 inputAmount
)
private
view
returns (uint256 outputAmount, bool didSucceed)
{
if (uniswapExchangeAddress == address(0)) {
return (outputAmount, didSucceed);
}
bytes memory resultData;
(didSucceed, resultData) =
uniswapExchangeAddress.staticcall.gas(UNISWAP_CALL_GAS)(
abi.encodeWithSelector(
functionSelector,
inputAmount
));
if (didSucceed) {
outputAmount = abi.decode(resultData, (uint256));
}
}
/// @dev Retrive an existing Uniswap exchange contract.
/// Throws if the exchange does not exist.
/// @param router Address of the Uniswap router.
/// @param tokenAddress Address of the token contract.
/// @return exchange `IUniswapExchangeQuotes` for the token.
function _getUniswapExchange(address router, address tokenAddress)
private
view
returns (IUniswapExchangeQuotes exchange)
{
exchange = IUniswapExchangeQuotes(
address(IUniswapExchangeFactory(router)
.getExchange(tokenAddress))
);
}
}

View File

@@ -1,363 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
interface IUniswapV3QuoterV2 {
function factory()
external
view
returns (IUniswapV3Factory factory);
// @notice Returns the amount out received for a given exact input swap without executing the swap
// @param path The path of the swap, i.e. each token pair and the pool fee
// @param amountIn The amount of the first token to swap
// @return amountOut The amount of the last token that would be received
// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactInput(bytes memory path, uint256 amountIn)
external
returns (
uint256 amountOut,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
// @notice Returns the amount in required for a given exact output swap without executing the swap
// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order
// @param amountOut The amount of the last token to receive
// @return amountIn The amount of first token required to be paid
// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactOutput(bytes memory path, uint256 amountOut)
external
returns (
uint256 amountIn,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
}
interface IUniswapV3Factory {
function getPool(IERC20TokenV06 a, IERC20TokenV06 b, uint24 fee)
external
view
returns (IUniswapV3Pool pool);
}
interface IUniswapV3Pool {
function token0() external view returns (IERC20TokenV06);
function token1() external view returns (IERC20TokenV06);
function fee() external view returns (uint24);
}
contract UniswapV3Sampler
{
/// @dev Gas limit for UniswapV3 calls. This is 100% a guess.
uint256 constant private QUOTE_GAS = 700e3;
/// @dev Sample sell quotes from UniswapV3.
/// @param quoter UniswapV3 Quoter contract.
/// @param path Token route. Should be takerToken -> makerToken
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return uniswapPaths The encoded uniswap path for each sample.
/// @return uniswapGasUsed Estimated amount of gas used
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromUniswapV3(
IUniswapV3QuoterV2 quoter,
IERC20TokenV06[] memory path,
uint256[] memory takerTokenAmounts
)
public
returns (
bytes[] memory uniswapPaths,
uint256[] memory uniswapGasUsed,
uint256[] memory makerTokenAmounts
)
{
IUniswapV3Pool[][] memory poolPaths =
_getValidPoolPaths(quoter.factory(), path, 0);
makerTokenAmounts = new uint256[](takerTokenAmounts.length);
uniswapPaths = new bytes[](takerTokenAmounts.length);
uniswapGasUsed = new uint256[](takerTokenAmounts.length);
for (uint256 i = 0; i < takerTokenAmounts.length; ++i) {
// Pick the best result from all the paths.
uint256 topBuyAmount = 0;
for (uint256 j = 0; j < poolPaths.length; ++j) {
bytes memory uniswapPath = _toUniswapPath(path, poolPaths[j]);
try quoter.quoteExactInput
{ gas: QUOTE_GAS }
(uniswapPath, takerTokenAmounts[i])
returns (
uint256 buyAmount,
uint160[] memory, /* sqrtPriceX96AfterList */
uint32[] memory, /* initializedTicksCrossedList */
uint256 gasUsed
)
{
if (topBuyAmount <= buyAmount) {
topBuyAmount = buyAmount;
uniswapPaths[i] = uniswapPath;
uniswapGasUsed[i] = gasUsed;
}
} catch {}
}
// Break early if we can't complete the sells.
if (topBuyAmount == 0) {
// HACK(kimpers): To avoid too many local variables, paths and gas used is set directly in the loop
// then reset if no valid valid quote was found
uniswapPaths[i] = "";
uniswapGasUsed[i] = 0;
break;
}
makerTokenAmounts[i] = topBuyAmount;
}
}
/// @dev Sample buy quotes from UniswapV3.
/// @param quoter UniswapV3 Quoter contract.
/// @param path Token route. Should be takerToken -> makerToken.
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return uniswapPaths The encoded uniswap path for each sample.
/// @return uniswapGasUsed Estimated amount of gas used
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromUniswapV3(
IUniswapV3QuoterV2 quoter,
IERC20TokenV06[] memory path,
uint256[] memory makerTokenAmounts
)
public
returns (
bytes[] memory uniswapPaths,
uint256[] memory uniswapGasUsed,
uint256[] memory takerTokenAmounts
)
{
IUniswapV3Pool[][] memory poolPaths =
_getValidPoolPaths(quoter.factory(), path, 0);
IERC20TokenV06[] memory reversedPath = _reverseTokenPath(path);
takerTokenAmounts = new uint256[](makerTokenAmounts.length);
uniswapPaths = new bytes[](makerTokenAmounts.length);
uniswapGasUsed = new uint256[](makerTokenAmounts.length);
for (uint256 i = 0; i < makerTokenAmounts.length; ++i) {
// Pick the best result from all the paths.
uint256 topSellAmount = 0;
for (uint256 j = 0; j < poolPaths.length; ++j) {
// quoter requires path to be reversed for buys.
bytes memory uniswapPath = _toUniswapPath(
reversedPath,
_reversePoolPath(poolPaths[j])
);
try
quoter.quoteExactOutput
{ gas: QUOTE_GAS }
(uniswapPath, makerTokenAmounts[i])
returns (
uint256 sellAmount,
uint160[] memory, /* sqrtPriceX96AfterList */
uint32[] memory, /* initializedTicksCrossedList */
uint256 gasUsed
)
{
if (topSellAmount == 0 || topSellAmount >= sellAmount) {
topSellAmount = sellAmount;
// But the output path should still be encoded for sells.
uniswapPaths[i] = _toUniswapPath(path, poolPaths[j]);
uniswapGasUsed[i] = gasUsed;
}
} catch {}
}
// Break early if we can't complete the buys.
if (topSellAmount == 0) {
// HACK(kimpers): To avoid too many local variables, paths and gas used is set directly in the loop
// then reset if no valid valid quote was found
uniswapPaths[i] = "";
uniswapGasUsed[i] = 0;
break;
}
takerTokenAmounts[i] = topSellAmount;
}
}
function _getValidPoolPaths(
IUniswapV3Factory factory,
IERC20TokenV06[] memory tokenPath,
uint256 startIndex
)
private
view
returns (IUniswapV3Pool[][] memory poolPaths)
{
require(
tokenPath.length - startIndex >= 2,
"UniswapV3Sampler/tokenPath too short"
);
uint24[4] memory validPoolFees = [
// The launch pool fees. Could get hairier if they add more.
uint24(0.0001e6),
uint24(0.0005e6),
uint24(0.003e6),
uint24(0.01e6)
];
IUniswapV3Pool[] memory validPools =
new IUniswapV3Pool[](validPoolFees.length);
uint256 numValidPools = 0;
{
IERC20TokenV06 inputToken = tokenPath[startIndex];
IERC20TokenV06 outputToken = tokenPath[startIndex + 1];
for (uint256 i = 0; i < validPoolFees.length; ++i) {
IUniswapV3Pool pool =
factory.getPool(inputToken, outputToken, validPoolFees[i]);
if (_isValidPool(pool)) {
validPools[numValidPools++] = pool;
}
}
}
if (numValidPools == 0) {
// No valid pools for this hop.
return poolPaths;
}
if (startIndex + 2 == tokenPath.length) {
// End of path.
poolPaths = new IUniswapV3Pool[][](numValidPools);
for (uint256 i = 0; i < numValidPools; ++i) {
poolPaths[i] = new IUniswapV3Pool[](1);
poolPaths[i][0] = validPools[i];
}
return poolPaths;
}
// Get paths for subsequent hops.
IUniswapV3Pool[][] memory subsequentPoolPaths =
_getValidPoolPaths(factory, tokenPath, startIndex + 1);
if (subsequentPoolPaths.length == 0) {
// Could not complete the path.
return poolPaths;
}
// Combine our pools with the next hop paths.
poolPaths = new IUniswapV3Pool[][](
numValidPools * subsequentPoolPaths.length
);
for (uint256 i = 0; i < numValidPools; ++i) {
for (uint256 j = 0; j < subsequentPoolPaths.length; ++j) {
uint256 o = i * subsequentPoolPaths.length + j;
// Prepend pool to the subsequent path.
poolPaths[o] =
new IUniswapV3Pool[](1 + subsequentPoolPaths[j].length);
poolPaths[o][0] = validPools[i];
for (uint256 k = 0; k < subsequentPoolPaths[j].length; ++k) {
poolPaths[o][1 + k] = subsequentPoolPaths[j][k];
}
}
}
return poolPaths;
}
function _reverseTokenPath(IERC20TokenV06[] memory tokenPath)
private
pure
returns (IERC20TokenV06[] memory reversed)
{
reversed = new IERC20TokenV06[](tokenPath.length);
for (uint256 i = 0; i < tokenPath.length; ++i) {
reversed[i] = tokenPath[tokenPath.length - i - 1];
}
}
function _reversePoolPath(IUniswapV3Pool[] memory poolPath)
private
pure
returns (IUniswapV3Pool[] memory reversed)
{
reversed = new IUniswapV3Pool[](poolPath.length);
for (uint256 i = 0; i < poolPath.length; ++i) {
reversed[i] = poolPath[poolPath.length - i - 1];
}
}
function _isValidPool(IUniswapV3Pool pool)
private
view
returns (bool isValid)
{
// Check if it has been deployed.
{
uint256 codeSize;
assembly {
codeSize := extcodesize(pool)
}
if (codeSize == 0) {
return false;
}
}
// Must have a balance of both tokens.
if (pool.token0().balanceOf(address(pool)) == 0) {
return false;
}
if (pool.token1().balanceOf(address(pool)) == 0) {
return false;
}
return true;
}
function _toUniswapPath(
IERC20TokenV06[] memory tokenPath,
IUniswapV3Pool[] memory poolPath
)
private
view
returns (bytes memory uniswapPath)
{
require(
tokenPath.length >= 2 && tokenPath.length == poolPath.length + 1,
"UniswapV3Sampler/invalid path lengths"
);
// Uniswap paths are tightly packed as:
// [token0, token0token1PairFee, token1, token1Token2PairFee, token2, ...]
uniswapPath = new bytes(tokenPath.length * 20 + poolPath.length * 3);
uint256 o;
assembly { o := add(uniswapPath, 32) }
for (uint256 i = 0; i < tokenPath.length; ++i) {
if (i > 0) {
uint24 poolFee = poolPath[i - 1].fee();
assembly {
mstore(o, shl(232, poolFee))
o := add(o, 3)
}
}
IERC20TokenV06 token = tokenPath[i];
assembly {
mstore(o, shl(96, token))
o := add(o, 20)
}
}
}
}

View File

@@ -1,95 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
contract UtilitySampler {
using LibERC20TokenV06 for IERC20TokenV06;
IERC20TokenV06 private immutable UTILITY_ETH_ADDRESS = IERC20TokenV06(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
function getTokenDecimals(IERC20TokenV06[] memory tokens)
public
view
returns (uint256[] memory decimals)
{
decimals = new uint256[](tokens.length);
for (uint256 i = 0; i != tokens.length; i++) {
decimals[i] = tokens[i] == UTILITY_ETH_ADDRESS
? 18
: tokens[i].compatDecimals();
}
}
function getBalanceOf(IERC20TokenV06[] memory tokens, address account)
public
view
returns (uint256[] memory balances)
{
balances = new uint256[](tokens.length);
for (uint256 i = 0; i != tokens.length; i++) {
balances[i] = tokens[i] == UTILITY_ETH_ADDRESS
? account.balance
: tokens[i].compatBalanceOf(account);
}
}
function getAllowanceOf(IERC20TokenV06[] memory tokens, address account, address spender)
public
view
returns (uint256[] memory allowances)
{
allowances = new uint256[](tokens.length);
for (uint256 i = 0; i != tokens.length; i++) {
allowances[i] = tokens[i] == UTILITY_ETH_ADDRESS
? 0
: tokens[i].compatAllowance(account, spender);
}
}
function isContract(address account)
public
view
returns (bool)
{
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function getGasLeft()
public
returns (uint256)
{
return gasleft();
}
function getBlockNumber()
public
view
returns (uint256)
{
return block.number;
}
}

View File

@@ -0,0 +1,134 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2022 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import './ApproximateBuys.sol';
import './SamplerUtils.sol';
struct VeloRoute {
address from;
address to;
bool stable;
}
interface IVelodromeRouter {
function getAmountOut(
uint256 amountIn,
address tokenIn,
address tokenOut
) external view returns (uint256 amount, bool stable);
function getAmountsOut(uint256 amountIn, VeloRoute[] calldata routes)
external
view
returns (uint256[] memory amounts);
}
contract VelodromeSampler is SamplerUtils, ApproximateBuys {
/// @dev Sample sell quotes from Velodrome
/// @param router Address of Velodrome router.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample (sorted in ascending order).
/// @return stable Whether the pool is a stable pool (vs volatile).
/// @return makerTokenAmounts Maker amounts bought at each taker token amount.
function sampleSellsFromVelodrome(
IVelodromeRouter router,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
) public view returns (bool stable, uint256[] memory makerTokenAmounts) {
_assertValidPair(makerToken, takerToken);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
// Sampling should not mix stable and volatile pools.
// Find the most liquid pool based on max(takerTokenAmounts) and stick with it.
stable = _isMostLiquidPoolStablePool(router, takerToken, makerToken, takerTokenAmounts);
VeloRoute[] memory routes = new VeloRoute[](1);
routes[0] = VeloRoute({ from: takerToken, to: makerToken, stable: stable });
for (uint256 i = 0; i < numSamples; i++) {
makerTokenAmounts[i] = router.getAmountsOut(takerTokenAmounts[i], routes)[1];
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from Velodrome.
/// @param router Address of Velodrome router.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return stable Whether the pool is a stable pool (vs volatile).
/// @return takerTokenAmounts Taker amounts sold at each maker token amount.
function sampleBuysFromVelodrome(
IVelodromeRouter router,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
) public view returns (bool stable, uint256[] memory takerTokenAmounts) {
_assertValidPair(makerToken, takerToken);
// Sampling should not mix stable and volatile pools.
// Find the most liquid pool based on the reverse swap (maker -> taker) and stick with it.
stable = _isMostLiquidPoolStablePool(router, makerToken, takerToken, makerTokenAmounts);
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
takerTokenData: abi.encode(router, VeloRoute({ from: takerToken, to: makerToken, stable: stable })),
makerTokenData: abi.encode(router, VeloRoute({ from: makerToken, to: takerToken, stable: stable })),
getSellQuoteCallback: _sampleSellForApproximateBuyFromVelodrome
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromVelodrome(
bytes memory takerTokenData,
bytes memory, /* makerTokenData */
uint256 sellAmount
) internal view returns (uint256) {
(IVelodromeRouter router, VeloRoute memory route) = abi.decode(takerTokenData, (IVelodromeRouter, VeloRoute));
VeloRoute[] memory routes = new VeloRoute[](1);
routes[0] = route;
return router.getAmountsOut(sellAmount, routes)[1];
}
/// @dev Returns whether the most liquid pool is a stable pool.
/// @param router Address of Velodrome router.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token buy amount for each sample (sorted in ascending order)
/// @return stable Whether the pool is a stable pool (vs volatile).
function _isMostLiquidPoolStablePool(
IVelodromeRouter router,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
) internal view returns (bool stable) {
uint256 numSamples = takerTokenAmounts.length;
(, stable) = router.getAmountOut(takerTokenAmounts[numSamples - 1], takerToken, makerToken);
}
}

View File

@@ -1,44 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
interface IBalancer {
function isBound(address t) external view returns (bool);
function getDenormalizedWeight(address token) external view returns (uint256);
function getBalance(address token) external view returns (uint256);
function getSwapFee() external view returns (uint256);
function calcOutGivenIn(
uint256 tokenBalanceIn,
uint256 tokenWeightIn,
uint256 tokenBalanceOut,
uint256 tokenWeightOut,
uint256 tokenAmountIn,
uint256 swapFee
) external pure returns (uint256 tokenAmountOut);
function calcInGivenOut(
uint256 tokenBalanceIn,
uint256 tokenWeightIn,
uint256 tokenBalanceOut,
uint256 tokenWeightOut,
uint256 tokenAmountOut,
uint256 swapFee
) external pure returns (uint256 tokenAmountIn);
}

View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
/// @dev Minimal Balancer V2 Vault interface
/// for documentation refer to https://github.com/balancer-labs/balancer-core-v2/blob/master/contracts/vault/interfaces/IVault.sol
interface IBalancerV2Vault {
enum SwapKind { GIVEN_IN, GIVEN_OUT }
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
struct BalancerV2PoolInfo {
bytes32 poolId;
address vault;
}
function queryBatchSwap(
SwapKind kind,
BatchSwapStep[] calldata swaps,
address[] calldata assets,
FundManagement calldata funds
) external returns (int256[] memory assetDeltas);
}

View File

@@ -1,33 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
interface IBancor {}
interface IBancorNetwork {
function conversionPath(address _sourceToken, address _targetToken) external view returns (address[] memory);
function rateByPath(address[] memory _path, uint256 _amount) external view returns (uint256);
}
interface IBancorRegistry {
function getAddress(bytes32 _contractName) external view returns (address);
function BANCOR_NETWORK() external view returns (bytes32);
}

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
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.
@@ -18,21 +18,26 @@
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
interface IBancorV3 {
interface IMooniswapRegistry {
/**
* @dev returns the output amount when trading by providing the source amount
*/
function tradeOutputBySourceAmount(
address sourceToken,
address targetToken,
uint256 sourceAmount
) external view returns (uint256);
function pools(address token1, address token2) external view returns(address);
}
/**
* @dev returns the input amount when trading by providing the target amount
*/
function tradeInputByTargetAmount(
address sourceToken,
address targetToken,
uint256 targetAmount
) external view returns (uint256);
interface IMooniswap {
function getReturn(
address fromToken,
address destToken,
uint256 amount
)
external
view
returns(uint256 returnAmount);
}
}

View File

@@ -1,72 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
// solhint-disable func-name-mixedcase
interface ICurve {
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
/// This function exists on later versions of Curve (USDC/DAI/USDT)
/// @param i The token index being sold.
/// @param j The token index being bought.
/// @param sellAmount The amount of token being bought.
/// @param minBuyAmount The minimum buy amount of the token being bought.
function exchange_underlying(
int128 i,
int128 j,
uint256 sellAmount,
uint256 minBuyAmount
)
external;
/// @dev Get the amount of `toToken` by selling `sellAmount` of `fromToken`
/// @param i The token index being sold.
/// @param j The token index being bought.
/// @param sellAmount The amount of token being bought.
function get_dy_underlying(
int128 i,
int128 j,
uint256 sellAmount
)
external
returns (uint256 dy);
/// @dev Get the amount of `fromToken` by buying `buyAmount` of `toToken`
/// This function exists on later versions of Curve (USDC/DAI/USDT)
/// @param i The token index being sold.
/// @param j The token index being bought.
/// @param buyAmount The amount of token being bought.
function get_dx_underlying(
int128 i,
int128 j,
uint256 buyAmount
)
external
returns (uint256 dx);
/// @dev Get the underlying token address from the token index
/// @param i The token index.
function underlying_coins(
int128 i
)
external
returns (address tokenAddress);
}

View File

@@ -0,0 +1,23 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
interface IGMX {
function getMaxAmountIn(IVault _vault, address _tokenIn, address _tokenOut)
external
view
returns (uint256);
function getAmountOut(IVault _vault, address _tokenIn, address _tokenOut, uint256 _amountIn)
external
view
returns (uint256, uint256);
}
interface IVault {
function getFeeBasisPoints(address _token, uint256 _usdgDelta, uint256 _feeBasisPoints, uint256 _taxBasisPoints, bool _increment) external view returns (uint256);
function stableSwapFeeBasisPoints() external view returns (uint256);
function stableTokens(address _token) external view returns (bool);
function tokenDecimals(address _token) external view returns (uint256);
function getMaxPrice(address _token) external view returns (uint256);
function getMinPrice(address _token) external view returns (uint256);
}

View File

@@ -1,96 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
// Keepin everything together
interface IKyberNetwork {
}
interface IKyberNetworkProxy {
function getExpectedRateAfterFee(
address src,
address dest,
uint256 srcQty,
uint256 platformFeeBps,
bytes calldata hint
)
external
view
returns (uint256 expectedRate);
}
interface IKyberHintHandler {
enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
enum ProcessWithRate {NotRequired, Required}
function getTradingReserves(
address tokenSrc,
address tokenDest,
bool isTokenToToken,
bytes calldata hint
)
external
view
returns (
bytes32[] memory reserveIds,
uint256[] memory splitValuesBps,
ProcessWithRate processWithRate
);
function buildTokenToEthHint(
address tokenSrc,
TradeType tokenToEthType,
bytes32[] calldata tokenToEthReserveIds,
uint256[] calldata tokenToEthSplits
)
external
view
returns (bytes memory hint);
function buildEthToTokenHint(
address tokenDest,
TradeType ethToTokenType,
bytes32[] calldata ethToTokenReserveIds,
uint256[] calldata ethToTokenSplits
)
external
view
returns (bytes memory hint);
function buildTokenToTokenHint(
address tokenSrc,
TradeType tokenToEthType,
bytes32[] calldata tokenToEthReserveIds,
uint256[] calldata tokenToEthSplits,
address tokenDest,
TradeType ethToTokenType,
bytes32[] calldata ethToTokenReserveIds,
uint256[] calldata ethToTokenSplits
)
external
view
returns (bytes memory hint);
}

View File

@@ -1,33 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
interface IMStable {
function getSwapOutput(
address _input,
address _output,
uint256 _quantity
)
external
view
returns (uint256 swapOutput);
}

View File

@@ -1,59 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
interface IMultiBridge {
/// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`.
/// @param tokenAddress The address of the ERC20 token to transfer.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
/// @param bridgeData Arbitrary asset data needed by the bridge contract.
/// @return success The magic bytes `0xdc1600f3` if successful.
function bridgeTransferFrom(
address tokenAddress,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
)
external
returns (bytes4 success);
/// @dev Quotes the amount of `makerToken` that would be obtained by
/// selling `sellAmount` of `takerToken`.
/// @param takerToken Address of the taker token (what to sell).
/// @param intermediateToken The address of the intermediate token to
/// use in an indirect route.
/// @param makerToken Address of the maker token (what to buy).
/// @param sellAmount Amount of `takerToken` to sell.
/// @return makerTokenAmount Amount of `makerToken` that would be obtained.
function getSellQuote(
address takerToken,
address intermediateToken,
address makerToken,
uint256 sellAmount
)
external
view
returns (uint256 makerTokenAmount);
}

View File

@@ -0,0 +1,11 @@
pragma solidity ^0.6;
interface IPlatypus {
function quotePotentialSwap(
address fromToken,
address toToken,
uint256 fromAmount
) external view returns (uint256 potentialOutcome, uint256 haircut);
function assetOf(address token) external view returns (address);
}

View File

@@ -1,43 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
interface IShell {
function viewOriginSwap (
address from,
address to,
uint256 fromAmount
)
external
view
returns (uint256 toAmount);
function viewTargetSwap (
address from,
address to,
uint256 toAmount
)
external
view
returns (uint256 fromAmount);
}

View File

@@ -1,52 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
interface IUniswapExchangeQuotes {
function getEthToTokenInputPrice(
uint256 ethSold
)
external
view
returns (uint256 tokensBought);
function getEthToTokenOutputPrice(
uint256 tokensBought
)
external
view
returns (uint256 ethSold);
function getTokenToEthInputPrice(
uint256 tokensSold
)
external
view
returns (uint256 ethBought);
function getTokenToEthOutputPrice(
uint256 ethBought
)
external
view
returns (uint256 tokensSold);
}

View File

@@ -1,34 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
interface IUniswapV2Router01 {
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}

View File

@@ -1,39 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
contract DummyLiquidityProvider
{
/// @dev Quotes the amount of `makerToken` that would be obtained by
/// selling `sellAmount` of `takerToken`.
/// @param sellAmount Amount of `takerToken` to sell.
/// @return makerTokenAmount Amount of `makerToken` that would be obtained.
function getSellQuote(
address, /* takerToken */
address, /* makerToken */
uint256 sellAmount
)
external
view
returns (uint256 makerTokenAmount)
{
makerTokenAmount = sellAmount - 1;
}
/// @dev Quotes the amount of `takerToken` that would need to be sold in
/// order to obtain `buyAmount` of `makerToken`.
/// @param buyAmount Amount of `makerToken` to buy.
/// @return takerTokenAmount Amount of `takerToken` that would need to be sold.
function getBuyQuote(
address, /* takerToken */
address, /* makerToken */
uint256 buyAmount
)
external
view
returns (uint256 takerTokenAmount)
{
takerTokenAmount = buyAmount + 1;
}
}

View File

@@ -1,455 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "../src/ERC20BridgeSampler.sol";
import "../src/interfaces/IKyberNetwork.sol";
import "../src/interfaces/IUniswapV2Router01.sol";
library LibDeterministicQuotes {
address private constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
uint256 private constant RATE_DENOMINATOR = 1 ether;
uint256 private constant MIN_RATE = RATE_DENOMINATOR / 100;
uint256 private constant MAX_RATE = 100 * RATE_DENOMINATOR;
uint8 private constant MIN_DECIMALS = 4;
uint8 private constant MAX_DECIMALS = 20;
function getDeterministicSellQuote(
bytes32 salt,
address sellToken,
address buyToken,
uint256 sellAmount
)
internal
pure
returns (uint256 buyAmount)
{
uint256 sellBase = uint256(10) ** getDeterministicTokenDecimals(sellToken);
uint256 buyBase = uint256(10) ** getDeterministicTokenDecimals(buyToken);
uint256 rate = getDeterministicRate(salt, sellToken, buyToken);
return sellAmount * rate * buyBase / sellBase / RATE_DENOMINATOR;
}
function getDeterministicBuyQuote(
bytes32 salt,
address sellToken,
address buyToken,
uint256 buyAmount
)
internal
pure
returns (uint256 sellAmount)
{
uint256 sellBase = uint256(10) ** getDeterministicTokenDecimals(sellToken);
uint256 buyBase = uint256(10) ** getDeterministicTokenDecimals(buyToken);
uint256 rate = getDeterministicRate(salt, sellToken, buyToken);
return buyAmount * RATE_DENOMINATOR * sellBase / rate / buyBase;
}
function getDeterministicTokenDecimals(address token)
internal
pure
returns (uint8 decimals)
{
if (token == WETH_ADDRESS) {
return 18;
}
bytes32 seed = keccak256(abi.encodePacked(token));
return uint8(uint256(seed) % (MAX_DECIMALS - MIN_DECIMALS)) + MIN_DECIMALS;
}
function getDeterministicRate(bytes32 salt, address sellToken, address buyToken)
internal
pure
returns (uint256 rate)
{
bytes32 seed = keccak256(abi.encodePacked(salt, sellToken, buyToken));
return uint256(seed) % (MAX_RATE - MIN_RATE) + MIN_RATE;
}
}
contract TestDeploymentConstants {
// solhint-disable separate-by-one-line-in-contract
// Mainnet addresses ///////////////////////////////////////////////////////
/// @dev Mainnet address of the WETH contract.
address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
/// @dev Overridable way to get the WETH address.
/// @return wethAddress The WETH address.
function _getWethAddress()
internal
view
returns (address wethAddress)
{
return WETH_ADDRESS;
}
}
contract FailTrigger {
// Give this address a balance to force operations to fail.
address payable constant public FAILURE_ADDRESS = 0xe9dB8717BC5DFB20aaf538b4a5a02B7791FF430C;
// Funds `FAILURE_ADDRESS`.
function enableFailTrigger() external payable {
FAILURE_ADDRESS.transfer(msg.value);
}
function _revertIfShouldFail() internal view {
if (FAILURE_ADDRESS.balance != 0) {
revert("FAIL_TRIGGERED");
}
}
}
contract TestERC20BridgeSamplerUniswapExchange is
IUniswapExchangeQuotes,
TestDeploymentConstants,
FailTrigger
{
bytes32 constant private BASE_SALT = 0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab;
address public tokenAddress;
bytes32 public salt;
constructor(address _tokenAddress) public {
tokenAddress = _tokenAddress;
salt = keccak256(abi.encodePacked(BASE_SALT, _tokenAddress));
}
// Deterministic `IUniswapExchangeQuotes.getEthToTokenInputPrice()`.
function getEthToTokenInputPrice(
uint256 ethSold
)
override
external
view
returns (uint256 tokensBought)
{
_revertIfShouldFail();
return LibDeterministicQuotes.getDeterministicSellQuote(
salt,
tokenAddress,
_getWethAddress(),
ethSold
);
}
// Deterministic `IUniswapExchangeQuotes.getEthToTokenOutputPrice()`.
function getEthToTokenOutputPrice(
uint256 tokensBought
)
override
external
view
returns (uint256 ethSold)
{
_revertIfShouldFail();
return LibDeterministicQuotes.getDeterministicBuyQuote(
salt,
_getWethAddress(),
tokenAddress,
tokensBought
);
}
// Deterministic `IUniswapExchangeQuotes.getTokenToEthInputPrice()`.
function getTokenToEthInputPrice(
uint256 tokensSold
)
override
external
view
returns (uint256 ethBought)
{
_revertIfShouldFail();
return LibDeterministicQuotes.getDeterministicSellQuote(
salt,
tokenAddress,
_getWethAddress(),
tokensSold
);
}
// Deterministic `IUniswapExchangeQuotes.getTokenToEthOutputPrice()`.
function getTokenToEthOutputPrice(
uint256 ethBought
)
override
external
view
returns (uint256 tokensSold)
{
_revertIfShouldFail();
return LibDeterministicQuotes.getDeterministicBuyQuote(
salt,
_getWethAddress(),
tokenAddress,
ethBought
);
}
}
contract TestERC20BridgeSamplerUniswapV2Router01 is
IUniswapV2Router01,
TestDeploymentConstants,
FailTrigger
{
bytes32 constant private SALT = 0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1;
// Deterministic `IUniswapV2Router01.getAmountsOut()`.
function getAmountsOut(uint256 amountIn, address[] calldata path)
override
external
view
returns (uint256[] memory amounts)
{
require(path.length >= 2, "PATH_TOO_SHORT");
_revertIfShouldFail();
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i = 0; i < path.length - 1; ++i) {
amounts[i + 1] = LibDeterministicQuotes.getDeterministicSellQuote(
SALT,
path[i],
path[i + 1],
amounts[i]
);
}
}
// Deterministic `IUniswapV2Router01.getAmountsInt()`.
function getAmountsIn(uint256 amountOut, address[] calldata path)
override
external
view
returns (uint256[] memory amounts)
{
require(path.length >= 2, "PATH_TOO_SHORT");
_revertIfShouldFail();
amounts = new uint256[](path.length);
amounts[path.length - 1] = amountOut;
for (uint256 i = path.length - 1; i > 0; --i) {
amounts[i - 1] = LibDeterministicQuotes.getDeterministicBuyQuote(
SALT,
path[i - 1],
path[i],
amounts[i]
);
}
}
}
// solhint-disable space-after-comma
contract TestERC20BridgeSamplerKyberNetwork is
TestDeploymentConstants,
FailTrigger
{
bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
enum ProcessWithRate {NotRequired, Required}
// IKyberHintHandler
function buildTokenToEthHint(
address tokenSrc,
TradeType /* tokenToEthType */,
bytes32[] calldata /* tokenToEthReserveIds */,
uint256[] calldata /* tokenToEthSplits */
) external view returns (bytes memory hint)
{
return abi.encode(tokenSrc);
}
function buildEthToTokenHint(
address tokenDest,
TradeType /* ethToTokenType */,
bytes32[] calldata /* ethToTokenReserveIds */,
uint256[] calldata /* ethToTokenSplits */
) external view returns (bytes memory hint)
{
return abi.encode(tokenDest);
}
// IKyberHintHandler
function buildTokenToTokenHint(
address tokenSrc,
TradeType /* tokenToEthType */,
bytes32[] calldata /* tokenToEthReserveIds */,
uint256[] calldata /* tokenToEthSplits */,
address /* tokenDest */,
TradeType /* EthToTokenType */,
bytes32[] calldata /* EthToTokenReserveIds */,
uint256[] calldata /* EthToTokenSplits */
) external view returns (bytes memory hint)
{
return abi.encode(tokenSrc);
}
// IKyberHintHandler
function getTradingReserves(
address tokenSrc,
address tokenDest,
bool isTokenToToken,
bytes calldata hint
)
external
view
returns (
bytes32[] memory reserveIds,
uint256[] memory splitValuesBps,
ProcessWithRate processWithRate
)
{
reserveIds = new bytes32[](1);
reserveIds[0] = bytes32(uint256(1));
splitValuesBps = new uint256[](0);
processWithRate = ProcessWithRate.NotRequired;
}
// Deterministic `IKyberNetworkProxy.getExpectedRateAfterFee()`.
function getExpectedRateAfterFee(
address fromToken,
address toToken,
uint256 /* srcQty */,
uint256 /* fee */,
bytes calldata /* hint */
)
external
view
returns
(uint256 expectedRate)
{
_revertIfShouldFail();
fromToken = fromToken == ETH_ADDRESS ? _getWethAddress() : fromToken;
toToken = toToken == ETH_ADDRESS ? _getWethAddress() : toToken;
expectedRate = LibDeterministicQuotes.getDeterministicRate(
SALT,
fromToken,
toToken
);
}
// Deterministic `IKyberNetworkProxy.getExpectedRate()`.
function getExpectedRate(
address fromToken,
address toToken,
uint256
)
external
view
returns (uint256 expectedRate, uint256)
{
_revertIfShouldFail();
fromToken = fromToken == ETH_ADDRESS ? _getWethAddress() : fromToken;
toToken = toToken == ETH_ADDRESS ? _getWethAddress() : toToken;
expectedRate = LibDeterministicQuotes.getDeterministicRate(
SALT,
fromToken,
toToken
);
}
}
contract TestERC20BridgeSamplerUniswapExchangeFactory is
IUniswapExchangeFactory
{
mapping (address => IUniswapExchangeQuotes) private _exchangesByToken;
// Creates Uniswap exchange contracts for tokens.
function createTokenExchanges(address[] calldata tokenAddresses)
external
{
for (uint256 i = 0; i < tokenAddresses.length; i++) {
address tokenAddress = tokenAddresses[i];
_exchangesByToken[tokenAddress] =
new TestERC20BridgeSamplerUniswapExchange(tokenAddress);
}
}
// `IUniswapExchangeFactory.getExchange()`.
function getExchange(address tokenAddress)
override
external
view
returns (address)
{
return address(_exchangesByToken[tokenAddress]);
}
}
contract TestERC20BridgeSampler is
ERC20BridgeSampler,
FailTrigger
{
TestERC20BridgeSamplerUniswapExchangeFactory public uniswap;
TestERC20BridgeSamplerUniswapV2Router01 public uniswapV2Router;
TestERC20BridgeSamplerKyberNetwork public kyber;
uint8 private constant MAX_ORDER_STATUS = uint8(IExchange.OrderStatus.CANCELLED) + 1;
constructor() public ERC20BridgeSampler() {
uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory();
uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01();
kyber = new TestERC20BridgeSamplerKyberNetwork();
}
// Creates Uniswap exchange contracts for tokens.
function createTokenExchanges(address[] calldata tokenAddresses)
external
{
uniswap.createTokenExchanges(tokenAddresses);
}
// Overridden to return deterministic states.
function getLimitOrderFillableTakerAmount(
IExchange.LimitOrder memory order,
IExchange.Signature memory,
IExchange
)
override
public
view
returns (uint256 fillableTakerAmount)
{
return uint256(keccak256(abi.encode(order.salt))) % order.takerAmount;
}
// Overriden to return deterministic decimals.
function _getTokenDecimals(address tokenAddress)
override
internal
view
returns (uint8 decimals)
{
return LibDeterministicQuotes.getDeterministicTokenDecimals(tokenAddress);
}
}

View File

@@ -1,135 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "../src/NativeOrderSampler.sol";
import "../src/UtilitySampler.sol";
contract TestNativeOrderSamplerToken {
mapping (address => uint256) public balanceOf;
mapping (address => mapping(address => uint256)) public allowance;
function setBalanceAndAllowance(
address owner,
address spender,
uint256 balance,
uint256 allowance_
)
external
{
balanceOf[owner] = balance;
allowance[owner][spender] = allowance_;
}
}
contract TestNativeOrderSampler is
NativeOrderSampler,
UtilitySampler
{
uint8 private constant MAX_ORDER_STATUS = uint8(IExchange.OrderStatus.CANCELLED) + 1;
bytes32 private constant VALID_SIGNATURE_HASH = bytes32(hex"01");
function createTokens(uint256 count)
external
returns (TestNativeOrderSamplerToken[] memory tokens)
{
tokens = new TestNativeOrderSamplerToken[](count);
for (uint256 i = 0; i < count; ++i) {
tokens[i] = new TestNativeOrderSamplerToken();
}
}
function setTokenBalanceAndAllowance(
TestNativeOrderSamplerToken token,
address owner,
address spender,
uint256 balance,
uint256 allowance
)
external
{
token.setBalanceAndAllowance(owner, spender, balance, allowance);
}
// IExchange.getLimitOrderRelevantState()
function getLimitOrderRelevantState(
IExchange.LimitOrder memory order,
IExchange.Signature calldata signature
)
external
view
returns (
IExchange.OrderInfo memory orderInfo,
uint128 actualFillableTakerTokenAmount,
bool isSignatureValid
)
{
// The order salt determines everything.
orderInfo.orderHash = keccak256(abi.encode(order.salt));
if (uint8(order.salt) == 0xFF) {
orderInfo.status = IExchange.OrderStatus.FILLED;
} else {
orderInfo.status = IExchange.OrderStatus.FILLABLE;
}
isSignatureValid = signature.r == VALID_SIGNATURE_HASH;
// The expiration time is the filled taker asset amount.
orderInfo.takerTokenFilledAmount = uint128(order.expiry);
// Calculate how much is fillable in maker terms given the filled taker amount
uint256 fillableMakerTokenAmount = LibMathV06.getPartialAmountFloor(
uint256(
order.takerAmount
- orderInfo.takerTokenFilledAmount
),
uint256(order.takerAmount),
uint256(order.makerAmount)
);
// Take the min of the balance/allowance and the fillable maker amount
fillableMakerTokenAmount = LibSafeMathV06.min256(
fillableMakerTokenAmount,
_getSpendableERC20BalanceOf(order.makerToken, order.maker)
);
// Convert to taker terms
actualFillableTakerTokenAmount = LibMathV06.getPartialAmountCeil(
fillableMakerTokenAmount,
uint256(order.makerAmount),
uint256(order.takerAmount)
).safeDowncastToUint128();
}
function _getSpendableERC20BalanceOf(
IERC20TokenV06 token,
address owner
)
internal
view
returns (uint256)
{
return LibSafeMathV06.min256(
token.allowance(owner, address(this)),
token.balanceOf(owner)
);
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/asset-swapper",
"version": "16.51.0",
"version": "16.62.1",
"engines": {
"node": ">=6.12"
},
@@ -33,13 +33,26 @@
"generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
"contracts:gen": "contracts-gen generate",
"contracts:copy": "contracts-gen copy",
<<<<<<< HEAD
"publish:private": "yarn build && gitpkg publish"
=======
"publish:private": "yarn build && gitpkg publish",
"sampler-size": "jq .compilerOutput.evm.deployedBytecode.object -- test/generated-artifacts/ERC20BridgeSampler.json | echo $(( $(wc -c) / 2 - 1 ))"
"sampler-size": "jq .compilerOutput.evm.deployedBytecode.object -- test/generated-artifacts/ERC20BridgeSampler.json | echo $(( $(wc -c) / 2 - 1 ))",
"list:deps": "yarn lerna list -l"
>>>>>>> 9b131199a (add weth/eth wrap/unwrap support for bancorv3)
},
"config": {
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker",
"publicInterfaceContracts": "BalanceChecker,FakeTaker",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2Sampler|BancorSampler|CompoundSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|FakeTaker|IBalancer|IBancor|ICurve|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|KyberSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SmoothySampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler).json",
<<<<<<< HEAD
<<<<<<< HEAD
"abis": "./test/generated-artifacts/@(BalanceChecker|FakeTaker).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|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|NativeOrderSampler|PlatypusSampler|SamplerUtils|ShellSampler|SmoothySampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler).json",
>>>>>>> f5c486050 (added bancor mixin/sampler and started linking up with asset-swapper)
=======
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2BatchSampler|BalancerV2Common|BalancerV2Sampler|BancorSampler|BancorV3Sampler|CompoundSampler|CurveSampler|DODOSampler|DODOV2Sampler|ERC20BridgeSampler|FakeTaker|GMXSampler|IBalancer|IBalancerV2Vault|IBancor|IBancorV3|ICurve|IGMX|IMStable|IMooniswap|IMultiBridge|IPlatypus|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|NativeOrderSampler|PlatypusSampler|SamplerUtils|ShellSampler|SmoothySampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler|VelodromeSampler).json",
>>>>>>> 1cc59ab1a (feat: Add Velodrome support [TKR-432] (#494))
"postpublish": {
"assets": []
}
@@ -60,28 +73,35 @@
"dependencies": {
"@0x/assert": "^3.0.34",
"@0x/base-contract": "^6.5.0",
"@0x/contract-addresses": "^6.12.0",
"@0x/contract-wrappers": "^13.19.1",
"@0x/contracts-erc20": "^3.3.27",
"@0x/contracts-zero-ex": "^0.31.1",
"@0x/contract-addresses": "^6.16.0",
"@0x/contract-wrappers": "^13.20.4",
"@0x/contracts-erc20": "^3.3.32",
"@0x/contracts-zero-ex": "^0.35.0",
"@0x/dev-utils": "^4.2.14",
"@0x/json-schemas": "^6.4.4",
"@0x/neon-router": "^0.3.5",
"@0x/protocol-utils": "^1.11.1",
"@0x/protocol-utils": "^11.15.0",
"@0x/quote-server": "^6.0.6",
"@0x/types": "^3.3.6",
"@0x/typescript-typings": "^5.3.1",
"@0x/utils": "^6.5.3",
"@0x/web3-wrapper": "^7.6.5",
"@balancer-labs/sor": "0.3.2",
"@balancer-labs/sdk": "0.1.6",
"@bancor/sdk": "0.2.9",
"@ethersproject/abi": "^5.0.1",
"@ethersproject/address": "^5.0.1",
"@ethersproject/contracts": "^5.0.1",
"@ethersproject/providers": "^5.0.4",
"@ethersproject/strings": "^5.0.10",
<<<<<<< HEAD
"@open-rpc/client-js": "^1.7.1",
"axios": "^0.24.0",
"axios-mock-adapter": "^1.20.0",
=======
"axios": "^0.21.1",
"axios-mock-adapter": "^1.19.0",
"balancer-labs-sor-v1": "npm:@balancer-labs/sor@0.3.2",
>>>>>>> 4057bdab9 (Publish)
"cream-sor": "^0.3.3",
"decimal.js": "^10.2.0",
"ethereum-types": "^3.7.0",
@@ -98,10 +118,9 @@
"@0x/contracts-exchange": "^3.2.38",
"@0x/contracts-exchange-libs": "^4.3.37",
"@0x/contracts-gen": "^2.0.46",
"@0x/contracts-test-utils": "^5.4.18",
"@0x/contracts-utils": "^4.8.8",
"@0x/contracts-test-utils": "^5.4.23",
"@0x/contracts-utils": "^4.8.13",
"@0x/mesh-rpc-client": "^9.4.2",
"@0x/migrations": "^8.1.16",
"@0x/sol-compiler": "^4.8.1",
"@0x/subproviders": "^6.6.5",
"@0x/ts-doc-gen": "^0.0.28",
@@ -123,7 +142,7 @@
"tslint": "5.11.0",
"typedoc": "~0.16.11",
"typemoq": "^2.1.0",
"typescript": "4.2.2"
"typescript": "4.6.3"
},
"publishConfig": {
"access": "public"

View File

@@ -6,10 +6,8 @@
import { ContractArtifact } from 'ethereum-types';
import * as BalanceChecker from '../generated-artifacts/BalanceChecker.json';
import * as ERC20BridgeSampler from '../generated-artifacts/ERC20BridgeSampler.json';
import * as FakeTaker from '../generated-artifacts/FakeTaker.json';
export const artifacts = {
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
BalanceChecker: BalanceChecker as ContractArtifact,
FakeTaker: FakeTaker as ContractArtifact,
};

View File

@@ -1,4 +1,3 @@
import { ChainId } from '@0x/contract-addresses';
import { SignatureType } from '@0x/protocol-utils';
import { BigNumber, logUtils } from '@0x/utils';
@@ -11,12 +10,9 @@ import {
RfqRequestOpts,
SwapQuoteGetOutputOpts,
SwapQuoteRequestOpts,
SwapQuoterOpts,
} from './types';
import {
DEFAULT_GET_MARKET_ORDERS_OPTS,
DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID,
DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID,
} from './utils/market_operation_utils/constants';
const ETH_GAS_STATION_API_URL = 'https://ethgasstation.info/api/ethgasAPI.json';
@@ -28,6 +24,7 @@ const ONE_SECOND_MS = 1000;
const ONE_MINUTE_SECS = 60;
const ONE_MINUTE_MS = ONE_SECOND_MS * ONE_MINUTE_SECS;
const DEFAULT_PER_PAGE = 1000;
const ZERO_AMOUNT = new BigNumber(0);
const ALT_MM_IMPUTED_INDICATIVE_EXPIRY_SECONDS = 180;
const DEFAULT_ORDER_PRUNER_OPTS: OrderPrunerOpts = {
@@ -42,21 +39,6 @@ const PROTOCOL_FEE_MULTIPLIER = new BigNumber(0);
// default 50% buffer for selecting native orders to be aggregated with other sources
const MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE = 0.5;
export const ZERO_AMOUNT = new BigNumber(0);
const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = {
chainId: ChainId.Mainnet,
orderRefreshIntervalMs: 10000, // 10 seconds
...DEFAULT_ORDER_PRUNER_OPTS,
samplerGasLimit: 500e6,
ethGasStationUrl: ETH_GAS_STATION_API_URL,
rfqt: {
integratorsWhitelist: [],
makerAssetOfferings: {},
txOriginBlacklist: new Set(),
},
tokenAdjacencyGraph: DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID[ChainId.Mainnet],
};
const DEFAULT_EXCHANGE_PROXY_EXTENSION_CONTRACT_OPTS: ExchangeProxyContractOpts = {
isFromETH: false,
isToETH: false,
@@ -91,8 +73,6 @@ export const DEFAULT_WARNING_LOGGER: LogFunction = (obj, msg) =>
const EMPTY_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000';
export const INVALID_SIGNATURE = { signatureType: SignatureType.Invalid, v: 1, r: EMPTY_BYTES32, s: EMPTY_BYTES32 };
export { DEFAULT_FEE_SCHEDULE, DEFAULT_GAS_SCHEDULE } from './utils/market_operation_utils/constants';
export const POSITIVE_SLIPPAGE_FEE_TRANSFORMER_GAS = new BigNumber(30000);
// tslint:disable-next-line: custom-no-magic-numbers
@@ -111,8 +91,6 @@ export const constants = {
ONE_AMOUNT: new BigNumber(1),
ONE_SECOND_MS,
ONE_MINUTE_MS,
DEFAULT_SWAP_QUOTER_OPTS,
DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID,
DEFAULT_SWAP_QUOTE_REQUEST_OPTS,
DEFAULT_EXCHANGE_PROXY_SWAP_QUOTE_GET_OPTS,
DEFAULT_EXCHANGE_PROXY_EXTENSION_CONTRACT_OPTS,

View File

@@ -109,6 +109,7 @@ export {
SwapQuoteGetOutputOpts,
SwapQuoteInfo,
SwapQuoteOrdersBreakdown,
SwapQuoteMultiHopBreakdown,
SwapQuoteRequestOpts,
SwapQuoterError,
SwapQuoterOpts,
@@ -116,49 +117,43 @@ export {
SamplerMetrics,
} from './types';
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
export {
<<<<<<< HEAD
=======
IRfqClient,
RfqClientV1Price,
RfqClientV1PriceRequest,
RfqClientV1PriceResponse,
RfqClientV1Quote,
RfqClientV1QuoteRequest,
RfqClientV1QuoteResponse,
} from './utils/irfq_client';
export {
DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID,
DEFAULT_GAS_SCHEDULE,
>>>>>>> a7f23a982 (feat: add IRfqClient (#467))
SOURCE_FLAGS,
BUY_SOURCE_FILTER_BY_CHAIN_ID,
SELL_SOURCE_FILTER_BY_CHAIN_ID,
NATIVE_FEE_TOKEN_BY_CHAIN_ID,
} from './utils/market_operation_utils/constants';
export {
Parameters,
SamplerContractCall,
SamplerContractOperation,
} from './utils/market_operation_utils/sampler_contract_operation';
export {
BalancerFillData,
BancorFillData,
CollapsedFill,
CurveFillData,
CurveFunctionSelectors,
CurveInfo,
DexSample,
DODOFillData,
ERC20BridgeSource,
ExchangeProxyOverhead,
FeeSchedule,
Fill,
FillData,
GetMarketOrdersRfqOpts,
KyberFillData,
<<<<<<< HEAD
=======
LiquidityProviderFillData,
>>>>>>> 2d16f83e3 (Offboard/clean up Oasis, CoFix, and legacy Kyber [TKR-405] (#482))
LiquidityProviderRegistry,
MarketDepth,
MarketDepthSide,
MooniswapFillData,
MultiHopFillData,
NativeCollapsedFill,
NativeRfqOrderFillData,
NativeLimitOrderFillData,
NativeFillData,
OptimizedMarketOrder,
SourceQuoteOperation,
TokenAdjacencyGraph,
UniswapV2FillData,
} from './utils/market_operation_utils/types';
export { ProtocolFeeUtils } from './utils/protocol_fee_utils';
export {
@@ -177,7 +172,7 @@ export {
PriceComparisonsReport,
} from './utils/quote_report_generator';
export { QuoteRequestor, V4RFQIndicativeQuoteMM } from './utils/quote_requestor';
export { ERC20BridgeSamplerContract, BalanceCheckerContract, FakeTakerContract } from './wrappers';
export { BalanceCheckerContract, FakeTakerContract } from './wrappers';
import { ERC20BridgeSource } from './utils/market_operation_utils/types';
export type Native = ERC20BridgeSource.Native;
export type MultiHop = ERC20BridgeSource.MultiHop;

Some files were not shown because too many files have changed in this diff Show More